ADEO Dev Summit

Fin juin avait lieu Adeo Dev Summit, événement autour du développement organisé au sein du groupe Adeo. L’occasion de rassembler les personnes de l’IT des différentes entités du groupe au niveau mondial (France, Russie, Brésil, Grèce…) 4 jours durant lesquels se sont succédés conférences, codelabs et keynotes dédiés aux techniciens : on a parlé frameworks, architecture, déploiement, méthodologies, open/inner source…
On ne va pas faire ici un résumé complet, mais on a assisté à des talks de qualité que ce soit par des speakers « internes » Adeo ou du beau monde venu de l’extérieur (booking.com, github, google, confluent/kafka, traefik, …)., ainsi que des ateliers pour tous les goûts.
La keynote de fermeture nous a permis d’écouter Dirk-Willem van Gulik, un des fondateurs et ancien président de la fondation Apache, sans qui notre métier serait probablement assez différent aujourd’hui. Un grand moment.

De mon côté j’ai suivi un atelier sur le langage Go, vu une première approche pratique du serverless / Function-as-a-service, découvert les outils Skaffold et Bazel pour gérer le déploiement de briques hétérogènes dans Kubernetes, …
J’ai également participé activement : j’ai donné un talk sur les micro-services appliqués à la vraie vie, et j’ai animé des codelabs sur la programmation réactive dans Spring et les microservices en java avec RabbitMq et Spring cloud stream.
Le tout dans la langue de Shakespeare…
Cela a été une super expérience à tout point de vue. L’événement en lui-même, organisé en très peu de temps, a été une énorme réussite que ce soit au niveau de l’organisation, la qualité des intervenants, et la diversité des thèmes abordés.

Plus généralement cela m’a inspiré quelques réflexions sur le passé et le présent de notre métier…
Nous avons depuis longtemps la conviction

  • Que le développeur a quelque chose de différenciant, une plus-value à apporter dans les produits auxquels il participe.
  • Que l’on ne peut pas remplacer sans réfléchir un développeur A par un développeur B.
  • Que l’on devrait parler de personnes et non de ressources.
  • Que travailler main dans la main avec son client et son utilisateur est bien plus rentable sur le long terme que d’envoyer le développement se faire dans un centre de service à l’autre bout du monde.

La bonne nouvelle, c’est qu’aujourd’hui cette conviction est non seulement partagée, mais est partie intégrante de la culture des services informatiques des entreprises (que l’on évoque des entreprises très centrées sur leur IT ou non).
Et ce genre d’événement le démontre !
L’approche DevOps, les méthodologies Agile, le software craftsmanship, sont autant d’éléments qui rappellent que le développeur a aujourd’hui un rôle fondamental à jouer.

Il y a 10 ou 15 ans, le terme même de « développement » avait une certaine connotation négative.
Dans beaucoup d’esprits, c’était plutôt pour les juniors !
Dans cette vision, la voie normale de carrière était : obtention du diplôme > développeur (pas trop longtemps) > chef de projet > manager.
Bien sûr c’est un peu caricatural mais reflète une certaine réalité de l’époque.
Il semble que ce temps soit révolu.
Aujourd’hui le développeur ne doit pas uniquement coder :

  • Il participe aux réflexions avec les utilisateurs,
  • Il est responsable des tests, du déploiement sur les environnements distants, de l’intégration continue, du run.
  • Il explique régulièrement ce que fait le produit.
  • Il prouve que ça fonctionne.
  • Il partage ses pratiques avec les autres équipes de développement.

Bref, le technicien a gagné ses lettres de noblesse. A eux, à nous, de continuer à faire avancer les choses et les mentalités.
Le changement de mindset a opéré, enfin, le train est en marche.

En conclusion, un grand bravo à Adeo pour cette initiative ! Ce n’est que le début !

Alexandre Vandekerkhove

PS : Merci à Florian Petit pour la photo !

On était au Devfest 2018 – IMT Lille Douai

Le 21 Juin 2018 avait lieu le devfest 2018 à l’IMT Lille Douai. Il s’agit d’une journée de conférences, codelabs autour de sujets technologiques innovants.

Tout démarre par une keynote d’Alexandra Nemery & Sarah Colmon. Elles ont su captiver l’auditoire avec un petit quizz interactif sur le thème des jeux vidéo sur kahoot.it. Elles ont ensuite tenté de faire le lien entre le monde de l’UX et celui des jeux vidéo, en prenant quelques exemples de jeux dont l’ergonomie n’est pas adaptée soit au device, soit aux habitudes des utilisateurs (joueurs). Et si Shigeru Miyamoto, célèbre créateur de Mario et Zelda, était le premier vrai visionnaire de l’UX ?

