Du Domain Driven Design pour Speckit ?

Dans le premier article de cette série, nous avons décrit plusieurs stades de maturité du développeur augmenté. Par l'exemple avec Speckit, nous avons montré les avantages d'un tel outil pour garantir la pérennité d'un projet IT en bonne santé.
Le framework est à ce jour parmi les plus expérimentés (122K stars sur Github là maintenant). Cependant, face à d'autres tels que BMAD notamment, il peut paraître moins adapté au Brownfield, et plus à l'aise sur la création from scratch. Chacun ses avantages et inconvénients, l'expérimentation mondiale actuelle autour de ces solutions de génération de code par IA répondra tôt ou tard à la grande question de savoir quelle méthode ou framework va l'emporter pour devenir le standard du développement du futur. Ou bien si un standard émergera vraiment.
Et comme Speckit présente de réels avantages, voyons si l'on peut travailler sur ses faiblesses. C'est une réflexion est en cours ouverte à la critique. Voyons point par point, le constat du problème et des propositions de solutions.
La hiérarchie des fichiers
Les premiers essais avec Speckit sont encourageants. Tout est structuré, à sa place. Puis à chaque nouvelle demande d'évolution de votre code, Speckit crée un nouveau répertoire dans lequel il va générer et stocker les spécifications, plans d'implémentation, tâches...
Si vous envisagez un cycle en V c'est parfait. Vous donnez votre cahier des charges en paramètre d'un /speckit.specify et vous déroulez le cycle un minimum de fois. Mais si l'on veut démarrer vite, l'arborescence des spécifications et tests devient illisible et on fait une croix sur l'expérience humaine. Et dans une équipe de 4 ou 5 développeurs c'est problématique. La combinatoire développeur x prompt donne naissance à une myriade de répertoires qui potentiellement se recouvrent fonctionnellement ou techniquement. La tendance naturelle qui en découle est donc de préparer son prompt le plus possible pour minimiser le nombre de jets avant de parvenir au résultat, et donc de retomber dans un cycle en V.
Pourquoi c'est un problème ? Comme nous l'avons vu dans le premier article Comment l'IA redéfinit la QA avec Speckit, ces répertoires contiennent spécifications et tests d'acceptance. On peut alors se retrouver avec des incohérences ou des doublons si une même feature est éclatée dans plusieurs dossiers. Le skill /speckit.analyze est censé pallier ce problème, mais il n'est pas infaillible et surtout il intervient a posteriori, et si on pense à le déclencher (il n'est pas obligatoire). Et je préfère garantir la consistance de ma spécification car encore souvent, c'est encore elle qui fait foi "contractuellement".
Comment faire ?
La capture d'écran précédente montre l'évolution de la spécification de notre application de prise de rendez-vous depuis le 1er article. Forcément, le temps a passé et les features se sont multipliées. Admettons qu'aujourd'hui, nous souhaitions apporter une modification en triant la liste des praticiens par proximité décroissante par rapport à l'utilisateur. Quelle est la spécification concernée ?
001-pro-client-booking ?
003-lazy-days-loading ?
005-nearby-practitioner-agendas ?
Pourrions-nous rendre cette arborescence plus lisible, pour savoir instantanément quelle spécification porte la logique de construction de la liste des praticiens, et connaître rapidement les tests d'acceptance concernés ?
Imaginons un nouveau skill /speckit-design qui à ce stade du projet, permettrait d'analyser les spécifications existantes pour identifier les domaines métier :
et qui créerait une nouvelle arborescence de spécifications avec un seul sous-répertoire et un seul fichier de spec (vide pour le moment) par domaine. Si nécessaire, le skill poserait des questions pour identifier le ou les bons domaines liés à la demande, sur le modèle de /speckit.clarify :
Le skill a aussi généré un descripteur domain-map.md des domaines métier, des relations entre eux, et du mapping des anciens répertoires de specs vers les nouveaux domaines.
Le skill a généré aussi une proposition de modèle d'information commun :
C'est déjà plus propre. Mais comment faire avec notre legacy de 1 an de fichiers de spécification ?
Imaginons donc un autre skill /speckit-spec-refactor qui irait identifier dans les anciennes spécifications les impacts dans chaque domaine
et qui rangerait au bon endroit chaque US, chaque test. Idéalement, ce skill one-shot ne devrait pas simplement copier-coller les anciennes spécifications dans la nouvelle arborescence, mais devrait aussi les réécrire par domaine.
Une fois le travail terminé, on ne se base plus sur les anciennes spécifications, mais uniquement sur les spécifications par domaine. Il faut inscrire dans la constitution que toute demande doit désormais être routée vers les spécifications par domaine :
VI. Frontières DDD et autonomie des domaines
Le modèle métier et les frontières de domaines priment sur la commodité technique.
Toute fonctionnalité DOIT être rattachée à un domaine métier explicite (specs/domains/<domain>).
Les bounded contexts DOIVENT rester autonomes: vocabulaire, invariants, et règles propres.
Le partage direct de modèles entre domaines DOIT être évité; utiliser des contrats explicites et/ou une couche d’anti-corruption.
La duplication de code entre domaines est AUTORISÉE (et peut être préférée) lorsqu’elle protège la clarté des frontières métier.
Un composant "commun" n’est acceptable que s’il représente une capacité réellement partagée et non une fuite de frontière.
Essayons maintenant de réaliser notre nouvelle évolution :
/speckit-specify la liste des praticiens doit être triée par proximité par rapport à l'adresse géolocalisée ou saisie par l'utilisateur
Le skill ignore la spécification legacy, et se concentre sur l'impact à apporter aux spécifications par domaine. Il identifie d'abord le(s) domaine(s) concerné(s) par ma demande :
Puis speckit retravaille uniquement la spécification du domaine en ajoutant les règles de gestion nécessaires :
Ensuite appelons le skill /speckit-plan :
et enfin, /speckit-tasks et /speckit-implement pour se concentrer sur le plan généré. Et hop, notre évolution est réalisée, les praticiens sont triés par distance croissante.
C'est moche, essayons d'arranger ce layout :
/speckit-specify Refonte de l'interface utilisateur (UX/UI) pour optimiser l'espace et la disposition de la liste des praticiens.
Densifie la liste des praticiens pour afficher plus d'informations à l'écran. Elargis la carte principale pour qu'elle s'adapte dynamiquement à la largeur de la fenêtre du navigateur (mode "full-width" responsive). Transforme la liste actuelle en une grille de tuiles (cards). Disposition des tuiles : alignement de gauche à droite, puis de haut en bas (layout Grid / Flexbox multiligne). Comportement : le nombre de tuiles par ligne doit s'ajuster automatiquement selon la largeur de la fenêtre pour maximiser l'espace disponible. Remplace aussi le menu secteur par un curseur de 0 à 100km
On lance et ...
Eh oui ! Si vous êtes un lecteur averti - nul doute là-dessus, puisque vous êtes sur Niji.tech, le meilleur de la tech by Niji - vous aurez noté précédemment que
toute demande doit désormais être routée vers les spécifications par domaine
donc /speckit.design ne modifie que la spécification concernée :
Quelques étapes plus loin, on obtient notre évolution, raccord avec spécifications et tests :
Pour aller au bout de notre idée, rajoutons à la constitution :
Pour toute nouvelle feature, speckit-design DOIT etre la premiere etape (routage bounded context + dossier domaine cible).
ce qui aura pour effet d'interdire les /speckit.specify sans avoir lancé /speckit.design au préalable
La parallélisation des développements.
Speckit est efficace en solitaire. Mais on a encore parfois besoin d'une équipe de plusieurs développeurs augmentés pour tenir un planning. Le risque de se marcher dessus augmente donc. Ce constat n'est pas nouveau mais il est exacerbé avec l'IA gen : chaque développeur travaille sur sa fenêtre de contexte et sa spécification, en revanche le code lui est partagé dans toute l'équipe. Quand 3 développeurs vont lancer un /speckit.implement et qu'une partie de code est commune aux 3 développeurs, le nombre de conflits va exploser et la gestion des branches avec.
Comment faire ?
Traditionnellement, investir dans le Domain Driven Design suppose une rigueur technico-fonctionnelle lourde et souvent coûteuse à mettre en place. Mais on peut s'en inspirer pour garder les principes qui nous intéressent, sans forcément aller jusqu'au bout de la philosophie. Comme on l'a vu, il est possible de déléguer à l'IA la définition des domaines métier, en les interprétant à partir du besoin exprimé et du code existant ; on peut aussi lui demander de générer le langage ubiquitaire (le modèle d'information commun) ; ainsi que l'architecture en couches propre au DDD.
Dans l'exemple précédent, non seulement notre application de prise de rendez-vous a été spécifiée par domaine, mais notre nouveau skill /speckit.design a aussi respecté une implémentation selon l'approche Domain Driven Design :
Le code est bien découpé par domaine, l'UI et la logique sont bien séparés et l'infrastructure est gérée à part. L'implémentation par IA n'a pas duré plus longtemps, mais elle a rendu une architecture plus facile à appréhender. Même étant seul développeur, je sais exactement où intervenir pour faire évoluer telle fonctionnalité. A plusieurs, on peut se responsabiliser chacun sur son domaine métier. Voire revenir à des notions de feature team augmentées. Le travail se parallélise mieux.
Oui, cette architecture apportera sans doute une complexité supplémentaire, mais est-ce encore un problème à l'heure de la gen AI ? On gagne surtout les avantages d'une architecture solide, propre et pérenne à un coût infiniment moindre par rapport à l'époque so-2020 où la gen AI n'avait pas encore percé.
(c'est de l'humour, on se calme équipe 1er degré :)
Le cycle d'instructions
Avec Speckit, le cycle d'instructions à respecter est fastidieux, même si vous souhaitez juste modifier un bouton.
Voici la description du cycle complet :
| Commande | Description |
|---|---|
/speckit.constitution |
Crée ou met à jour les principes de gouvernance du projet et les guidelines de développement |
/speckit.specify |
Définit ce que vous voulez construire (exigences, user stories) |
/speckit.clarify |
Clarifie les zones d'ombre (recommandé avant /speckit.plan) |
/speckit.plan |
Crée le plan de conception technique et génère la documentation associée selon vos choix de stack technique. |
/speckit.checklist |
Génère une liste de points à vérifier avant implémentation (cohérence, exhaustivité, respect et clarté des exigences) |
/speckit.tasks |
Génère une liste de tâches de développement avec pour chacune le caractère parallélisable sur plusieurs agents d'implémentation. |
/speckit.analyze |
Analyse de la cohérence cross-artifact |
/speckit.taskstoissues |
Convertit les tâches générées en GitHub issues pour le tracking et leur exécution. |
/speckit.implement |
Exécute les tâches du plan d'implémentation pour construire la fonctionnalité selon le plan. |
Le respect de ce cycle assure qu'à chaque instant vos spécifications, vos tests et votre code sont synchronisés au sein du même repository. Cependant on sait tous qu'en cas d'urgence, le délai de déploiement d'un correctif peut justifier de modifier le code manuellement en allant au plus vite. Il parait donc utopique de conserver cette rigueur sur la durée. Les spécifications et les tests ne reflètent alors plus le code et ne sont plus une source de vérité pour l'avenir.
Comment faire ?
Dans notre exemple précédent, nous utilisions le nouveau skill /speckit.design pour identifier les domaines métier, puis il fallait enchainer avec /speckit.specify et la demande. Faisons évoluer /speckit.design pour être utilisé soit seul (identification des domaines métier, mise en place de l'arborescence projet raccord), soit directement avec une demande. Dans ce cas, le skill enchainera avec /speckit.specify pour réaliser la spécification nécessaire :
Speckit détecte bien le domaine concerné par ma demande :
Ensuite, si on est pressé il est possible de lier manuellement les appels suivants :
Voire on pourrait imaginer un skill /speckit-dash qui automatiserait ces appels. On aurait ainsi le choix de dérouler chacune des étapes manuellement avec la maîtrise du plan d'implémentation et des tâches qui en découlent, ou d'exécuter une fois /speckit-dash si on accorde notre confiance à Speckit pour faire les bons choix.
On réduit ainsi le cycle d'instruction nécessaire, notamment pour intervenir en urgence et déployer un correctif rapidement.
Toutefois, dans ce contexte il sera plus rapide donc plus instinctif d'aller directement modifier le code généré par l'IA, ou de prompter de façon brute le correctif souhaité, plutôt que de repasser par des skills. Dans ce cas, on va créer un écart entre les spécifications et le produit. Des plugins existent déjà tels que bgervin/spec-kit-sync pour resynchroniser vos spécifications depuis le code.
Synthèse
Speckit allie rigueur et flexibilité pour s’adapter aux besoins de chaque projet. Il peut offrir une structure solide pour les projets encadrés ou basculer vers plus de souplesse quand nécessaire. Des ajustements ciblés permettent de rationaliser la spécification par domaine métier, facilitant son appropriation. Dans cet article, nous avons exploré l'intégration de l'IA pour automatiser le Domain Driven Development, ce qui améliore la parallélisation des tâches tout en assurant une synchronisation parfaite entre le produit et ses spécifications. La réduction des cycles d’instructions accélère également le développement si besoin. Enfin, le découpage par domaine métier optimise le travail des équipes distribuées en adaptant le cadre à leur organisation.
Conclusion
Cette exploration de Speckit en 2 articles montre que les outils d'IA générative ne suppriment pas le besoin de rigueur, mais le déplacent. Vibe-coder vite et sale n'a jamais été aussi accessible, mais c'est dangereux. Car le gain observé à court terme masque une dette menaçant la pérennité du produit. Les solutions actuelles de harness engineering telles que Speckit peuvent apporter une solution. En combinant une approche ATDD (le produit fait ce qu'on attend de lui), une Constitution (pour mettre des limites à l'IA), et une approche inspirée du DDD (pour cloisonner les responsabilités et permettre le travail en équipe), on commence à imaginer ce que sera le développement augmenté de demain.
En prolongeant la réflexion, on peut imaginer que le code va passer de livrable final à sous-produit technique, automatisable...et jetable ! La richesse d'un projet résidant dans ses spécifications, son architecture et son modèle métier qu'il sera possible de réimplémenter à volonté.
Nous avons exploré Speckit et l'avons "hacké" pour s'adapter aux contraintes de la vraie vie mais les standards sont encore à écrire, et définiront le métier de développeur augmenté. Un développeur qui loin de disparaître, deviendra l'ultime garant du projet. Il devra suivre la cadence infernale de l'IA qui développe, en sécurisant l'architecture fonctionnelle et technique empêchant l'IA de détruire demain ce qu'elle a construit aujourd'hui.





