cet article si vous voulez en savoir plus).
Comment ça marche ?
En architecture hexagonale, on va chercher à isoler le métier en le faisant interagir avec des dépendances extérieures via des interfaces. Ensuite lorsque l’on va mettre en place nos dépendances, celles-ci vont implémenter les interfaces. Ainsi le domaine métier reste toujours isolé et maître de son comportement.
Une technique simple au départ d’un projet sera d’implémenter ces interfaces avec des modèles In-Memory : des listes, maps, etc. Elles pourront très simplement répondre au besoin métier, nous permettant de livrer quelque chose de testable par les utilisateurs. Il faudra sans doute les remplacer à terme par une base persistante. À ce moment-là on aura déjà validé le cœur de l’application.
Exemple
Sur une application qui gère des utilisateurs, on commence par définir notre architecture hexagonale avec un usecase qui va dépendre de l’interface UserRepository du domaine métier :
On observe que les imports viennent uniquement du domaine : on sépare le métier des implémentations techniques.
Jetons alors un oeil à l’interface UserRepository :
Une fois que notre use-case et notre métier sont définis, on va pouvoir faire une première implémentation du Repository en utilisant une solution In Memory. Celle-ci est basique mais va nous permettre de valider le métier avant de nous poser la question du type de base de données à connecter.
Lorsque nous voudrons injecter les dépendances, nous pourrons utiliser cette implémentation dans un premier temps.
Pour voir le détail : https://github.com/jozolr/retarder-les-choix-structurants
Définition
Un spike s’apparente à un POC dans le sens où il permet de prouver ou infirmer des hypothèses. Là où il va se différencier est le contexte dans lequel on va le mettre en place : un spike s’intègre dans la vie d’un projet. Quand un POC permet d’évaluer la faisabilité d’un projet/produit, un spike va tenter de répondre à un problème unique en se débarrassant de toute autre hypothèse dans le cadre d’un projet/produit
Pourquoi ?
Grâce à des modèles In-Memory couplés à de l’architecture hexagonale, on se met en capacité d’intégrer plus tard des services dans un projet. Une des difficultés qui va apparaître est d’être capable de tester ces services pour choisir le plus adapté. Comme de nouvelles technologies, librairies ou architectures vont régulièrement sortir il est difficile voire impossible de les anticiper. Si on ajoute une tâche technique au backlog, celle-ci sera difficile à estimer car elle comportera beaucoup d’inconnues. Pour se donner les moyens de tester et de s’améliorer en permanence tout en limitant les inconnues nous pouvons utiliser des spikes. Cette technique permet de se découpler des problématiques d’un projet et de nous aider à tester et mettre en place ce qui est nécessaire quand c’est nécessaire.
Comment ça marche ?
L’idée est de s’isoler du projet sur lequel on est pour ne pas être impacté par des éléments extérieurs à ce qu’on veut tester. On peut y parvenir en créant un nouveau projet vierge et en implémentant directement la nouvelle technologie ou le nouveau concept. Les points d’attention sont :
Il est possible et conseillé d’intégrer des tâches de type spike dans le backlog d’un projet. Ils représentent en quelque sorte une R&D qui permet à l’équipe de monter en compétences et de s’investir. Ce format a un autre avantage : c’est un travail de capitalisation dont les résultats sont utilisables au-delà d’un seul projet.
Exemple
Pour l’exemple précédent sur l’isolation de dépendance, nous avons bootstrappé une application dont l’unique objectif est de faire un focus sur l’isolation des dépendances. Ce spike est maintenant présent dans un repository, a démontré la faisabilité d’une telle technique, et pourra être partagé.
Un autre exemple que nous avons pu appliquer sur un de nos projets : la mise en place d’un outil de migration de base de données. Au début du projet nous n’avions pas de besoin de l’avoir pour valider les premières features métier, alors nous avons repoussé sa mise en place. Lorsque les premières douleurs sont ressenties, nous avons regardé ce qui se faisait. Avant de se lancer sur une tâche technique, nous avons effectué un spike pour tester une solution, Flyway, en dehors du contexte métier du projet. En une journée nous avions validé son fonctionnement et avions une idée claire de la manière de l'intégrer au projet.
Dans le cas où le spike est un NO GO, il faut le voir comme du temps gagné sur le projet : on aura invalidé rapidement une hypothèse sans ajouter de dette à l’application. C’est l’idée du fail fast : on limite l’impact des erreurs en les ayant au plus tôt.
Source: http://www.extremeprogramming.org/rules/spike.html
Pourquoi ?
En utilisant des spikes on prend l’habitude de tester et d’intégrer des nouveaux concepts régulièrement dans nos applications. Cantonné au code applicatif on sera cependant limité : si j’ai besoin d’utiliser au bout de quelques mois une base de données je devrais me coordonner avec les équipes ops pour le déploiement. Quand cela concerne des environnements de développement, c’est une contrainte qui fait perdre en souplesse.
Dans un schéma “classique” où les développeurs vont livrer des artefacts applicatifs, et les ops vont les deployer, on se retrouve avec une synchronisation complexe entre les deux parties. Cela peut amener à essayer de mettre au plus vite en place une stack d’infrastructure qui aura le défaut d’apporter une inertie importante. Afin de maintenir des échanges efficaces entre les équipes, et de garder de la flexibilité sur la mise en place de nouvelles couches d’infrastructure, on peut utiliser de l’infrastructure as code. Ce code est présent dans un repository partagé par les développeurs et les ops.
Quand cela est possible, on obtient la même flexibilité à livrer des features applicatives que des services au sein de l’écosystème. Cela laisse donc la possibilité de retarder la mise en place de services annexes (base de données, file de messages, etc) lorsque l’on en aura réellement besoin, et lorsque l’on sera capable de juger de la meilleure solution technique.
Comment ça marche ?
Pour livrer et déployer des artefacts, on peut utiliser des pipelines de déploiement. Celles-ci vont décrire les étapes successives pour construire et livrer les artefacts au sein de l’infrastructure. Elles peuvent notamment être décrites en tant que code, et donc être à la main des ops et des développeurs.
Que l’infrastructure soit composée de machines virtuelles dans lesquelles on va exécuter un script Ansible, ou d’un cluster Kubernetes où l’on va appliquer des scripts de configuration, les contextes sont nombreux pour nous permettre d’avoir ce “terrain partagé”.
Un développeur peut alors décrire le déploiement d’une base de données, d’un nouveau service ou d’une nouvelle application au sein de l'écosystème de manière autonome. Il pourra indiquer sa configuration dans le script de déploiement et sa fonctionnalité sera livrée intégralement.
Cette technique est plus complexe à mettre en place que les précédentes : elle nécessite d’avoir une organisation souple entre la partie applicative et infrastructure. Cependant à partir du moment où elle est en place l’autonomie des équipes permet un gain en agilité qui va amener un rythme de livraison rapide. Cette autonomie est primordiale pour optimiser au mieux les développements. Celle-ci est détaillée dans l’ouvrage Accelerate: The Science Behind Devops qui démontre l’importance de casser le mur entre développeurs et ops (si vous voulez en savoir plus, cet article le résume).
Développer un produit nous amène à répondre à plusieurs questions :
Aujourd’hui, le constat est que ce qui a vocation à subsister dans le temps, ce n’est pas les technologies mais le cœur du métier. Alors pour nous adapter, nous avons vu 3 techniques qui nous servent à retarder au plus tard les choix techniques non-structurants, et à valoriser ce qui doit être le plus important, à savoir le métier.
Isoler les dépendances par un modèle In-Memory
Comment s’assurer que le focus d’un début de projet se fera sur le cœur des fonctionnalités métier ? Par l’utilisation d’architecture hexagonale et du modèle In-Memory. Cette technique est la plus activable, vous pouvez dès demain l’utiliser sur votre projet !
Utiliser des spikes
Comment se donner la possibilité de tester et innover le long d’un projet sans le mettre en risque ? Via l’utilisation de Spikes. Cela demande une structuration de vos process pour laisser la liberté aux équipes d’explorer avec des objectifs précis et atteignables.
Infrastructure as code
Le mur entre le métier et les développeurs a été cassé avec l’agilité, l’étape suivante est de briser celui avec les ops avec de l’infrastructure as code. Cela amènera une capacité de livrer rapidement et d’avoir des feedbacks plus rapides, et ainsi de maintenir la capacité à innover.