24min.

Ce que nous avons retenu du Forum PHP 2024, jour 1

Comme chaque année l’équipe de JoliCode était présente au Forum PHP de l’AFUP, le plus gros événement PHP de l’Hexagone, pour deux jours de conférence sur l’éco-système !

Dans cet article nous allons vous partager nos take-aways, ce que nous y avons découvert et ce que nous en retenons. Accrochez-vous à vos écrans, on va chez Mickey 🐭 ! Nous avons séparé nos retours en deux articles tant il y avait de choses à raconter, voici donc le jour 1 – le jour 2 est par ici !

Forum PHP 2024

Section intitulée creer-sa-malware-sandbox-en-phpCréer sa Malware Sandbox en PHP

Alexandre Daubois, développeur chez Decathlon et contributeur régulier à Symfony, nous a présenté une sandbox pour analyser les malwares, développée en PHP. Avant d’en arriver à cette solution, il a détaillé son parcours pour tenter de sécuriser les fichiers uploadés dans un back-office sécurisé de son entreprise.

Par exemple, pour s’assurer qu’un fichier ne contient pas de virus, plusieurs approches sont possibles. Après avoir mis le fichier en quarantaine :

  • Envoyer le fichier via une API à des éditeurs d’antivirus ;
  • L’analyser soi-même : cela nécessite de prendre des empreintes (fingerprints) du fichier et de les comparer avec des bases de données souvent très coûteuses ;
  • Exécuter le fichier dans une sandbox (VM) et analyser les appels système effectués par l’exécutable.

Toutes ces solutions s’avérant trop onéreuses, Alexandre a décidé de développer une classe PHP capable de vérifier les cas les plus courants de manière plus économique :

  • Vérifier qu’il n’y a pas de caractère non-ASCII dans le nom du fichier ;
  • S’assurer qu’il n’y a pas de tentative de “directory traversal” (un nom de fichier contenant ../) ;
  • S’assurer que le fichier n’a pas de droits d’exécution ;
  • Vérifier les magic bytes (les 4 premiers octets d’un fichier qui définissent son type) pour s’assurer qu’il ne s’agit pas d’un fichier exécutable, en tenant compte à la fois du Big Endian et du Little Endian ;
  • Si le fichier est une archive, appliquer ces contrôles à chaque fichier qu’elle contient.

La conférence s’est déroulée de manière fluide et agréable. Toutefois, bien que la solution proposée soit intéressante, elle nous est apparue un peu simpliste, et nous aurions sans doute attendu quelque chose de plus approfondi.

Les magic bytes pour détecter les fichiers exécutables

Section intitulée les-nouveautes-dans-symfony-7-xLes nouveautés dans Symfony 7.x

Nicolas Grekas a présenté les nouveautés de Symfony 7, et même si nous en avions déjà parlé en avril, de nouvelles informations sont venues enrichir cette version.

Parmi les nombreux changements évoqués, on trouve l’ajout de typage natif, l’utilisation des nouvelles syntaxes PHP 8.2, et les « constructor property promotion ». Mais concentrons-nous sur les véritables nouveautés.

Du côté des tests, une avancée notable : PHPUnit 11 deviendra bientôt la version par défaut, et le phpunit-bridge va disparaître. Initialement conçues pour combler certaines lacunes de PHPUnit, comme les rapports de dépréciation, ces fonctionnalités sont désormais pleinement supportées nativement.

Concernant les nombreux bridges de Symfony, on observe une activité intense, comme l’ajout récent d’un connecteur JoliNotif, notre bibliothèque pour déclencher des notifications desktop ! 😍

De nouveaux attributs pour les contrôleurs font leur apparition, notamment les attributs #[Map*] qui permettent de mapper des contenus de requêtes dans des objets ou arguments avec une gestion d’erreurs (4xx) en cas de problème. Mentionnons également #[WhenNot], une version inversée de #[When], permettant d’activer un service uniquement dans certains environnements (dev, test, prod).

À partir de Symfony 7.2, le composant Console pourra gérer des signaux d’alarme via un événement ConsoleAlarmEvent, ce qui facilite la manipulation des processus avec alarme.

En outre, Symfony inclura désormais la possibilité d’avoir des serializers nommés. Cela permet de résoudre des conflits potentiels, notamment avec des outils comme API Platform ou Jane, en évitant que les normalizers se propagent à toute l’application. On pourra ainsi avoir des configurations spécialisées sans effets de bord.

Enfin, plusieurs nouveaux composants sont en discussion, notamment ObjectMapper, JsonEncoder, FeatureFlags, et AccessToken. Le composant Uri est en débat, mais pourrait être intégré directement dans PHP.