On a ensuite assisté à une introduction de gRPC par Sébastien FRIESS. Ce framework s’appuie sur le protocole HTTP/2 et utilise Protocol Buffers pour permettre d’échanger des données entre briques applicatives de façon performante. Sébastien nous a présenté le schéma de description des messages (IDL), puis une démo client/serveur. Il a apporté des modifications aux schémas de données à chaud, côté serveur puis côté client, pour démontrer que les échanges n’étaient pas impactés.

Sébastien Pertus nous a présenté les modules dans EcmaScript 6 et nous a également parler de TypeScript. Il a d’abord fait un historique et un focus sur Node.js puis nous a présenté sous forme de démos l’utilisation des modules dans les navigateurs.

Alexis Hassler nous a fait une revue de HTTP/2 et de son support dans les navigateurs, frameworks web, serveurs d’applications… La démo d’Alexis nous a permis de constater l’efficacité du multiplexage (utilisation de la même connexion tcp) de HTTP/2 sur le chargement de plusieurs éléments d’une page web. Il nous a également parler de la compression des headers http et du « server push » qui permet au serveur de pousser des ressources avant même qu’elles soient demandées par le client. On a pu apprendre que le support d’HTTP/2 est assez hétérogène et que l’utilisation du « server push » n’est pas forcément très simple pour le moment et nécessite de vérifier toutes les briques (reverse proxy, …) séparant le client du serveur.

On a vu différentes méthodes pour protéger ses API avec Léo Unbekandt. Les « API tokens » sont parfaits pour débuter rapidement et sont simples mais ne sont pas idéaux dans un écosystème distribué. Oauth 2 permet d’utiliser un vrai standard partagé mais implique beaucoup de complexité et d’appels client/serveur, cela reste néanmoins une excellente méthode pour faire de la délégation d’identité. Les tokens JWT peuvent être une bonne alternative dans le sens où le token peut être directement validé par le serveur sans appel supplémentaire, les jetons étant signés avec une clé privée connue du serveur.

Christophe Furmaniak & Yoan Rousseau, nous ont parlé de monitoring et d’alerting dans des environnements conteneurisés. Ils ont présenté l’outil de monitoring Prometheus dont le principe est de collecter les métriques en mode PULL dont l’un des principaux avantages est que les applications n’ont pas connaissance de l’infrastructure de monitoring, ce qui simplifie la configuration. Les applications ont tout de même la possibilité de venir Pusher des métriques via un composant intermédiaire que Prometheus utilisera pour collecter la donnée. Il nous ont également montré l’utilisation de Grafana qui permet la visualisation et la mise en forme des métriques collectées par Prometheus. Enfin, la problématique de mise en cluster de Prometheus a été rapidement abordée, le projet Thanos a été mentionné pour répondre à ce besoin. Nous pouvons conclure que Prometheus est adapté pour le monitoring mais n’est pas fait pour stocker des logs ou des événements, il n’est pas fait non plus pour tracer les requêtes dans une architecture microservices où il faudra utiliser des outils comme OpenTracing / Zipkin.

Le composant Istio nous a été présenté par David Gageot. Istio permet d’appliquer le pattern « façade » (ou sidecar) à son architecture micro-services au sein d’un environnement Kubernetes : un proxy HTTP Envoy est adossé à chaque micro-service, ce qui permet d’ajouter des traces, de monitorer, sans rien modifier dans son code ou son déploiement. Istio permet également de faire du TLS automatiquement entre les services, de router le traffic plus finement… David nous a fait une démo de canary deployment où un fix a été déployé pour un seul utilisateur en fonction d’une entête HTTP. Puis il a effectué un blue/green deployment, avec un routage d’une partie des requêtes vers la nouvelle version de l’application et une bascule progressive. Malgré l’effet démo subi par le speaker, cette conférence était très intéressante et Istio est vraiment prometteur.

Aurélien Loyer et Nathan Damie nous ont parlé de Javascript et des frameworks Javascript web. On a eu droit à une petite séance de pair-programming en live sur les bindings en Javascript via le « framework » Vanilla 🙂 Le message de fond est de démarrer simplement avec du pur Javascript, bien comprendre et spécifier son (éventuelle) problématique, et ensuite choisir (ou non) un framework qui colle rééllement à cette problématique.

