Aller au contenu
AFUP AFUP Day 2025 Baromètre Planète PHP PUFA
 

Un moteur bien huilé

Description

Le Rule Engine est un puissant pattern qui nous permet d’implémenter des systèmes complexes de manière découplée, extensible et testable.

Découvrons comment nous avons implémenté des centaines de règles métier dans une application Symfony tout en gardant un code simple et lisible, notamment grâce à l’injection de dépendances.

Cela a permis de facilement s’adapter aux changements de besoin et de permettre des cas d'usages complexes (chaînage des règles, utilisation d'APIs, requêtes à la base de données, etc).

Conférence donnée lors du Forum PHP 2022, ayant eu lieu les 13 et 14 octobre 2022.

Informations complémentaires

Vidéo

Le speaker

Thibault RICHARD

Développeur lillois, Thibault est passionné par PHP et Symfony et amoureux de l'open-source. Co-maintainer de Bref, il est employé chez Wid'op où il oscille entre développement Symfony et missions devops, principalement sur AWS.

Verbatim

_ Bonjour, tout le monde. Aujourd'hui, nous allons parler du design pattern Rule Engine. J'aimerais commencer par un sondage. À main levée, qui a déjà fait des demandes à un organisme social ? La CAF ? Les demandes de bourse ? Gardez la main en l'air. J'ai 42 questions. Ça devrait aller vite. Qui a déjà loué un logement ? Qui a déjà fait une demande de prêt ? Qui a aimé ça ? Pour ceux qui ont gardé la main levée, on ne vous juge pas. Si vous avez déjà fait ce genre de demande, de démarche, vous avez sûrement été confrontés à ce genre de choses : veuillez nous fournir les documents suivants. Une pièce d'identité, etc. Dans la réalité, c'est ce qu'on vous demande de vous. Mais peut-être que derrière, les règles de gestion ressemblent plus à celles-ci. Si vous êtes français, on vous demande une pièce d'identité, mais si vous êtes étrangers, on vous demande un titre de séjour. Si vous êtes au chômage, une attestation de droits Pôle Emploi.

Nous avons dû implémenter ce genre de règles et bien d'autres comme nous le verrons tout au long de cette conférence. Pour un acteur du logement social français. Avec tout ce que cela implique.

Très rapidement, je vais passer, je suis développeur chez Wid'Op. Nous faisons du Symfony, du API Platform, de l'infrastructure. Nous pouvons en parler après cela. Je co-maintiens Bref. Je suis AWS Community builder. Je serais ravi d'en parler après la pause. Ou à la pause plutôt. Mais revenons-en à nos règles. Si on devait implémenter ces règles, une manière naïve de le faire, ce serait de créer une méthode comme celle-ci. On initialise un tableau de documents. Si l'utilisateur est français, on demande la pièce d'identité. Sinon, nous demandons le titre de séjour, etc. À la fin, nous retournons ce tableau de documents. Nous avons répondu au besoin métier. Nous sommes contents.

Le problème, c'est que c'est une implémentation naïve. Ça marche bien, il y a cinq règles et une condition pour chaque règle. Nous ne sommes pas trop embêtés. Mais la réalité des choses, c'est que nous aurons des conditions imbriquées et à rallonge. Nous aurons des calculs à faire à l'intérieur pour déterminer si une règle s'applique ou non. Nous allons avoir quelque chose qui sera dur à maintenir. Avoir du code spaghetti. Il y a un risque de créer des effets de bords. Si je veux modifier une règle, si nous avons quatre conditions imbriquées, est-ce que ça ne va pas péter autre chose ? C'est dur à tester.

Quand nous avons été confrontés à ce besoin, nous avons cherché une solution pour éviter d'en arriver là. Nous sommes tombés sur ce pattern. Rules Engine. Je le considère plus comme un concept comme un pattern. On peut mettre tout et n'importe quoi derrière. Il y a des services en sas qui proposent des Rule Engine, des librairies en PHP qui proposent des rule builders pour le moteur des règles. Nous pouvons faire quelque chose nous-mêmes.