Section intitulée comment-deboguer-xdebug-ou-n-importe-quel-autre-bug-bizarre-en-phpComment déboguer Xdebug… ou n’importe quel autre bug bizarre en PHP

Kévin Dunglas, développeur chez les-tilleuls.coop et core contributeur à Symfony, API Platform, FrankenPHP, et autres projets, nous a présenté un cas concret : un bug rencontré dans FrankenPHP et sa résolution.

Qui n’a jamais été confronté à un bug mystérieux, sans savoir par où commencer ? Si vous vous êtes déjà retrouvé dans cette situation, cette conférence est faite pour vous !

À travers plusieurs étapes, Kévin nous a guidés dans l’identification de l’origine potentielle d’un bug : est-ce dû à notre propre code (dépendances à jour, utilisation de la « happy path », bibliothèques populaires et bien maintenues) ou se situe-t-il dans les vendors (une récente mise à jour pourrait en être la cause) ?

Dans l’exemple présenté, il semblait que le bug provenait des vendors. Mais de quel côté ? Docker, PHP, ou Xdebug ?

La première étape consiste à créer un scénario reproductible du bug. Ensuite, il est crucial de réduire le code au strict minimum pour éliminer des pistes. Souvenez-vous : moins de code signifie moins de bugs. Par exemple, Kévin a testé sans Docker, ce qui lui a permis d’exclure cette technologie de l’équation.

Vient ensuite le moment de sortir un débogueur bas niveau car… Xdebug faisait planter le script ! Le plus connu dans ce domaine est GDB, mais il n’est plus compatible avec les dernières versions ARM de macOS. À la place, il faut utiliser LLDB, le débogueur fourni par LLVM. Ces outils, qui fonctionnent avec n’importe quel langage compilé (C, C++, Go, Rust, etc.), sont relativement simples d’utilisation. En général, on les lance avec une commande comme : gdb – ./path/to/my/program. Cela permet ensuite de faire du pas-à-pas, d’inspecter la RAM, ou encore de demander un backtrace.

En quelques secondes, Kévin obtient une trace et identifie la source du bug. Attention toutefois : pour qu’un backtrace soit lisible, il faut que le programme soit compilé avec les symboles de debug. Ceux-ci sont l’équivalent des “source maps” en JavaScript : ils associent les instructions CPU aux lignes de code. Si les symboles ne sont pas présents, il faudra les installer.

Et voilà ! Grâce à ce backtrace, Kévin sait d’où vient le bug. Il peut alors contacter Derick, le créateur de Xdebug, pour discuter d’un correctif et soumettre une pull request.

Le bug en lui-même n’était pas exceptionnel, mais le chemin pour le débusquer et le corriger l’était. Cette conférence a captivé l’audience et devrait donner à tous les développeurs et développeuses le courage de ne plus craindre un bug, et de plonger avec détermination dans les vendors pour le résoudre.

Section intitulée github-copilot-une-integration-sans-turbulences-dans-notre-dsiGitHub Copilot : une intégration sans turbulences dans notre DSI

Audrey BROUARD, DevRel chez Harmonie Mutuelle, nous explique qu’en fin d’année dernière, pendant l’explosion en popularité de l’IA, son service informatique s’est intéressé aux outils basés sur l’IA dans une quête de productivité.

L’équipe à choisi d’essayer en particulier GitHub Copilot.

Ce choix s’explique par plusieurs facteurs :

  • Intégration transparente : L’équipe utilise déjà GitHub, ce qui facilite l’adoption de l’outil ;
  • Maturité et leadership : Copilot est une solution avancée, leader sur le marché ;
  • Prix accessible : Le coût de Copilot a été jugé raisonnable.

Audrey a présenté Copilot comme un outil qui suggère des complétions de code en se basant sur un vaste ensemble de code open-source et sur le contexte du projet (comprendre : les onglets ouverts dans l’IDE).

Un point important a été souligné : Copilot est un assistant, pas un remplaçant. Le peer programming avec un développeur expérimenté reste essentiel, et l’esprit critique doit toujours primer.

Pour intégrer Copilot à la DSI, l’équipe a adopté une approche méthodique :

  1. Sondage auprès des développeurs : L’objectif était de recueillir les avis et la perception de l’outil. Il s’est avéré que Copilot était déjà connu, et que les développeurs étaient globalement ouverts à l’idée de l’utiliser ;
  2. Identification des besoins : Une phase de test de 2 mois avec la licence entreprise a été lancée, permettant aux développeurs d’explorer les différentes fonctionnalités de Copilot. Un canal de discussion dédié a favorisé le partage d’astuces et de retours d’expérience. Un panel de 25 testeurs aux profils variés (juniors, seniors, front, back…) a permis d’obtenir des perspectives diversifiées et plus directes.

