· Blog de veille

Retour sur le Forum PHP 2017

Clever Age était au Forum PHP organisé par l’AFUP avec encore une fois un programme très intéressant. Voici un résumé des conférences auxquelles nous avons assisté :

PHP 7.2 : Remi Collet

Remi collet, release manager de PHP 7.2 nous a présenté cette nouvelle version. Au menu la roadmap, les breaking changes vis à vis des précédentes versions et quelques nouveautés. Le jour même de la conférence (26 octobre) la RC5 est sortie et la release finale est prévu pour le 30 novembre.

Dans les changements :

  • suppression de mcrypt (déprécié en PHP 7.1) dont la bibliothèque utilisée derrière n’était plus maintenue depuis 8 ans,
  • des fonctions dépréciées (cf slides ci-dessous),
  • les “count” sur les objets non-comptables ne sont plus possibles,
  • quand on cast un tableau en objet et un objet en tableau, il n’y a plus de problème avec des clés numériques, la conversion se fait correctement,
  • object peut maintenant être utilisé en type hinting,
  • meilleurs retours d’erreurs dans l’ouverture de session.

Remi n’a pas oublié de nous rappeler que PHP 7.0 ne sera plus maintenu en décembre 2017 et dans un an ce sera au tour de PHP 7.1. Il faut donc penser à mettre à jour nos versions assez régulièrement, au mieux tous les ans sans attendre le support native chez certains OS (ex : RedHat 7 qui n’a longtemps supporté que PHP 5.4 nous incitant à passer à RedHat 8 pour PHP 7.2). Pour nous aider, Rémi dispose d’un repository pour installer PHP de 5.4 à 7.2 sur Fedora RHEL et CentOS.

L’AB Testing chez M6 Web : Nastasia Saby et Fabien de Saint pern

Nastasia et Fabien nous ont expliqué ce qu’est l’AB testing, comment et pourquoi l’utiliser avec des retours d’expériences issus de M6 Web. Dans les grandes lignes, l’AB testing permet de changer les mentalités en prouvant qu’une idée est vraiment bonne. On peut s’en servir dans différents cas de figure :

  • personnaliser une page, par exemple avec la variation de l’ordre de la recommandation des programmes chez M6Web,
  • la communication, tel que tester une campagne d’emailing ou encore des notifications via des applications,
  • lancer progressivement une nouvelle fonctionnalité (Canary deployment),
  • tester les performances, entre 2 versions, sur le taux d’abandon au chargement ou encore la scalabilité de l’application,
  • créer une production cachée en mettant à disposition une nouvelle release à des utilisateurs restreints.

La conférence s’est terminée avec quelques pièges à éviter pour récupérer des métriques cohérentes comme la saisonnalité avec des tests l’été, le samedi et dimanche qui peuvent ne pas donner des résultats utiles ou encore l’impact d’une nouvelle fonctionnalité qui peut diminuer avec le temps.

Écrire des tests pour le long terme : Charles Desneuf

Charles nous a appris ce qu’est un test de qualité et comment l’écrire par une série d’exemples simples et compréhensibles en utilisant des principes d’écritures de tests.

Avant toute chose il faut se demander pourquoi on écrit des tests : Pour découvrir des bugs ? Refactorer ? Documenter ?  Améliorer l’architecture du projet ? … Il évoque ensuite qu’un test doit être indépendant de l’implémentation en se contentant de décrire le comportement du système, il doit avoir un résultat prédictible, être rapide à exécuter, simple à mettre en place et indépendant des autres tests.

Charles nous a expliqué des principes à respecter :

AAA pour Arrange Act Assert

Issu du pattern Four-Phase Test de la suite xUnit, cela consiste à commencer un test par la phase de Setup (Arrange) avec l’initialisation de tout ce dont le test a besoin pour s’exécuter. Il y a ensuite la partie exécutant le cas de test (Exercice pour Four-Phase Test et Act pour AAA) puis celle qui vérifie que le test est valide (Assert). L’idée est de respecter cet ordre afin d’avoir une lecture plus lisible et cohérente.

Don’t mock what you don’t own