Nous avons fait une implémentation maison. Nous avions un besoin simple au final. Du coup, nous n'avons pas besoin de cette complexité d'une interface et d'un système complet qui gérerait cela pour nous. Nous sommes dans des règles figées. C'est le logement social. Ce n'est pas une tarte. Le besoin ne change pas tous les jours. Le client ne veut pas avoir la main là-dessus. Ça évolue peu. Le client n'est pas technique. Lui donner une interface pour construire des règles aurait été de la formation, etc. Ça n'aurait pas été nécessaire. Ça nous aurait pris du temps.

Ce que je vous propose, c'est qu'aujourd'hui, nous passions en revue cette implémentation. Comment vous pouvez faire cela dans vos propres applications Symfony. Mais vous pouvez appliquer cela à du Laravel facilement.

Nous commençons par créer une interface qui représente notre règle. Il y a deux méthodes. "When", elle retourne un bullet un : vrai, la règle doit s'appliquer, faux, la règle ne s'applique pas. Une méthode "Zend on choisit un utilisateur et ça retourne le document. Nous avons une autre méthode when. Il y a aussi la méthode Zend par exemple, qui retourne le document ou la pièce d'identité.

Nous avons nos règles. Il y a maintenant un moteur. C'est celui qui va implémenter nos règles. Les évaluer. Nous voyons que notre moteur prend un tableau de règles, et la méthode get documents comme avant. On vient initialiser un tableau. Si la règle doit s'appliquer, on roule when, et le document est retourné par Rule Zend. Nous avons déjà quelque chose qui commence à prendre forme.

Malgré tout, nous sommes aux applications Symfony. Nous aimons le service Locator... non, je rigole. Nous aimons l'injection de dépendances. Nous allons essayer de brancher tout cela grâce à l'injection de dépendances Symfony. Je vais essayer de faire la configuration en huit. Je ne veux pas commencer avec du YAML. On ajoute ce tag. Tout ce qui implémente l'interface va se voir attribuer le Tag app.document rule dans l'injecteur de dépendances Symfony. Ça va permettre d'identifier toutes les classes.

La deuxième étape, c'est d'aller dans notre moteur et d'injecter tout ce qui est implémente l'interface. Tout ce qui a ce tag injection de dépendances.

Dans le constructeur et en attributes, nous venons mettre l'attribute tag litterator. L'attribute, c'est le même que nous avons vu avant. Nous venons ajouter les documents au tableau. Et nous avons un moteur qui fonctionne. Nous pouvons l'utiliser ici dans un contrôleur. Nous l'injectons avec l'injection de dépendances dans notre constructeur. Après, nous récupérons l'utilisateur courant et on le passe au moteur. Tout cela au format Json. Nous venons de créer une API qui va nous retourner les documents pour cet utilisateur.

Nous venons de créer notre premier Rule Engine sur ce document.

J'aimerais qu'on revienne sur cette classe-là où tout se passe. C'est là où nous venons définir nos règles. Nous pouvons en tirer quelques caractéristiques. Nous voyons que c'est quelque chose de lisible. Nous avons une dizaine de lignes de codes. Les conditions sont simples. Nous avons la chance d'avoir dans notre user des méthodes assez bien foutues qui nous disent que l'utilisateur est français ou pas. Mais la méthode est lisible. C'est implémentable facilement. Les méthodes sont isolées. Il n'y a pas 15 chemins possibles dans une méthode. On voit si l'utilisateur en question a besoin d'une pièce d'identité ou non. On peut le faire pour le titre de séjour, la fiche de paye, tous les documents nécessaires. Si demain, cette règle n'a plus lieu d'exister, nous supprimons le fichier. La règle ne s'applique plus. Nous avons tout automatisé avec l'injection de dépendances Symfony. Nous ajoutons une règle qui implémente l'interface. Elle sort du système et elle n'existe plus. Et on ne va impacter que cette règle. Que nous n'aurons pas d'effet de bords très bizarre.

Si nous avons plusieurs règlent qui s'appliquent en français. Nous serons obligés de dupliquer cette condition sur toutes nos règles. Faire des PO pour refactoriser cela.

C'était notre premier cas d'usage. Générer des listes de documents. Mais nous avons bien aimé le système. Nous voulons l'appliquer partout. Le deuxième cas d'usage, ça a été de faire des calculs.