L’expérimentation a mis en lumière plusieurs cas d’usage pertinents :

  • Génération de documentation ;
  • Génération de tests ;
  • Migration et refactorisation de code ;
  • Explication de code ;
  • Implémentation de l’accessibilité.

Et les retours des développeurs ont été très positifs :

  • Gain de temps estimé à 3h45 par semaine en moyenne (valeur à prendre avec des pincettes car dure à estimer) ;
  • 78% se concentrent sur des tâches plus satisfaisantes ;
  • 83% prennent plus de plaisir à coder ;
  • 94% se sentent plus rapides.

Certaines limites ont toutefois été identifiées, par exemple Copilot peut avoir une tendance à générer du code erroné, incomplet ou redondant. Aussi l’utilisation de Copilot par les développeurs juniors et alternants soulève des questions quant à l’impact sur leur apprentissage. Globalement, l’équipe a tiré un bilan très positif de l’utilisation de Copilot :

  • Intégration facile : L’outil s’intègre parfaitement à l’environnement de travail existant ;
  • Rentabilité : Le coût de la licence est compensé par le gain de temps réalisé d’après les développeurs ;
  • Adoption croissante : L’accès gratuit pour les étudiants familiarise les futurs développeurs avec l’outil, et ils s’attendent à le retrouver en arrivant sur le marché du travail ;
  • « Développeur augmenté » : Copilot ne remplace pas les développeurs, mais les assiste et les rend plus efficaces (si tant est qu’on relit et test le code généré).

Enfin, la question de la confidentialité du code a été abordée. Si la licence personnelle utilise le code privé pour entraîner l’IA, la licence entreprise est censée garantir la confidentialité des données. Cependant, des interrogations subsistent quant à la collecte et à l’utilisation des données par Copilot pour générer ses suggestions, et on se demande si malgré les engagements quant à la confidentialité que prend la licence entreprise, nos codes privés ne traînaient quand même pas dans des logs à la Silicon Valley : vos fichiers locaux faisant parti du prompt qui est envoyé à GitHub. Audrey nous a finalement informé qu’il existe une API qui permet de collecter des données sur l’utilisation de Copilot au sein d’une organisation, offrant ainsi la possibilité de mesurer l’efficacité de l’outil : https://github.com/github-copilot-resources/copilot-metrics-viewer.

Section intitulée php-parallel-accelerer-sensiblement-ses-temps-d-executionPHP/Parallel : Accélérer sensiblement ses temps d’exécution

Thierry KAUFFMANN nous a livré un retour d’expérience très pertinent sur le développement d’un orchestrateur de serveurs écrit en PHP. Le projet doit permettre à un service d’être flexible et d’adapter son infrastructure à la demande, de manière rapide et efficace, afin d’optimiser les coûts et l’expérience utilisateur.

La limitation la plus importante dans ce type de développement est qu’il faut « parler » à de nombreux services en même temps (SSH sur les serveurs, HTTP avec l’API du service Cloud, etc.).

Le choix de PHP pour ce développement a été justifié par deux raisons :

  • L’équipe de développement est à l’aise avec PHP ;
  • Il existe une extension permettant de faire des traitements en parallèle.

Le cœur du projet repose donc sur une extension : parallel.

PHP est mono-threadé par défaut. On peut utiliser des outils comme pcntl, popen, exec, qui sont standards (voir le composant Process de Symfony). On peut également citer ReactPHP et Amphp, qui sont mono-threadés mais qui utilisent des event loops. Il y avait aussi pthreads, mais ce dernier a été abandonné. Nous avons donc maintenant parallel, le nouveau venu.

Cette extension, créée par Joe Watkins (krakjoe), permet de réaliser du véritable multi-threading. Elle est conçue selon ce principe :

Ne communiquez pas en partageant la mémoire, partagez plutôt la mémoire en communiquant.

L’API de base est la suivante :

\parallel\run(
  function() {
    sleep(5);
    echo "World !"
  }
)
\parallel\run(
  function() {
    sleep(2);
    echo "Hello "
  }
)

// Hello World !

Il existe bien sûr de nombreuses options, comme les channels pour la communication entre threads, mais nous n’entrerons pas plus dans les détails ici.