Au niveau de l’organisation, c’était excellent, très bien organisé et fluide. Il y avait toujours de la place à condition d’arriver à l’heure dans l’amphi (quelques uns ont fini sur les marches, des souvenirs de début d’année en fac..) C’est également l’occasion de recroiser de nombreuses têtes rencontrées au détour de missions dans la région 🙂 Les sponsors proposaient de nombreuses animations, baby foot, bornes d’arcade, etc. On regrettera juste des soucis récurrents avec le projecteur de l’amphithéâtre principal qui a occasionné quelques coupures et slides tronqués. Globalement les présentations étaient de qualité avec des speakers au niveau.

On reviendra avec plaisir l’année prochaine !

Alexandre Vandekerkhove et Maxime Decronambourg

Tests automatisés d’api avec Karate

Dans le cadre de nos projets, nous sommes régulièrement amenés à définir et à développer des API et des services REST.

Nous avons à plusieurs reprises fait le choix d’utiliser Karate pour réaliser des scénarios de tests automatisés sur ce type de projet.

Karate est idéal pour mettre au point rapidement une série de tests représentant des enchaînements d’appels de services REST, de plus il s’intègre parfaitement avec l’ outil d’intégration continue Jenkins.

Nous allons voir comment écrire et organiser des scénarios de tests avec Karate, ainsi que son intégration à Jenkins.

Posons le contexte

Pour illustrer la réalisation de tests automatisés avec Karate, prenons l’exemple d’une api permettant à un client d’acheter des produits et de payer via une de ses cartes de paiements.

Notre api permet donc à nos clients:

1 – de créer un panier

POST /carts

2 – d’ajouter des produits dans le panier

POST /carts/{{cartId}}/items
{
  "itemId": '#(itemId)'
}

3 – de modifier la quantité des produits du panier

PUT /carts/{{id}}/items/{{itemId}}
{
  "quantity": '#(quantity)'
}

4 – de consulter son panier

GET /carts/{{cartId}}

5 – de récupérer ses moyens de paiements

GET /carts/{{cartId}}/wallet

6 – de payer le panier

POST /carts/{{cartId}}/payment?cardId={{cardId}}

Réalisons les scénarios réutilisables

Pensons réutilisabilité et commençons par créer 6 fichiers feature contenant chacun un scénario correspondant à une requête vers notre api.

Pour chaque requête, nous enregistrons le code de retour http et la réponse afin de pouvoir y accéder ultérieurement.

1 – Créer un panier

Fichier: createCart.feature

Feature: API - createCart

  Scenario: create a cart
    When url BASE_URL + '/carts'
    And request {}
    And method post 
    * def statusCode = responseStatus
    * def body = $

Ce scénario effectue une requête http POST sur /carts

2 – Ajouter des produits dans le panier

Fichier: addItemToCart.feature

Feature: API - addItemToCart

  Scenario: add an item to a cart
    When url BASE_URL + '/carts/' + cartId + '/items'
    And request
    """
    {
      "itemId": '#(itemId)'
    }
    """
    And method post
    * def statusCode = responseStatus
    * def body = $

Ce scénario effectue une requête http POST sur /carts/{{cartId}}/items

Il a deux paramètres:

  • cartId: identifiant du panier
  • itemId: identifiant du produit à ajouter au panier

3 – Modifier la quantité des produits du panier

Fichier: updateCartQuantity.feature

Feature: API - updateCartQuantity

  Scenario: update cart item quantity
    When url BASE_URL + '/carts/' + cartId + '/items/' + itemId
    And request
    """
    {
      "quantity": '#(quantity)'
    }
    """
    And method put
    * def statusCode = responseStatus
    * def body = $

Ce scénario effectue une requête http PUT sur /carts/{{id}}/items/{{itemId}}

Il a trois paramètres:

  • cartId: identifiant du panier
  • itemId: identifiant du produit à mettre à jour
  • quantity: nouvelle quantité pour le produit à mettre à jour

4 – Consulter son panier

Fichier: retrieveCart.feature

Feature: API - retrieveCart

  Scenario: retrieve a cart
    When url BASE_URL + '/carts/' + cartId
    And request {}
    And method get
    * def statusCode = responseStatus
    * def body = $

Ce scénario effectue une requête http GET sur /carts/{{cartId}}

Il a un paramètre

  • cartId: identifiant du panier

5 – Récupérer ses moyens de paiements

Fichier: getWallet.feature