J'aime bien les sondages. On va pouvoir faire un deuxième sondage. Je ne sais pas si vous serez aussi nombreux à lever la main. Qui est capable de me dire quel est le taux de vacances moyennes structurelles ? Même moi, je ne pourrais pas vous ressortir la définition. (lecture du PowerPoint). Des règles comme cela, nous en avions des centaines. Ça a été marrant à implémenter. Mais ce sont des règles... les calculs de dates, on nous a demandé des pourcentages de date. Je vous laisse deviner ce que ça peut être en pourcentage de dates. Il nous a fallu du temps pour comprendre. Du coup, encore une fois, le client n'était pas vraiment en mesure d'implémenter cela. Ça aurait été difficile de fournir une interface et d'avoir quelque chose qui serait compréhensible par une machine à la fin. Nous avons implémenté ces règles nous-mêmes. Nous avons appliqué le même pattern. Nous avons créé une interface pour les règles de calcul. La méthode when et la méthode zend qui ne retourne rien. Nous avons eu une opération. Mais le principe de base reste le même. Nous avons toujours notre auto configure tag, on pense mettre un nouveau thème. Globalement, nous avons la même chose.

Petit disclaimer : Les prochaines slides peuvent choquer la sensibilité de certains spectateurs. Ce n'est rien de gore. C'est du code en français. Parce que vous vous doutez bien que dans le logement social, il y a beaucoup de jargon. Des règles comme cela, nous en avions des centaines avec leur jargon. Ça nous semble plus pertinent d'avoir du code en français pour être au plus proche du métier. Je clos la parenthèse. C'est notre règle sur le taux de vacances moyennes structurelles. Nous initialisons un compteur, nous venons boucler pour les bâtiments démolis, pour chaque bâtiment, nous ajoutons le nombre de LLS. Quand nous avons bouclé, nous avons un deuxième compteur. Nous venons faire le taux de vacances moyennes structurelles. Pour appliquer la règle de calcul.

Le principe de base est le même. Mais fondamentalement, c'est différent. On ne retourne rien, mais nous venons muter l'objet qui est passé en paramètres. Ça a été un deuxième cas d'usage similaire, mais différent dans le principe sur lequel il interagit avec le reste du système.

Il y a autre chose que vous ne pouvez pas voir. Des trucs bizarres sur cette ligne. Vous ne pouvez pas vous en rendre compte. Ça, c'est une donnée calculée. Ça implique une nouvelle notion. La notion de chaînage. Nous avions des règles qui dépendaient d'autres valeurs qui étaient elles-mêmes calculées. Encore une fois, dans notre cas, le besoin était simple. Pour l'affaire rapide, dans l'interface, nous avions un formulaire à étapes, les données de l'étape deux pouvaient dépendre de l'étape une, celles de l'étape trois pouvaient dépendre de l'étape une ou deux. Nous sommes partis sur un système de pondération des règles de priorité. Nous avons ajouté dans notre interface une méthode get priority. Nous venons trier sur cette priorité.

Nous pourrions imaginer des choses un peu plus complexes. Mais c'était un moyen simple et pragmatique d'implémenter cela. Dans notre engine sur les règles de calcul, nous valons toujours boucler sur les règles. Nous n'initialisons pas de tableau. Dans le constructeur, nous venons modifier l'attribute, c'est Symfony qui vient faire le travail à notre place. Merci, Symfony. Sur l'étape une, il y a la priorité 100, puis 200, 300 selon les étapes. Nous avons géré le chaînage assez facilement comme cela.

Il y a quand même quelques inconvénients à cette manière de faire. C'est fragile. Dans la manière de l'implémenter. Dans notre cas, ce n'était pas trop problématique parce que nous avions cette question d'étapes. Mais nous pourrions avoir des graphes de dépendance. Les dépendances sont implicites et sont basées sur les étapes. Dans notre système, rien ne dit qu'une règle dépend d'une autre. Nous n'avons pas de lien. Rien ne nous indique que le nombre de LLS était une donnée calculée aussi.