L’orateur évoque également les limitations :

  • La communication entre threads ne doit jamais être faite par référence, donc pas d’objets ;
  • La tâche ne doit pas :
    • utiliser yield ;
    • déclarer une classe ;
    • déclarer une fonction nommée.

Cependant, pour passer des objets entre threads, on peut utiliser serialize, par exemple.

🚨 L’auteur de cette extension a besoin de votre aide. Joe Watkins est un pilier de la communauté PHP, et si vous le pouvez, c’est le moment de l’aider 🫶.

Section intitulée cte-la-puissance-inexploitee-de-votre-base-de-donnees-sqlCTE, la puissance inexploitée de votre base de données SQL

Timothée Martin ne s’attendait pas à faire salle comble avec du SQL ! 🤯

CTE signifie Common Table Expression, et ce sont des requêtes avancées que Timothée nous a aidés à démystifier. D’abord, il nous a rassurés, les CTE sont présents sur tous les moteurs de base de données, donc pas d’excuse ! À travers un exemple concret, il nous a fait voir leur puissance.

Par exemple, si l’on veut récupérer tous les employés qui gagnent plus que le salaire moyen de leur département, on pourrait écrire :

WITH AvgSalaryCTE AS (
    SELECT department, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY department
)
SELECT e.employee_name, e.department, e.salary, a.avg_salary
FROM employees e
JOIN AvgSalaryCTE a
ON e.department = a.department
WHERE e.salary > a.avg_salary;

On pourrait simplifier en disant que ce sont des tables temporaires créées à la volée dans le cadre d’exécution de la requête principale seulement (à la différence des vues, par exemple). Certes, elles permettent d’écrire des requêtes plus puissantes, mais Timothée nous a aussi montré qu’elles peuvent servir à simplifier certaines requêtes qui seraient plus difficiles à lire (comme des sous-requêtes).

Ensuite, nous sommes entrés dans le vif du sujet : les CTE récursives, qui portent en fait mal leur nom. Ce sont en réalité des boucles, seule la syntaxe est récursive. Ouf ! Toujours à travers son exemple, il nous a montré quelques requêtes permettant de faire des boucles sur des données existantes, pour finir par la mise en place d’une requête de construction d’un graphe.

Là, c’est sûr, une partie de la salle avait des étoiles dans les yeux 🤩. Grâce à PostgreSQL et l’implémentation native de CYCLE, le moteur SQL sait détecter des boucles infinies lors de CTE récursives afin de les éviter, mais il peut aussi donner en sortie le graphe traversé lors de l’exécution de la CTE.

Pour le coup c’est bien une utilisation avancée, je vous renvoie donc vers la documentation pour plus de détails.

Niveau performance, comme souvent, ça dépend. Même si sur les petits volumes, il semble que les performances soient au rendez-vous, pour les autres cas, il nous invite à tester et comparer ! Mais il ne faut pas oublier que le gain de performance est aussi d’éviter des aller-retours avec le code métier.

Et Doctrine dans tout ça ? Eh bien, rapidement, il a présenté des pistes, par exemple, utiliser les CTE comme si c’étaient des vues. Les vues étant prises en charge par Doctrine nativement. Sinon, on peut se tourner vers les NativeQuery associées à des ResultSetMapping. C’est peut-être un peu plus de travail, mais le résultat en vaut la peine car on retrouve au final des DTO ou Entités faciles à utiliser dans notre code.

Section intitulée le-grand-cycle-de-la-vie-d-une-variableLe grand cycle de la vie (d’une variable)

Benoit Viguier, fidèle à son style clair et didactique, nous a expliqué avec fluidité le cycle de vie d’une variable en PHP. Cette présentation s’est concentrée sur l’allocation et la désallocation de la mémoire par la machine virtuelle PHP. En seulement 20 minutes, il était impossible de couvrir l’intégralité du sujet, mais Benoît a tout de même abordé des concepts clés comme le garbage collector, les références circulaires, le copy on write, et les weak references.

Si ces termes vous sont inconnus, nous vous invitons à consulter les slides de sa conférence (PDF).

Section intitulée throw-new-exception-oui-mais-laquellethrow new Exception(); Oui mais laquelle ?!

Olivier Dolbeau nous a parlé d’exceptions en commençant par leur utilité : gérer un cas exceptionnel. Une exception n’est donc pas synonyme d’un bug. Elle correspond à toutes les situations qui sortent du cas nominal mais qu’on peut prévoir.

Pour savoir quelle exception est la plus adaptée à être déclenchée, Olivier distingue deux cas, suivant si l’on se trouve dans une bibliothèque, ou sur un projet final.