Feature: API - getWallet

  Scenario: get wallet
    When url BASE_URL + '/carts/' + cartId + '/wallet'
    And request {}
    And method get
    * def statusCode = responseStatus
    * def body = $

Ce scénario effectue une requête http GET sur la ressource /carts/{{cartId}}/wallet

Il a un paramètre

  • cartId: identifiant du panier

6 – Payer le panier

Fichier: postPayment.feature

Feature: API - postPayment

  Scenario: Pay a cart
    When url BASE_URL + '/carts/' + cartId + '/payment'
    And param cardId = cardId
    And request {}
    And method post
    * def statusCode = responseStatus
    * def body = $

Ce scénario effectue une requête http POST sur /carts/{{cartId}}/payment

Il a deux paramètres

  • cartId: identifiant du panier
  • cardId: identifiant de la carte de paiement

Réalisons les scénarios de tests

Commençons par créer un nouveau fichier « feature » avec un block « Background » permettant de rejouer des instructions avant chaque scénario. Ici les instructions du block « Background » correspondent à la création d’un panier. Nous utilisons l’instruction call pour réutiliser les scénarios précédemment créés. Afin que l’identifiant du panier soit visible dans tous les scénarios, nous l’enregistons dans une variable cartId.

Feature: API

  Background:
    When def createCartResult = call read(createCart)
    Then match createCartResult.statusCode == 200
    * def cartId = createCartResult.body.id

Ajoutons un scénario qui vérifie simplement la bonne création d’un panier. La création du panier est effectuée dans le block Background, il est donc inutile de répéter cette opération dans le scénario.

  Scenario: Create a cart
    Then match createCartResult.body.status == 'IN_PROGRESS'
    And match createCartResult.body.items == []

Ajoutons un scénario qui teste la consultation d’un panier. Un nouveau panier est créé avant l’exécution du scénario grâce aux instructions du block Background

  Scenario: Retrieve a cart
    When def r = call read(retrieveCart)
    Then match r.statusCode == 200
    And match r.body.status == 'IN_PROGRESS'

Ajoutons un scénario qui vérifie l’ajout d’un article dans un panier.

  Scenario: add an item
    When def r = call read(addItemToCart) { itemId: 'XXX' }
    Then match r.statusCode == 200
    And match r.body.status == 'IN_PROGRESS'
    And match r.body.items[0].itemId == 'XXX'

Ajoutons un scénario qui ajoute un article au panier et vérifie la mise à jour de la quantité

  Scenario: add an item and update its quantity
    When def addItemToCartResult = call read(addItemToCart) { itemId: 'XXX' }
    Then match addItemToCartResult.statusCode == 200

    When def r = call read(updateCartQuantity) { itemId: '#(addItemToCartResult.body.items[0].itemId)', quantity: 3 }   
    Then match r.statusCode == 200
    And match r.body.status == 'IN_PROGRESS'
    And match r.body.items[0].quantity == 3

Ajoutons un dernier scénario qui ajoute un produit dans un panier, récupère une carte de paiement, utilise cette carte pour payer, vérifie l’état du panier et la création d’un ticket.

  Scenario: Pay a cart with a card
    # add an item to cart
    When def addItemToCartResult = call read(addItemToCart) { itemId: 'XXX' }
    Then match addItemToCartResult.statusCode == 200

    # retrieve a card
    When def getWalletResult = call read(getWallet)
    Then match getWalletResult.statusCode == 200
    * def cardId = getWalletResult.items[0].id

    # pay
    When def r = call read(postPayment) { cardId: '#(cardId)' }
    Then match r.statusCode == 200
    And match r.body.status == 'PAYMENT'
    And match r.body.payment == 
    """
    {
      "id": '#string',
      "creationDate": '#string',
      "status": "SUCCESS"
    """

    # check status FINISHED and ticket is available
    When def r = call read(retrieveCart)
    Then match r.statusCode == 200
    And match r.body.status == 'FINISHED'
    And match r.body.ticket == { ticketNumber: '#string', creationDate: '#string' }

Intégration avec Jenkins

Le plugin Cucumber Reports permet d’intégrer facilement nos scénarios Karate à Jenkins.

En utilisant un jenkins pipeline, il suffit d’ajouter dans son Jenkinsfile après son build:

cucumber fileIncludePattern: '**/target/surefire-reports/*.json'

Jenkins construira un reporting comme illustré ci-dessous:

karate-report1
karate-report2

Conclusion

Karate est un outil très efficace pour tester des api et des services rest.