Nous pourrions imaginer des choses plus complexes aussi. Ce que fait Doctrine Fixtures. Vous avez dû le voir dans Symfony. Vous pouvez mettre get impedencies. On pourrait mettre quelque chose de similaire dans notre moteur de règles. Mais nous avons choisi de nous épargner cette complexité.

Nous revenons dans notre règle, notre donnée est calculée. On peut faire le reste. La particularité, c'est que la donnée n'est pas calculée comme les autres. Elle est chiante parce qu'il y a du chaînage. Et elle vient d'une API. Il a fallu composer avec cela. Ce qu'on peut faire, nous sommes dans une application Symfony. Depuis pas mal de versions Symfony maintenant, il y a des choses qui sont bien sympas. L'autoconfiguring : tout ce qui est dans votre dossier SRC est un service. Il peut être injecté quelque part et recevoir de l'injection de dépendances. Dans notre règle, nous venons injecter un repository doctrine. Nous pouvons l'utiliser et faire un count pour récupérer la donnée non pas de manière à répéter comme nous faisions avant, mais en faisant travailler notre base de données. Dans notre cas, c'était plutôt avec une API. On injecte API, on fait un 7, le nombre de logements. Il y a peu de limites. Ça peut venir de l'API, ça peut venir d'un cache. De tout ce que vous voulez au final. Ça ouvre vraiment les possibilités de ce système. Nous ne sommes pas contraints de ne faire que des opérations arithmétiques ou des conditions. Mais des choses avancées.

Mais attention à la dérive. À commencer à penser d'envoyer des mails et faire des trucs dans Mercure et dans Messenger ça pourrait partir dans la mauvaise direction. Mais sur le principe, ça permet de refactoriser une partie de notre logique dans des services.

C'était notre deuxième cas d'usage. Le premier, gérer une liste. Faire des calculs, imiter un objet.

Le troisième cas d'usage auquel nous avons pu appliquer ce design pattern, c'est un to-do list. C'est une bonne to-do list administrative à la française. Nous voyons avant des opérations. Dans notre application, ça représente des applications sur des logements sociaux. Ou la construction d'un nouveau parc de logements, la rénovation de certains logements. Ça peut être la démolition de logements vieillissants, etc. Il y a tout un enchaînement d'étapes pour réaliser ces opérations. Cette to-do list, c'était les jalons, les tâches. Une règle que nous avions, c'était le dépôt du dossier. Quand vous voulez faire une opération, six mois avant le lancement de cette opération, le début de la démolition des bâtiments, il faut déposer un dossier auprès de certains organismes pour déclarer cette opération. Nous avions la même chose pour les permis de construire, les demandes diverses et variées qui dépendaient du type d'opération. On ne va pas demander un permis de construire pour refaire de la peinture à l'intérieur des bâtiments. Etc.

Après, nous avions des dates de clôture. Une fois que nous avons déposé le dossier, que nous avons une date de dépôt dans notre opération, nous considérons que nous avons effectué cette tâche.

Après, nous avions des alertes qui s'affichaient dans l'interface pour dire : Attention. Vous avez moins de quatre mois, deux mois. Vous avez raté la date. Vous n'avez pas déposé le dossier alors que vous auriez dû commencer l'opération.

Encore une fois, nous avons appliqué le même pattern. Mais cette fois-ci, ça n'entrait pas dans le moule du when, zend, parce qu'on avait différentes conditions. Mais nous les avons matérialisées dans notre interface. Elle reprend trois méthodes. Chute display, chute close, chute alerte qui dit s'il y a un niveau d'alerte. Nous n'avons pas une seule méthode qui applique notre règle comme c'était le cas avec zend dans les exemples précédents. Nous avons décidé de déporter cette logique à l'intérieur même du moteur. Nous venons toujours initialiser un tableau de tâches pour récupérer les tâches réalisées. Nous venons boucler les tâches de la même manière. Mais nous venons d'abord évaluer si la règle doit s'afficher. Si elle doit s'afficher, on vérifie si elle doit être clôturée. Nous pouvons être six mois avant, mais avoir déjà déposé le dossier. La règle est clôturée. Nous générons une tâche clôturée et nous continuons. Pour éviter de faire ce qui est en dessous. Pour passer à la règle suivante.