Une bibliothèque a généralement des besoins figés. On va donc chercher à anticiper tous les cas d’erreurs possibles pour que l’utilisateur puisse les gérer comme bon lui semble. Il n’est pas nécessaire de créer une classe pour chaque erreur. En revanche, chaque exception levée devrait implémenter/hériter d’une interface/classe commune à toute la bibliothèque. Et il ne faut jamais lancer une exception n’appartenant pas à la bibliothèque. Pour l’illustrer, Olivier nous parle du package symfony/http-client qui fournit des classes d’exceptions pour les erreurs HTTP 4xx, d’autres pour les erreurs HTTP 5xx, encore d’autres lorsque la réponse JSON n’est pas valide, etc. Et pour autant, toutes ces exceptions implémentent l’interface Symfony\Contracts\HttpClient\Exception\ExceptionInterface, permettant à l’utilisateur de catcher, en un coup s’il le souhaite, toutes les erreurs possibles.

Au contraire, dans le cas d’un produit fini, les besoins sont souvent évolutifs. Chercher à gérer tous les cas d’erreurs serait une perte de temps. Il vaut mieux se concentrer sur les cas d’erreurs prévus et/ou utiles. À la place, pour déterminer quelle classe d’exception utiliser, Olivier nous propose cet ordre de priorité :

  • Utiliser une exception provenant d’une bibliothèque utilisée dans le projet. Ces bibliothèques fournissent souvent de nombreuses exceptions qui peuvent correspondre à votre besoin, par exemple Symfony\Component\Validator\Exception\ValidationFailedException ou Doctrine\ORM\EntityNotFoundException ;
  • Créer sa propre exception si nécessaire pour le métier ;
  • Utiliser une exception fournie par PHP (pour les exceptions non prévues par le métier, par exemple \RuntimeException ou \LogicException).

Pour conclure, Olivier nous suggère également qu’il n’est pas nécessaire de toujours chercher à tout catcher. Pour lui, c’est normal d’avoir une erreur 500 en prod si la BDD est KO par exemple.

Exception PHP

Section intitulée un-parser-de-php-en-php-le-coeur-des-outils-d-analyse-statiqueUn parser de PHP en PHP : le cœur des outils d’analyse statique

Lors de cette conférence, Mathieu Noël nous a réexpliqué les concepts fondamentaux des lexers, des tokens, des parsers et des AST (Abstract Syntax Tree). Nous avons constaté que PHP ne possède pas d’outil natif pour accéder à ces primitives.

C’est donc la bibliothèque nikic/PHP-Parser, développée par Nikita Popov, qui est utilisée. La plupart des outils d’analyse statique, tels que PHPStan, php-cs-fixer, etc. (que nous utilisons fréquemment chez Jolicode), reposent sur cette bibliothèque.

Malheureusement, Nikita Popov n’est plus aussi actif dans la communauté PHP source, ce qui expose la communauté à un risque important, également connu sous le nom de facteur d’autobus.

Nous avons ensuite étudié un exemple concret d’utilisation de la bibliothèque de Nikita. Mathieu nous a guidés à travers la création d’un script PHP visant à établir une règle de style de code spécifique.

Enfin, Mathieu a présenté plusieurs alternatives au parser de Nikita Popov :

  • tolerant-php-parser de Microsoft, qui ne génère pas d’erreurs car il est conçu pour être utilisé dans le contexte d’un IDE ;
  • php-ast, également de Nikita Popov, écrit en C ;
  • pxp, malheureusement encore en phase de développement.

Pour pallier le départ de Nikita, une solution pourrait être d’intégrer ce parser directement dans le cœur de PHP.

NDLR : Nous souhaitons apporter quelques corrections à la présentation :

  • Il existe des primitives dans PHP pour lexer du code PHP et récupérer les tokens: token_get_all(). C’est d’ailleurs ce qu’utilise PHP-Parser ;
  • L’extension php-ast ne fait qu’exposer l’AST qui est déjà construit par PHP.

Section intitulée resurrecting-the-deadResurrecting the Dead 🧟

Un projet open source peut passer par plusieurs phases au cours de sa vie : d’abord il est jeune, il est un peu bancal mais plein de potentiel, les gens commencent à s’y intéresser. Il devient ensuite mature, c’est sa phase idéale. À ce stade, le projet est stable, maintenu régulièrement par une communauté solide. La phase suivante est la phase zombie : le projet est toujours très utilisé, mais peu maintenu. Il peut passer d’une de ces deux phases à l’autre plusieurs fois au cours de sa vie. Mais s’il n’est plus maintenu, il meurt.