Sa faculté à s’interfacer avec du code java et javascript est très utile pour ajouter des scripts et interagir avec d’autres outils comme Selenium Webdriver.

Enfin Karate reposant sur Cucumber, nous pouvons profiter des plugins Cucumber pour une intégration avec Jenkins.

Monitoring d’infrastructure avec la stack : Grafana – Telegraf – InfluxDb.

La mise en place du monitoring d’infrastructure est devenue essentielle pour écouter et surveiller ce qu’il se passe sur votre infrastructure (utilisation CPU, mémoire) ou le comportement des applications (Flux non envoyés, Build, Batch en échec, etc.).

Grâce à cela, on peut être plus réactif sur certaines anomalies et déclencher des actions en cas de problème.

Par exemple: Être alerté en cas d’utilisation anormale de CPU sur un serveur.

Dans le cadre d’une de nos missions en clientèle, nous avons mis en oeuvre une stack dédiée au Monitoring composée en plusieurs applications :

  • Grafana : Pour la présentation des informations de monitoring
  • Telegraf : Pour la collecte des données de monitoring
  • InfluxDb : Pour le stockage des données de monitoring

Cet article se propose de les décrire.

Grafana

Grafana

DashBoard Grafana

C’est un outil d’analyse des métriques et de dashboard. Il permet d’avoir une représentation des données à l’aide de différents graphiques.Un point fort de Grafana est qu’il est multi-datasource. Il est donc possible d’interroger une base InfluxDb, Graphique, ElasticSearch.

Une autre fonctionnalité importante de Grafana est l’Alerting. Il est, en effet, possible de notifier des anomalies lorsque des valeurs dépassent un certain seuil.

La notification peut se faire via plusieurs channels : Webhook – Mail – Slack etc…

InfluxDb

InfluxDb est un gestionnaire de base de données, open-source, orientée time-séries.

Il est conçu pour le stockage et la restitution de données de type métriques et événements et est développé par InfluxData (écrit en GO).

Telegraf

C’est un collecteur de données. Ces dernières sont récoltées de deux manières :

  • Soit en mode pull, dans ce cas, c’est Telegraf qui récupère la métrique.
  • Soit en mode push, la métrique est alors envoyée par une application via l’api exposée par Telegraf.

Chaque donnée récoltée est ensuite envoyée à InfluxDB.

L’application est décomposée en plugins ou chaque plugin permet de collecter une métrique en particulier.

Par exemple, un plugin permettant :

  • de faire du ping sur des serveurs,
  • de récupérer des infos depuis une base de données PostgersSQL,
  • d’obtenir les informations système d’un serveur,
  • etc…

Autres Outils

D’autres outils peuvent s’interfacer à cette stack afin de compléter le monitoring :

  • JMXTrans : C’est également un collecteur de données. Par contre, comme son nom l’indique, il est orientée dans la récupération des infos via JMX (Info JVM Tomcat par exemple). Les infos collectées  sont envoyées à InfluxDB.
  • Kapacitor : C’est un moteur de règle qui permet de définir des règles de déclenchement d’alertes. En le branchant à InfluxDB, les alertes déclenchées par les règles pourront être stockées. Kapacitor propose deux modes de fonctionnement:
    • Stream ⇒ InfluxDB pousse à Kapacitor les infos reçues. Ce dernier vérifie si une alerte doit être déclenchée via les règles définies dans le moteur.
    • Batch ⇒ Kapacitor interroge périodiquement InfluxDB et déclenche l’alerte si nécessaire.

Les alertes sont ensuite notifiées via différents Channels : Slack, Mail, Application tierce.

  • Alerta : Application tierce permettant de lister et d’afficher les alertes reçues soit par Kapacitor mais également par Grafana.

Alertes dans Alerta

Schéma technique

Schéma technique

Déploiement

Il est très facile de monter rapidement  cette architecture sur son poste via Docker.

En effet, un container existant pour chaque application de la stack, un simple docker-compose.yml suffit à monter et démarrer l’ensemble.

Voici un exemple de fichier:

déploiement docker

Liens

Enfin, nous vous proposons les liens suivants qui vous permettrons d’aller plus loin :

Grafana : https://grafana.com/

Telegraf : https://docs.influxdata.com/telegraf

InfluxDb : https://docs.influxdata.com/influxdb

Continuous Documentation – Exemple de mise en place