Pareil pour le niveau d'alerte. On peut avoir une tâche qui est commencée, qui devrait s'afficher, mais qui est à un niveau d'alerte. Nous devrions générer une tâche avec un niveau d'alerte. Si elle n'est pas clôturée et qu'elle n'est pas en alerte, nous venons générer une tâche à réaliser. Nous retournons notre tableau de tâches que nous avons générées.

Nous venons déporter la logique de traitement dans notre moteur. Il n'est pas bête et méchant. Il a de l'intelligence. Ça permet de ne pas avoir cette logique à l'intérieur de chaque règle. Mais avoir une séparation. La règle dicte quelles sont les conditions d'affichage clôturées. Après, c'est le moteur qui s'occupe d'interpréter ces différentes conditions.

En quelques chiffres, sur l'application de manière générale, nous avons implémenté 47 + 92 documents. Nous avions deux cas où nous avions des listes de documents à générer. Ça représente 3000 et plus de lignes de codes. 6300 lignes de code. Il y avait pas mal de choses qui étaient refactorisées. Nous avions 65 tâches avec les conditions d'affichage et d'alerte. C'est modéré, critique. C'était 3000 lignes de code pour chaque tâche. Au total, plus de 12 000 lignes de code pour tout cela. Ce sont des jours et des jours de souffrance à implémenter toutes ces règles. Comprendre comment ça devait se comporter.

Pour conclure, globalement, repasser en revue tout ce qu'on vient de se dire, déjà, j'espère que je vous ai appris un petit peu ce que c'est le pattern Rule Engine. Et comment on peut l'implémenter dans une application Symfony assez simplement. J'espère que vous avez pu voir aussi que c'est simple à mettre en place aussi, mais à tester. Nous avons quelque chose qui est adaptable à vos besoins réels. Que ce soit pour générer des listes comme pour nos documents, muter des objets comme pour nos calculs, ou encore déporter cette logique dans le moteur pour avoir un moteur qui ne fait pas juste évaluer des règles, mais qui vient aussi porter une partie de l'intelligence de ce système. Nous avons aussi la possibilité d'ajouter du chaînage, de manière simple avec des priorités ou de manière plus complexe. Dans ce cas, je vous laisse vous débrouiller. Étendre la logique avec des services, des repository, du HTTP client. Tout ce que vous voulez dans la limite du raisonnable. C'est adaptable aux besoins. On peut imaginer de mettre plus de PO là-dedans pour faire de la composition, de l'abstraction. Implémenter différentes pratiques que nous avons l'habitude d'utiliser en PO.

N'hésitez pas à laisser un feed-back. C'est important. C'est ma première conférence grand public comme cela. C'est important pour moi d'avoir un retour. Merci pour votre attention. Vous pouvez me suivre sur Twitter. Je suis aussi sur le Slack Symfony et le Slack Bref. Vous pouvez m'envoyer des lettres d'amour. N'hésitez pas. Je suis là sur les deux jours. Merci beaucoup.

(applaudissements)

_ Nous avons du temps pour pas mal de questions.

_ Salut. J'ai une question qui pourrait se résumer à : pourquoi when ? Est-ce que ce n'est pas un souci d'avoir un moteur externe à règle qui définit quand elle doit s'appliquer et ne pas tout laisser dans la classe ? C'est-à-dire que tu n'aurais qu'une seule méthode ?

_ Je comprends ce que tu veux dire. Nous sommes partis sur ce principe au début. Nous étions avec Symfony et des méthodes support. Nous l'avons implémenté comme cela. Nous l'avons légèrement regretté à certains moments. Tu as raison, on vient déporter cette logique à l'extérieur de la classe. Nous avons une classe qui est pilotée depuis l'extérieur. Aussi pour ceux qui utilisent PHP stat, ça pose problème pour l'analyse statistique. Si on reprend les règles du début où on dit : L'utilisateur est français, si on vient refaire des vérifications sur les champs parce que certaines valeurs n'étaient pas nulles, nos analyseurs statiques n'ont aucun moyen de savoir que la méthode zend a forcément été appelée avant la méthode when et que la méthode when sera appliquée après la zend. Nous aurions peut-être dû faire une méthode uply*. On met return. Elle ne doit pas forcément s'appliquer, mais sinon, fait son taf. Est-ce que ça répond aux questions ?