Alors comment un projet vient-il à mourir ? Cela peut arriver pour de nombreuses raisons, qu’elles soient familiales ou parce qu’un autre projet plus populaire le remplace.

Juliette Reinders Folmer nous raconte comment elle est devenue « mainteneur accidentel » du projet PHP_CodeSniffer. Simplement en contribuant, puis en réparant la CI et avec un peu de pression de la part de la communauté. À ce moment-là, notamment sur de petits projets, on espère que quelqu’un d’autre reprendra le flambeau, puis on réalise que si on ne le fait pas, personne d’autre ne le fera !

Une autre cause de départ des mainteneurs de projets est le burnout. La pression de la communauté met parfois les gens dans le rouge humainement. Merger des PR, vérifier qu’une issue est toujours pertinente, sont autant de petites choses qui prennent du temps aussi. Il faut prendre conscience que derrière chaque projet open source il y a des humains comme vous et moi.

Alors que faire ?

Tout d’abord, connaissez-vous bien vos dépendances ? Et l’état dans lequel elles se trouvent ? Qui sait sur quel zombie vous vous reposez ? Et peut être qu’il n’existe pas de remplacement à celles-ci. Un point important que vous devez mettre en avant est qu’il est économiquement plus viable de mettre le budget pour maintenir ces dépendances à l’abandon que de les remplacer. Donc n’hésitez pas à financer les projets et à sponsoriser.

Si vous maintenez vous-même un projet, quelques conseils :

  • Vous pouvez ajouter un nouvel administrateur à votre projet. Il faut que ça soit sur une organisation dédiée, car s’il s’agit de l’organisation d’une entreprise, elle sera peut être réticence à donner un accès admin à un utilisateur extérieur ;
  • Le repository peut être transféré à une personne de confiance. Cela permet de conserver toutes les issues, les PR, et globalement, l’historique du projet, c’est bien mieux qu’un fork ;
  • Forker (dupliquer) le repository. C’est plus confus, on perd les issues, le wiki, les URL de download… Il faut tout recommencer et les gens se perdent ; on peut parfois garder le nom du package sur composer et ça aide. Attention lorsque plein de gens forkent le repo, les utilisateurs ne s’y retrouvent plus et le projet meurt quand même !
  • Laisser le projet mourir s’il n’est vraiment plus pertinent ou plus utilisé.

Juliette nous rappelle que maintenir un projet, ce n’est pas juste coder. C’est faire en sorte que le projet puisse continuer de tourner. En ayant une CI qui puisse bien passer, des issues triées etc. Mais c’est aussi avoir une vision du futur. En tant que mainteneur, il ne faut pas hésiter à laisser les bug fixes et features aux autres : ces issues sont la porte ouverte à des contributeurs externes, futurs nouveaux mainteneurs !

Un projet en bonne santé donc, c’est quoi ?

  • Plusieurs mainteneurs, des « cercles » de contributeurs autour de ces mainteneurs, plus ou moins assidus. Les gens peuvent avancer ou reculer d’un cercle à l’autre sans impacter la santé du projet ;
  • Une gestion de la succession : écrire les releases, informer des donations, activer la communauté, tout documenter. Il faut aussi partager les clés du château pour éviter les accidents (admin sur le repo, accès au DNS, droit sur le package, réseaux sociaux, etc) ;
  • Une organisation dédiée, des canaux de sponsoring, des branches protégées, des PR, un guide de contribution, un rangement par label… et fermer les issues rapidement pour réduire le bruit.

Le F de FOSS, est pour free au sens de “freedom”, « libre », pas pour “free” comme « gratuit ».

Si quelque chose a l’air de « juste » fonctionner, c’est que quelqu’un se donne à fond derrière pour maintenir le projet.

Pour bien manager un projet open-source il faut :

  • Documenter
  • Engager les gens
  • Identifier
  • Coacher
  • Valider
  • Promouvoir
  • Financer !

Le financement est effectivement très important pour les mainteneurs qui font autre chose que de développer. En tant qu’entreprise, donner du temps à ses salariés pour contribuer ne suffit pas, car toutes ces PRs resteront potentiellement sans review ou ne seront pas mergées, ou pas assez vite ! En tant que mainteneur, Juliette conseille de ne pas appeler ça « sponsoriser” ou “donner » mais « assurer », pour convaincre les entreprises d’investir.

Elle conseille aussi aux contributeurs de ne pas utiliser d’IA pour développer. Ils connaissent sûrement mal la licence utilisée pour ce code, et si du code est volé par erreur, les mainteneurs n’ont pas le budget pour se défendre !