Autrement dit, éviter de vérifier le comportement des dépendances externes, de les coupler à vos tests et de rendre vos tests fragiles. Pour cela le mieux est de respecter le principe SOLID, créer des interfaces métiers qui nous appartiennent et s’en servir pour ne pas avoir à interagir directement avec ce qui ne nous appartient pas.

Charles énonce d’autres principes à respecter permettant de comprendre les tests et de pouvoir les utiliser à d’autres fins comme la documentation, l’utilisation de factory, de méthode de refactoring (extract method), de DataProvider ou des pattern Object Mother et Test Data Builder.

LE STREAMING D’API : POURQUOI ? COMMENT ? Audrey Neveu

De plus en plus de sites modernes proposent une expérience utilisateur poussée et sont amenés à fournir de la donnée en temps réel.

Audrey Neveu, Full-stack Developer chez Saagie nous a fait un tour d’horizon des différentes solutions disponibles et a partagé ses avis et conseils sur les choix à effectuer pour mettre en place une API temps réel. Merci Audrey pour tes lumières !

Polling

A éviter, il s’agit d’un simple appel GET effectué en boucle afin de savoir si la donnée a été modifiée. En moyenne 98,5 % des requêtes sont inutiles.

WebHook

Pour faire du « presque temps réel ». Ce concept utilise un « consumer » (possédant une url de callback) et une API servant de provider qui va envoyer la donnée vers l’url de callback. Plusieurs solutions sont ici possibles pour envoyer les notifications :

Inline HTTP Request

Envoie une requête POST sur chaque abonnement et à chaque fois qu’un événement est déclenché. Cette solution n’est pas recommandée à moins d’être sûr d’avoir une faible quantité d’événements et d’abonnements.

SQL based queue

On crée un enregistrement dans la base de données pour chaque notification. Un processus va ensuite parcourir les notifications et les envoyer. Une solution à utiliser si on ne veut pas mettre en place un système de « queue » propre de type AMQP broker.

AMQP broker

RabbitMQ, ActiveMQ ou Redis, des solutions plus fiables et sécurisées et qui permettent également d’éviter de surcharger le serveur.

Batch

Solution préférable si le nombre d’envois simultanés de hooks est élevé. Il est également conseillé d’agréger les hooks en un seul gros.

Quelques points négatifs avec WebHook :

  • Ne fonctionne pas sur tous les clients (ex : mobile),
  • faible expérience utilisateur sur certaines implémentations,
  • difficile à debuger,
  • vulnérable aux attaques DDoS si l’url de callback est découverte,
  • impossible de gérer le nombre de requête vers le consumer,
  • on peut manquer des informations sans s’en rendre compte si le serveur ne répond plus,
  • potentiel duplication si le client ne répond pas correctement aux éléments envoyés.

Les recommandations sur la mise en place :

  • Un callback par WebHook,
  • bien définir les réponses attendues,
  • veiller à pouvoir tenir la charge,
  • s’assurer de gérer les duplications.

WebSub

Appelé également PubSubHubbub, Push, PubSub. WebSub est un open protocol issu du W3C. Il est basé sur un pattern où un publisher et un subscriber communiquent via un hub.

Le premier point positif de WebSub est l’authentification. Pour s’abonner ou se désabonner au contenu, le hub s’assure que l’intention vient bien de l’utilisateur.

Une autre différence concerne les notifications envoyées, avec WebSub, elles sont plus légères, on envoie seulement les nouvelles entrées avec quelques données comme le titre et le lien. C’est ensuite à l’abonné de décider s’il veut récupérer la donnée complète ou pas.

WebSub résout les problèmes d’expériences utilisateurs et des attaques de type DDoS rencontrées avec WebHook, il permet d’économiser beaucoup de ressources. Audrey conseille d’utiliser WebSub si vous avez un site à fort trafic avec beaucoup de données à échanger. A contrario, WebHook est préférable quand l’événement est important et que vous devez interagir immédiatement avec ce dernier.

LES SOLUTIONS PUSH (le « vrai temps réel »)

WebSocket vs Server-sent-event