_ Bonjour, merci pour la présentation. C'était intéressant. J'espère que ça va rendre l'utilisation des organismes publics plus intéressante. Ma question : Avec toutes ces règles, est-ce qu'il y a une stratégie de tests automatisés ou autre pour rendre le truc le moins fragile ?

_ Nous aurions aimé. Comme sur beaucoup de projets, il y a toujours des contraintes de délai, de budget, etc. qui font que les tests, ce n'est pas très simple. Sur ce projet, j'ai dit que c'était testable, mais nous n'avons pas pu tester. Nous aurions aimé. Nous avons eu la chance d'avoir très peu de bugs. L'expression du besoin était claire. Nous venions remplacer quelque chose qu'ils faisaient déjà au quotidien. Ils étaient capables de détecter les problèmes. C'est un métier qu'ils connaissent. Ils ont été capables de valider que nous avions respecté les contraintes. Mais les tests nous auraient soulagés dans la mise en place. Mais nous n'avons pas eu l'occasion de le faire. Mais je pense que c'est facile à tester. Il y a des choses très isolées qui font peu de choses. Nous sommes capables d'aller tester notre règle unitairement. Si je passe un utilisateur français, est-ce que j'ai une pièce d'identité ? Pour un étranger, est-ce qu'il me retourne une carte de séjour ? Avec des lots de données différentes. Le passer en entrée et voir si j'ai en sortie ce qui est attendu.

_ Bonjour, merci. Est-ce que vous avez identifié une opportunité d'autodocumentation et de traçabilité ? Ce que je veux expliquer, c'est que quand les règles vont s'appliquer, la capacité sur l'interface de comprendre : Voici la règle qui s'est appliquée avec ces critères. Le deuxième point : Voici l'ensemble des règles d'un point de vue traçabilité et audit qui s'est appliqué. Est-ce qu'il y a une opportunité ?

_ Je pense que l'opportunité est là. Nous pourrions mettre du tracing dans notre moteur. Il vient évaluer toutes nos règles. Nous pouvons identifier facilement quelle règle est appliquée et quelle règle ne s'est pas appliquée. Ce que nous avions en entrée. Qu'est-ce qu'on a en sortie ? Dans le cadre des calculs. Ce n'est pas quelque chose que nous avons eu à faire. Mais je pense qu'on peut mettre cette intelligence au niveau du moteur assez facilement. Pour dire : voici la liste des règles qui se sont appliquées. Pour les déboguer. Comprendre ce qui s'est appliqué ou non. Ou on pourrait donner des noms à nos règles. Au niveau métier. Au niveau des calculs, ça pourrait être quelque chose d'intéressant. Ce n'était pas un besoin exprimé. Mais nous pourrions émettre cela. Si le besoin se présentait. La force de ce truc, c'est que le code est simple. À mettre en place. En même temps, nous avons cette flexibilité. Ce n'est pas une librairie qui nous contraint. Nous faisons ce que nous voulons. Nous l'avons vu, nous avons des cas d'usage différents. Ils entrent dans le même moule. Mais pour les tâches, nous avons tenté de déporter dans le moteur, ça marche très bien. Nous pourrions facilement ajouter cela.

_ E-ce que c'est à Open Source ? Est-ce que tout le monde peut contribuer ?

_ J'ai présenté en préparant le talk. Est-ce que ça ne pourrait pas être une librairie ? C'est tellement simple à mettre en place. Nous créons une interface, un moteur. Le reste, ce sont des règles. Que ce soit le moteur ou les interfaces, l'interface, c'est cinq lignes et le moteur en fait 20. Je ne voyais pas vraiment l'opportunité de venir automatiser, de venir généraliser le principe. Nous viendrions créer une usine à gaz pour des cas. Comme si on supportait tous les cas. Muter des objets. Je pense que ce serait plus compliqué d'avoir un truc Open Source que de l'implémenter soi-même. Je n'ai pas vu l'opportunité de créer quelque chose autour de cela. Nous pourrions. Le mettre en place dans sa manière la plus simple, justement, c'est simple à faire dans n'importe quelle Symfony. N'importe qui peut dire : Lundi matin, j'arrive et je le mets en place. Le plus compliqué, c'est de créer les règles. Le moteur est pas bête et méchant. Au plaisir de discuter après dans les couloirs. Ça pourrait être intéressant. Mais je n'ai pas vu le truc. Je ne sais pas si ça répond à ta question ?