Quelques leçons que Juliette a tiré de son expérience :

  • Dire NON. Il n’est pas possible d’accepter toutes les propositions de la communauté et des décisions fermes doivent être prises pour assurer l’avenir du projet ;
  • Prendre des journées off, afin de prendre soin de soi et de sa santé mentale ;
  • Avoir des conversations avec des gens du projet en dehors de GitHub. Cela permet de prendre du recul.

Merci à Juliette pour ces nombreux conseils, l’écosystème open-source est un sujet qui nous tient à cœur chez JoliCode. Mention spéciale pour le thème d’Halloween de cette conférence ! 👻

Section intitulée une-gestion-dynamique-des-permissions-en-phpUne gestion dynamique des permissions en PHP

Marion Agé, développeuse chez les-tilleuls.coop, a pris le temps de revenir sur les différents concepts d’autorisation. Elle a poursuivi sa présentation en utilisant Symfony et les Voters, jusqu’à atteindre le point où ces derniers ne suffisent plus, car le métier exige une granularité des droits très fine, souvent objet par objet. C’est ainsi qu’elle nous a montré sa solution faite maison, qui s’adapte à de nombreuses situations. Elle a conclu sa présentation en nous expliquant comment partager les droits d’une application entre son backend et un frontend écrit en JavaScript.

Étant donné que cette présentation était très complète, il nous est impossible de la résumer succinctement. Nous vous invitons a lire ses slides.

Section intitulée how-to-eliminate-waste-in-your-development-processHow to Eliminate Waste in your Development Process

Nous sommes payés pour produire du code, créer de la valeur – et faire ça efficacement (sans perte, avec un rendement maximal) demande un peu d’organisation.

Le mythique 10x programmer existe : il code vite, sans test, tout le temps dans la zone. Il transforme le café en lignes de code ! Mais il ne répond pas aux emails, il merge trop vite, il bloque les PR, il code pendant les réunions : il génère de la valeur tout en créant, en parallèle, un énorme gachi et une dépendance forte : à long terme il produit de la perte.

C’est le sujet de la conférence de Matthias Noback qui va nous donner quelques bonnes pratiques sur l’amélioration de notre approche au code.

Matthias recommande fortement le pair-programming, qui semble prendre plus de temps mais qui est au final est plus rapide. En équipe composée d’un pilote et d’un ou de plusieurs navigateurs ; au début tout est frustrant mais très vite tout s’accélère et les features pleuvent ! On prend alors de meilleures décisions et on gagne même sur la code review puisqu’elle n’est plus nécessaire.

Le second point revient à s’assurer que nous pouvons délivrer la valeur créée par les développeurs rapidement. Si elle reste coincée derrière un test flaky, ou en attente de review pendant des semaines, il y a de la perte.

Le flux de livraison de la valeur est composé de nombreuses étapes :

  • on écrit une tâche / une issue ;
  • on écrit du code pour répondre au besoin ;
  • la CI / QA nous dit si c’est ok ;
  • nos pairs font une code review ;
  • la release est déployée.

Il faut s’assurer qu’aucune de ces étapes ne coince, regarder où est la perte. La dérivabilité est contrainte naturellement par la taille des tâches, l’attente de la CI, les bugs qui échappent aux tests… Mais il y a aussi des contraintes accidentelles :

  • forcer le numéro de ticket dans le commit ;
  • chaque issue doit être estimée ;
  • chaque membre de l’équipe doit être capable de prendre un ticket ;
  • on n’a pas le droit d’ajouter des issues dans le sprint en cours ;
  • on a besoin de 2 approval pour merger la PR…

Ces contraintes génèrent de la frustration et empêchent parfois de délivrer de la valeur et produisent de la perte.

Pour finir l’accent est mis sur le ✨ Continuous Delivery ✨, qui permet d’éliminer beaucoup de pertes dans les processus de review et déploiement. Mais avant d’arriver à un tel niveau de confiance, il y a du travail : les tests doivent être très complets, le déploiement robuste (si votre lead-dev crie “⚠️ ATTENTION JE DÉPLOIE” dans l’open-space c’est mauvais signe) et les PR toutes mergeable sans effets de bords (donc bien cloisonnées, bien scopées).

How to Eliminate Waste

Section intitulée php-particularly-horrible-programsPHP : Particularly Horrible Programs

Gina BANYARD, core contributrice PHP nous a fait un one woman show. Cette présentation à but humoristique a mis en lumière les faiblesses et les incohérences de PHP. Quelques petites pépites :