Ces deux technologies sont des solutions de type push, elles font toutes les deux l’objet d’une spécification W3C. Server-sent-event, apparu en 2006, ne supporte que du texte et est unidirectionnel, seul le serveur envoie de la donnée au client. Tandis que Websocket, apparu en 2008, est bidirectionnel et supporte aussi bien du texte que du binaire.

Point négatif pour Websocket : il possède son propre protocole, websocket. Il faut donc faire une demande au serveur afin de pouvoir switcher de protocole et celle-ci peut être refusée.

Server-sent-event quant à lui possède beaucoup moins de contraintes car il utilise le protocole HTTP, un simple ajout de Accept : text/event-stream dans le header suffit.

D’un point de vue applicatif, ces deux solutions sont relativement simple à mettre en place. WebSocket nécessite de créer un objet WebSocket puis de s’abonner à des callbacks, il en existe trois : onopen, onmessage et onerror.

Server-sent-event utilise quant à lui un objet EventSource et implémente les mêmes méthodes callback que WebSocket. L’avantage de Server-sent-event est qu’il est possible d’ajouter des « eventListeners » grâce à une méthode supplémentaire addEventListener. Cela nous permet de typer les messages afin de ne s’abonner qu’à certains d’entre eux.

Une fois la connexion revenue, WebSocket est incapable de récupérer la donnée, alors que Server-sent-event possède un processus qui utilise l’ID du dernier message envoyé. Le serveur est capable de retrouver l’historique du message et de le transmettre au client.

Tous les clients supportent WebSocket mais Internet Explorer ne prend pas en charge Server-sent-event. Ce problème peut cependant être pallié grâce aux Polyfills. Sur mobile, la compatibilité est identique sur les deux solutions, seul Opera mini n’est pas disponible.

Enfin, un test de performance portant sur la récupération de 500 tweets a montré que Server-sent-event est plus rapide face à WebSocket : 5s vs 8s sur Chrome, 6s vs 8s sur Firefox et 7s vs 16s sur Safari…

Pour conclure, WebSocket est la solution à utiliser si vous devez faire du temps réel avec du binaire, ex : jeux vidéo, chat, … Mais dans la plupart des cas, Server-sent-event semble de loin être la meilleure solution tous points de vue confondus.

Développer plus rapidement avec le framework Symfony™ 4 : Kévin Dunglas

Kévin nous donne un aperçu des nouveautés qui apparaissent avec Sf 4 et Sf 3.4 (les deux versions contiendront les mêmes fonctionnalités).

Capture d’écran 2017-11-03 à 15.19.09

 

Symfony s’appuie maintenant sur la méthodologie 12 factor et simplifie la compatibilité des applications à des plateformes de cloud (Heroku, Plateform.sh…) ou Docker. On utilise maintenant des variables d’environnement à la place du fichier parameters.yml et la configuration sera mieux organisée et gérée par Symfony Flex.

Symfony Flex est un plugin Composer permettant d’installer ou supprimer proprement une librairie externe sans nécessiter d’intervenir manuellement comme on devait le faire avant avec les Bundles. Il s’appuie sur 2 repositories (symfony/recipes et symfony/recipes-contrib) décrivant comment doivent s’installer les dépendances grâce à un fichier manifest.json.

Les process de qualité – le cas de Symfony : Nicolas Grekas

Pour Nicolas, la qualité n’est pas un état mais un process qui se mesure sur la vie et l’évolution du code. On a donc appris dans cette conférence comment Symfony évoluait, à quelle fréquence et comment y contribuer.

Symfony comporte un repository principale symfony/symfony (appelé aussi monorepo) utilisé notamment pour répertorier les issues mais derrière il y a 48 repository indiqués en tant que “readonly” sur GitHub et intégrés dans le repository principal grâce à un robot.

Le Semantic versioning est utilisé à des intervals réguliers : un patch tous les mois, une version mineure tous les 6 mois et une version majeure est censée sortir tous les ans. Seuls les patchs de sécurité ne suivent pas et peuvent perturber cet ordonnancement. Une version LTS (version supportée pendant 3 ans) est créée au final pour la dernière version mineure d’une version majeure (exemple 2.8 pour Sf 2 et 3.4 pour Sf 3). Une LTS est uniquement utile pour un projet stable ne disposant plus d’investissement (frozen project).