Parmi les livrables d’un projet, la documentation est celle qui assurera sa pérennité. Dans le cadre d’une application, la documentation technique est la garante des fonctionnalités disponibles, de leurs usages mais aussi de son architecture, son intégration et son déploiement. Par conséquent, la documentation est vouée à vivre au rythme de l’évolution de l’application, et trouve naturellement sa place aux côtés du code source de l’application. Ainsi, quels sont les outils les plus adaptés à la rédaction de la documentation pour la faire cohabiter avec les sources ?

La documentation au plus proche du code source

Tout d’abord, certains outils de gestion de sources – tel que GitHub et GitLab – proposent des fonctionnalités dédiées à la documentation comme un wiki intégré et l’interprétation des fichiers MarkDown et AsciiDoc, deux formats de texte pour la rédaction de documentations. Ces formats simples on l’avantage d’être de simples fichiers textes et sont par conséquent facilement exploitable dans un outil de gestion de sources, contrairement aux formats Word et LibreOffice. L’emplacement de la documentation technique est alors idéale car au plus proche de l’application : elle pourra évoluer et être versionnée en même temps que le code.

Cependant, cela ne convient pas à tous les usages : le référentiel de codes est rarement ouvert à tous en entreprise, et la consultation de la documentation via GitHub ou GitLab n’est pas toujours le format le plus adapté pour la consulter ou la partager. C’est pourquoi, des formats plus traditionnels comme le HTML ou le PDF sont souvent plus pratiques à l’usage, à la publication, éventuellement pour l’impression ou encore pour un classement dans une GED.

A l’instar de HTML/CSS, les documents MarkDown et AsciiDoc peuvent servir à la génération d’un document plus lisible et esthétique aux formats HTML ou PDF par exemple. En outre, AsciiDoctor est un outil pour convertir les documents AsciiDoc vers HTML, PDF ou encore DocBook.

asciidoctor

Générer la documentation à la construction de l’application

Intégrer la génération de la documentation avec la construction de l’application garantie la livraison d’une documentation à chaque version. Dans cette optique, le plugin asciidoctor-maven-plugin convertit les documents AsciiDoc pour les projets Maven. Les projets Gradle ne sont pas en reste et disposent d’un plugin équivalent : asciidoctor-gradle-plugin.

En ce qui concerne le plugin Maven, son utilisation est des plus simple :

  • déclarer le plugin dans votre fichier pom.xml,
  • placer votre documentation asciidoc dans src/main/asciidoc.

La documentation sera alors générée dans target/generated-docs en même temps que la construction du projet.

Exemple d’utilisation du asciidoctor-maven-plugin:
<plugin>
  <groupId>org.asciidoctor</groupId>
  <artifactId>asciidoctor-maven-plugin</artifactId>
  <version>1.5.3</version>
  <executions>
    <execution>
      <id>generate-docs-html</id> <!-- <2> -->
      <phase>prepare-package</phase>
      <goals>
        <goal>process-asciidoc</goal>
      </goals>
      <configuration>
        <backend>html</backend>
        <doctype>book</doctype>
        <attributes>
          <snippets>${snippetsDirectory}</snippets>
        </attributes>
      </configuration>
    </execution>
  </executions>
</plugin>

<1> Dépendances requises pour supporter le PDF.
<2> La première exécution du plugin génère la documentation en HTML.
<3> La seconde exécution génère la documentation en PDF.

 

Documenter les API REST

La documentation d’une API est une partie des plus fastidieuses. En effet, celle-ci décrit l’utilisation de chaque services – que ce soit la requête attendue ou la réponse qui sera émise – et les différents cas d’usage. Un travail d’autant plus pénible que les contrats de services seront amenés à évoluer au fur-et-à-mesure des versions.

Swagger et JSONDoc : solutions invasives

A cette fin, des outils tels que Swagger ou JSONDoc sont populaires. Ils agrémentent tous les deux vos API afin d’exposer votre documentation, exploitable ensuite à travers une interface Web. Séduisantes au premier abord, elles vous permettent également de tester directement vos API.

Néanmoins, ces solutions sont intrusives dans le code de votre application. D’abord, elles imposent de les embarquer dans votre application et ajoutent une surcouche à vos API même en production. De plus, leur fonctionnement implique d’insérer des annotations dédiées à la documentation au cœur même du code source, sur chaque services de l’API. Une idée séduisante initialement : avoir la documentation au plus proche du code. Malheureusement, cela tend rapidement à réduire la lisibilité du code, et limite la maintenance de la documentation uniquement aux développeurs.