$a = 'Zz';
echo ++$a;
// AAa
var_dump('007' == '7');
// true
readonly class ReadOnlyClass
{
    public function __construct(
        public string $name,
        public int $age,
    ) {
    }

}

$object = new ReadOnlyClass('Can I change this?', 20);
$a = new ArrayObject($object);
$a['name'] = 'it looks like I can 😱';
$a['age'] = 'twenty'; // type changed!

var_dump($object);

//^ ReadOnlyClass^ {#2
//  +name: "it looks like I can 😱"
//  +age: "twenty"
//}

Et notre préféré pour finir :

$ php -n -d "disable_classes=Error"  -r "array_map(fn ($v) => $v, true);"

Notice: Accessing static property ParseError::$file as non static in Command line code on line 1

Deprecated: Creation of dynamic property ParseError::$file is deprecated in Command line code on line 1
Segmentation fault (core dumped)

Section intitulée gerer-de-gros-volume-de-donnees-avec-phpGérer de gros volume de données avec PHP

Joël

Double conférencier cette année, Joël est intervenu à la fin de la première journée pour exposer différentes stratégies à garder en tête au moment de traiter de gros volumes de données. Au travers d’expériences passées, il montre comment des problématiques qui semblaient initialement insurmontables peuvent, avec de l’analyse, du pragmatisme, du bon sens et un soupçon d’optimisations techniques, souvent être réduites pour grandement améliorer les performances dans le cadre de la gestion de gros volumes de données.

Après avoir tenté de définir ce qu’est un « gros » volume de données (nous n’avons pas forcément tous les mêmes références), Joël a parcouru plusieurs expériences passées, que ce soit au sein d’une marketplace ou dans le cadre de redirection.io, projet sur lequel il intervient fréquemment et qui présente des défis de volumétrie et de performance intéressants.

L’exemple de l’import de catalogue produit par les vendeurs d’une marketplace est intéressant, car la solution n’est pas que technique. Dans ce type d’import, les volumétries des offres sont importantes, car elles sont le produit cartésien du nombre de produits et du nombre de vendeurs. Les mises à jour des tarifs des produits se font donc vendeur par vendeur, par le biais d’import de (gros) fichiers CSV, dont pourtant la plus grosse partie ne change pas d’un import à l’autre. L’approche de résolution a consisté à chercher à ne plus traiter les lignes des imports qui ne changent pas : si le prix d’un produit est le même que dans l’import précédent, cela ne sert à rien de l’importer à nouveau ! Pour cela, la stratégie à suivre se passe en quelques étapes :

  • calculer un hash pour chaque ligne (type crc32) ;
  • créer une table temporaire avec LOAD DATA INFILE ;
  • utiliser les jointures SQL pour isoler les lignes ajoutées et supprimées ;
  • exporter ces lignes là précisément dans un fichier CSV, qui sera beaucoup plus petit que le fichier d’import original ;
  • importer ce fichier qui ne contient que des opérations réelles d’écriture.

Dans le cadre de redirection.io, Joël a montré comment l’utilisation de générateurs PHP et de différentes options permet d’optimiser la transmission de données de manière streamée depuis une base de données jusqu’à un logiciel qui consomme ces données, en passant par toutes les couches intermédiaires : API, réseau, etc.

Les différentes optimisations présentées pour cette approche « streamée » permettent ainsi, sur certaines opérations, de réduire de manière drastique la consommation de mémoire vive, tout en simplifiant l’architecture au point de permettre le retrait de certaines couches de cache qui ne sont plus nécessaires. Au-delà de meilleures performances et d’une meilleure scalabilité, la bonne compréhension du problème et des objectifs permet donc aussi de simplifier une architecture technique !

La conclusion principale de la présentation de Joël est donc : « il n’y a jamais de solution magique au traitement de gros volumes de données, et il s’agit en premier lieu de bien comprendre le besoin pour simplifier les problématiques ».

Section intitulée fin-de-journeeFin de journée

Cette première journée s’achève sur une conférence ovnie, des lightnings talks et un apéro dans Disney Village qui ne se racontent pas mais se vivent ! Il faut venir en profiter l’année prochaine si vous n’étiez pas des nôtres !

Le résumé des conférences du deuxième jour très bientôt sur vos écrans !


Cet article porte sur la conférence Forum PHP 2024.

Forum PHP 2024

Commentaires et discussions

Nos articles sur le même sujet

Nos formations sur ce sujet

Notre expertise est aussi disponible sous forme de formations professionnelles !

Voir toutes nos formations

Ces clients ont profité de notre expertise