Symfony a des règles de rétrocompatibilité assez strictes. Toutes les versions 3.x doivent être rétrocompatibles. Des annotations sont utilisées pour ne pas avoir de problème à ce niveau (@internal : ne pas utiliser, @final : ne pas surcharger). Symfony dispose même d’un chemin de migration continu afin de faciliter la migration des versions. Ainsi, d’autres règles font leur apparition telles que les notices de dépréciations qui doivent être indiquées lorsque la prochaine version majeure introduira des « breaking changes ».

Pour nous aider à contribuer, une surcouche à PHPUnit existe (PHPUnit Bridge) afin de vérifier que des fonctionnalités dépréciées ne sont pas utilisées dans une PR (Pull Request). PHPUnit Bridge contient également une horloge virtuelle et un mock de DNS. Les éléments dépréciés doivent être testés en utilisant l’annotation @group legacy.

A chaque PR effectuée, l’intégration continue prend le relais avec Travis sur Linux, Appveyor sur Windows et Fabbot pour les conventions de codage ainsi que d’autres vérifications. Même la CI de Symfony fait l’objet d’optimisations, par exemple : l’ensemble des tests passent en moins de 5 minutes. Lorsqu’une PR est validée, le merge est effectué un à un dans les versions supérieures en corrigeant les éventuels conflits afin que la correction soit effective dans toutes les versions que Symfony maintient.

Réécriture de code vieux de 17 ans : Anna Filina

Anna nous fait un retour “quelques années en arrière” en nous rappelant des erreurs commises que l’on peut retrouver dans du code legacy. Elle a ensuite poursuivi la conférence en nous expliquant comment on peut reprendre et améliorer ce type de code.

Pour Anna, il n’y a pas de cas désespéré. Le refactoring est toujours possible et doit être privilégié, à moins que le projet ne soit pas trop important et que le business accepte de faire une refonte entière sans nouvelle fonctionnalité, pendant une période définie. La stratégie la plus mise en avant a été une réécriture progressive d’une application en passant par un nouveau projet Symfony et la redirection d’URLs grâce au mode_rewrite d’Apache.

Il est important d’arriver à extraire les règles métiers issues du design, de les faire valider et d’améliorer le design. Concernant la base de données, Anna préconise d’utiliser des vues durant la transition. On peut également faire des tests assez haut niveau valables pour l’application legacy et la nouvelle. Il faut tout de même faire attention lorsque les tests sont trop couplés (par exemple au design ou au DOM) car ils perdront de leur intérêt s’ils ne peuvent plus s’appliquer au nouveau code.

Log me now : Kevin Gomez

Kevin nous a expliqué comment écrire des logs utiles sans rentrer dans des détails techniques. La première étape est de définir une stratégie et de savoir précisément ce que l’on veut logger : des performances, des ressources, des erreurs,  ou encore des actions utilisateurs qui ont une valeur métier ?

A qui les logs sont-ils utiles ? Disposent-ils d’informations nécessaires ? On peut répondre à ces questions en partant d’un log simple Order failed et en finissant par quelque chose de beaucoup plus complet : [2017-12-12T14:30:51.965Z] [WARNING] Order {order_ref} failed : {reason} -- {"order_ref" : "REF-42", "reason" : "payment gateway unreachable"}

Le Log a suivi différentes étapes nous permettant de bien comprendre certaines règles :

  • Un message de log doit être explicite.
  • On doit savoir quand il arrive et pour quelle raison.
  • Il doit être normalisé et exploitable.
  • Il doit utiliser un format parsable comme le JSON et ne jamais être sur plusieurs lignes.
  • On doit ajouter des informations supplémentaires pour faciliter son utilisation, un contexte.
  • Il doit avoir un niveau de criticité.

On peut également aller jusqu’à faire des catégories par sous-système, proposer une solution à l’erreur et générer un identifiant afin de regrouper des logs issus de la même action.