Par ailleurs, ces outils ne répondent que partiellement au besoin de documentation des API REST, notamment ils ne permettent pas de décliner aisément les différents cas d’utilisation et se limitent à la seule description des services, des champs à renseigner ou des réponses. Ils n’adressent pas non plus les liens HATEOAS. Dernier mauvais point, ils ne peuvent pas être inclus dans une documentation traditionnelle comme un guide de l’utilisateur.

Spring RESTDoc : une approche via les tests

Pour ces motifs, Spring RESTDocs propose une autre approche qui combine les avantages d’une documentation écrite manuellement et de la documentation générée. Ainsi, ce framework s’introduit également dans votre application, mais uniquement dans la phase de tests : il n’introduira alors en aucun cas de désagrément à vos services en production. Il n’y sera même pas présent. Son fonctionnement reprend l’idée de s’inviter dans le code source de votre application pour être au plus près de vos API, mais contrairement à Swagger ou JSONDoc, le code de votre application n’est pas impacté. En effet, Spring RESTDocs vient enrichir vos tests unitaires !

Exemple de test unitaire incluant de la documentation:
this.mockMvc.perform(get("/user/5").accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk())
        .andDo(document("index",
                responseFields( 
                        fieldWithPath("contact.email")
                                .description("The user's email address"), 
                fieldWithPath("contact.name").description("The user's name"))));

Dorénavant, lors de la construction du projet au moment où les tests seront exécutés, Spring RESTDocs générera des fichiers AsciiDoc contenant les requêtes et les réponses simulées lors du tests ainsi que les descriptions ajoutées dans les tests. Ensuite, ces documents pourront ensuite être inclus dans la documentation que vous avez produit pour décrire un cas d’usage. De cette façon, elle est non seulement plus lisible et plus détaillé, mais également toujours en concordance avec vos tests et par conséquent avec votre code.

Un projet exemple est disponible sur GitHub.

 

Création d’un Plugin JQuery : Input Prefix

Pour les besoins d’un projet, nous avons développé un plugin JQuery permettant d’ajouter un préfixe à valeur fixe dans les balises « Input ».

Il est alors impossible d’effacer, modifier ou couper ce préfixe…

Par contre il est toujours possible d’ajouter du texte après le préfixe, sans autres limitations que celles par défaut !

Plugin JQuery

Le plugin sur Github :

https://github.com/gfruleux/jquery-plugin-input-prefix

Demo sur Jsfiddle :

https://jsfiddle.net/97vuzwba/50/

Symfony 2 : Grande distribution

Pour le compte d’un client de la grande distribution, nous développons « from scratch » une application de gestion grâce au framework Symfony 2.

Une large liste de composants et une communauté très active, entres autres, font de ce framework une valeur sûre pour réussir vos projets.

Pour découvrir les avantages, cas d’usage, et bonnes pratiques de Symfony 2, contactez-nous et parlons PHP !

Symfony 2

Prototypage d’un gestionnaire d’événements REST-JSON : Grande Distribution

Notre client, acteur de la grande distribution, nous a sollicité pour une refonte de son SI. En effet, l’architecture logicielle actuelle ne permet plus de soutenir sa croissance.

Les 3 exigences exprimées par le client :

  1. Un référentiel de données d’entreprise centralisé
  2. Un fonctionnement autonome de ses agences locales : pouvoir faire des réservations et des ventes, même si le référentiel de données d’entreprise centralisé n’est pas accessible
  3. Un point d’accès unique aux données du référentiel par les différentes applications du SI

L’architecture préconisée par SALTO dans ce cadre :

  1. Mise en oeuvre d’un ERP (Apache OfBiz) pour la gestion du référentiel des données d’entreprise (Réponse exigence 1)
  2. Echanges inter applicatif gérés par un gestionnaire d’événements centralisé (basé sur les technologies NodeJS & MongoDB ) :
    • Abonnement des applicatifs du SI aux événements stockés par le gestionnaire d’événements pour synchronisation de leurs données (réponse exigence 2)
    • Mise à jour des données du référentiel centralisé par push d’événements (Création, Mise à jour) vers le gestionnaire de flux (réponse exigence 3)

SALTO a réalisé :

  1. Un prototype du gestionnaire d’événements en NodeJS / MongoDB
  2. Une démonstration de celui-ci à travers la mise en oeuvre de mouvements de stock sur 3 instances d’OfBiz (2 instances mettant à jour les stocks, une instance synchronisant et centralisant les stocks)