_ Bonjour et merci. Est-ce que vous avez étudié l'utilisation du pattern spécifications ? Combiner éventuellement les règles métier entre elles pour agréer les différentes règles métiers avec des connecteurs logiques ?

_ Pour l'instant, les règles sont indépendantes. Il y a du chaînage, mais il n'y a pas : Si cette règle s'applique, nous viendrions appliquer une autre règle. Ça ouvrirait une porte à des "ou/et". C'était cela notre besoin. L'opportunité ne s'est pas présentée pour aller creuser dans cette direction. Il faudrait voir à quel point ce serait simple compliqué à mettre en place. Mais je pense que tu entres dans quelque chose qui est plus compliqué à mettre en place. Créé beaucoup d'embranchements possibles. Mais nous n'avons pas eu l'occasion de creuser cela.

_ Je suis là. J'ai une question. Dans la slide, il y avait l'usage de l'attribute PHP8. Est-ce que d'un point de vue performance, c'est mieux de redescendre toutes les conf YAML dans tout le code plutôt que de laisser dans le service ?

_ Est-ce que c'est mieux de faire la configuration en attribute ou YAML ? Est-ce qu'il y a un impact de performance ? Je n'ai pas creusé le sujet, mais de ce que j'en comprends, l'injection de dépendances va générer cela. Le conteneur est généré une fois. Il va générer le tag litterator et il va gérer les dossiers, les mettre en cache. Il y a peut-être un impact de performance pour le conteneur. Je ne suis pas sûr. Mais au runtime, je ne suis pas sûr. Parce que tout est en cache dans l'injection de dépendances.

_ Encore une question, si vous voulez.

_ Bonjour. Vous avez parlé de toutes les règles que vous avez implémentées. Nous avons vu des situations où ça se passait bien. Comment vous avez géré les erreurs ? Les cas où ça n'entre pas dans ces règles ?

_ Je ne suis pas sûr de comprendre la question. Si une règle ne s'applique pas, on passe à la suivante. Comment on gère les erreurs dans le code, déjà, nous avons mis... nous l'avons enlevé ici, mais nous avons mis de l'analyse statistique sur tout le projet. Pour s'assurer que nous n'avions pas des appels à des variables nulles. Nous avions beaucoup de conditions pour vérifier ce genre de choses. Mais nous n'avions pas de gestion des erreurs à proprement... spécifiques à cette partie. C'est de la gestion d'erreurs classique. C'est des erreurs de cas. Nous savons à quoi ça ressemble, nous n'avons pas beaucoup de surprises sur ce qui est possible ou non. Nous avons nos entités qui ont des retours. Si ça peut être nul, ça retournera nul. Le typing est correct. Avec l'analyse statique, nous avons été capables d'identifier les éventuels problèmes. Dans toutes nos when, les règles, il y avait pas mal de vérifications : Est-ce que j'ai cette donnée ? Cette donnée ? Pour que la règle puisse s'appliquer ? C'est le problème que je remontais au début. On se retrouvait à faire les mêmes vérifications dans le when et le zend pour faire de l'analyse static. Mais si la variable peut être nulle, le cas est facilement géré. Nous avons mis l'analyse static pour qu'on remonte facilement ces erreurs. Mais nous avions de la gestion d'erreurs autour de cela aussi. Mais rien de particulier au niveau du moteur au final. C'est plutôt de la gestion d'erreur qui s'appliquerait à l'application de manière générale. Je ne sais pas si ça répond à ta question ?

_ Merci beaucoup. Rendez-vous sur Open Feedback pour donner des retours. Maintenant, place à la pause. Nous vous retrouvons tout à l'heure pour : Les femmes à barbe et à capuche sortent de la grotte pour sauver le numérique et son impact.