GraphQL, L’avenir du REST ? : François Zaninotto

François nous a fait une présentation de GraphQL en le comparant à son concurrent principal, REST.

REST est un style d’architecture alors que GraphQL est un langage de requête. Avec REST, on a une URL pour chaque ressource alors qu’avec GraphQL on n’a qu’une URL servant de point d’entrée peu importe la ressource recherchée. GraphQL ne respecte pas réellement les verbes HTTP comme le fait REST, il peut uniquement utiliser GET et POST. POST semble le plus populaire étant donné que les requêtes peuvent s’effectuer de manière plus propre en JSON dans le header.

Les avantages que l’on a pu retenir en faveur de GraphQL sont :

  • La rapidité de prise en main pour le client de l’API notamment grâce à GraphiQL.
  • L’API est plus facilement évolutive et moins soumise à des problèmes de rétrocompatibilité, on ne fait plus de versionnement et on ne touche pas aux champs existants, on ne fait qu’en ajouter de nouveaux.
  • On peut indiquer les informations dont on a besoin évitant ainsi de récupérer des choses inutiles et d’alourdir la réponse.
  • On peut plus facilement faire de l’Optimistic UI car GraphQL ne demande pas au front d’attendre la réponse pour la traiter différemment selon certain code d’erreur (comme pourrait le faire REST).
  • GraphQL cache l’implémentation back permettant de faire plus simplement des requêtes complexes et se rapproche plus du métier.

Dans les inconvénients :

  • Log plus difficile étant donné que le POST est utilisé par défaut.
  • Le cache backend est plus complexe à mettre en place, une seule URL, généralement en POST avec des requêtes beaucoup plus personnalisables qu’avec une API REST rendant difficile l’utilisation d’outil tel que Varnish.
  • Comme ce sont les utilisateurs de l’API qui créent les requêtes, on est plus facilement exposé à des attaques de type Denial Of Service.

A l’écriture de cet article les slides n’étaient pas disponibles mais François à publier une série d’articles sur le sujet.

Faut-il faire du travail de qualité ? : Jean-François Lépine

Jean-François nous a parlé de qualité. Il a commencé par démontrer que celle-ci est généralement subjective quand on en discute (« mon code est propre pas le tien ») et pourtant il y a des normes (norme ISO 9126, ISTQB). Il faut donc la prioriser et se baser sur une liste de critères avec des objectifs précis afin de déterminer ce que peut être la qualité pour un projet donné et la mesurer correctement.

objectifs qualité

Un point d’attention particulier a était fait pour expliquer que la qualité n’est pas superposable à la stack technique. Ce n’est pas parce que l’on versionne les assets et qu’on n’utilise pas un gestionnaire de dépendances comme npm, yarn ou bower qu’on ne fait pas de la qualité. jQuery par exemple peut faire le job ! L’important est d’avoir pesé le pour et le contre et de pouvoir expliquer les choix fait sur un projet à un moment donné.

Il faut également éviter de faire de la surqualité. Par exemple une démarche SOLID peut être contre-productive dans certains cas de figure amenant un niveau d’abstraction trop important et complexifie la compréhension. Pareil pour les tests, il est inutile de passer 50 % du temps de développement sur des tests si ce que l’on teste n’a pas de valeur vis-à-vis du métier et de nos objectifs. Il faut prioriser, identifier ce qui est long et difficile à tester manuellement et l’automatiser.

La qualité doit se faire au sein de petites équipes et pas d’entreprises de manière globale parce que les objectifs et les métriques peuvent être différents. Laisser un bug en production ou ne pas se focaliser sur la performance de l’application, c’est parfois de la qualité. Le principal est d’être cohérent et de se concentrer sur les critères que l’on s’est fixés.

Et les autres conférences ?

Clever Age n’a pas pu assister à toutes les conférences mais vous pourrez trouver les slides et les vidéos sur le site de l’AFUP.

Merci aux organisateurs et à l’AFUP pour cette belle édition du forum PHP qui aura une fois encore tenu toutes ses promesses.