La suite :

  1. Centraliser et synchroniser les données B2C
  2. Migrer les données existantes ( ~ 500 000 occurrences) vers l’ERP « Référentiel de données » à travers le gestionnaires d’événements (pour test de montée en charge du gestionnaire d’événements)
  3. Réaliser des IHMs d’administration du gestionnaire d’événements

 

Jhipster : le générateur Spring Boot + AngularJS


JhipsterJhipster
est un générateur Yeoman qui permet de créer des projets Spring Boot / AngularJS. Créé par Julien Dubois, il permet d’utiliser un back-end efficace (Spring) parfaitement adapté à AngularJS, pour satisfaire les équipes qui ont des grandes exigences de time-to-market !

Dans le cadre d’un projet de cartes cadeaux, Salto Consulting a réalisé l’ensemble de l’architecture, du développement et de l’intégration Salesforce, pour un client de la grande distribution.

Si vous souhaitez découvrir Jhipster à travers un retour d’expérience, nous organiserons un Dojo avant l’été, contactez-nous pour y assister !

Retour sur la soirée GitHub au ChtiJUG du 9 décembre 2015

Ce Mercredi 9 décembre à l’Université Lille 1 à Villeneuve d’Ascq se tenait un Ch’ti JUG qui avait pour thème : Comment GitHub build GitHub.GitHub

Alain Helaili (@AlainHelaili) travaille chez GitHub et nous a présenté l’entreprise et montré en partie quelle était leur façon de travailler et les outils qu’ils utilisent.

Il a commencé par nous apprendre l’histoire originale de l’entreprise : des associés en Californie qui voulaient développer une super idée. Pour améliorer leurs conditions de travail, il ont créé une application autour du gestionnaire de source git. Puis ils l’ont partagé, jusqu’au jour où une entreprise a voulu l’utiliser. Il a donc fallu créer la société : GitHub, pour pouvoir vendre et trouver un prix. A ce moment là, DropBox proposait du stockage pour 7$/mois… le prix était trouvé.

Le contexte aussi est intéressant : les associés, même à coté, discutent par chat. Et le leitmotiv est que tout doit avoir une URL pour exister. Ainsi le travail est plus facilement collaboratif et asynchrone : pratique quand on travail sur plusieurs « time zone », surtout quand on sait que l’entreprise de près de 500 salariés est répartie un peu partout dans le monde ! Par ailleurs, l’une des valeurs fondamentales de GitHub est que tout soit le plus simple possible, quitte à omettre des fonctionnalités ou les retravailler jusqu’à ce que l’utilisation en devienne une évidence.

Alain nous a ensuite montré comment fonctionnait l’organisation du développement dans la société. Notamment via l’utilisation des issues et pull request. Ce qui transparaît le plus était pour moi :

  • L’absence d’e-mail au profit de création d’issue ou pull request afin de rendre visible les décisions et qu’elles soient de fait toujours documentées.
  • L’outillage devops notamment avec hubot le robot avec qui on discute par chat et qui se charge de déployer en production, faire des opérations de maintenance etc.
  • Le workflow de développement qui contient les phases classique de TU, TI, TNR etc et qui se termine par un test… en production, plutôt que d’imaginer des scénarios de montées en charge qui resteront toujours éloignés de la réalité. La phase finale consiste à déployer en production pendant un laps de temps défini, d’en mesurer les impacts puis de retirer la fonctionnalité le temps de valider qu’il n’y ait pas eu de mauvais impact. Et ce n’est qu’une fois cette validation en production faite que le développement est mis sur la branche principale : master. Ainsi la branche master ne correspond pas forcément à ce qu’il y a actuellement en production, mais elle est le socle de base, fiable pour la production.

Enfin l’application GitHub nous a été aussi présenté comme hautement personnalisable via les hooks et les nombreuses apis disponibles. On a notamment cité :

  • Review Ninja : la gestion des pull request par SAP
  • Gitcolony : également sur les pull request avec notamment la possibilité de les gérer cross-repos
  • Zenhub : qui permet de visualiser les évolutions en cours sous la forme d’un kanban
  • et plus globalement tous les addons disponibles avec GitHub

N’hésitez pas à consulter leur blog http://githubengineering.com pour en découvrir plus encore.

Le seul point négatif à mon sens de cette conférence était la salle dont l’écran était un peu petit et le micro qui coupait de temps en temps. Par contre on peut souligner le super accueil des étudiants de Lille 1 !

Merci à Alain, à l’équipe du Ch’ti JUG (enfin surtout Cyril cette fois-ci ;)) et aux étudiants de Lille 1 !

Matthieu Fernandes