Notre Stack technique

Notre Stack technique
Photo by Iva Rajović / Unsplash

L'avantage d'une mise en place d'une démarche Domain Driven Design from scratch, c'est entre autre que l'on a la capacité de reprendre complètement la main sur les outils et librairies que l'on souhaite utiliser.
Quelque part on revient à "l'os" de la programmation. Une petite cure d'amaigrissement salutaire.

C'est donc l'occasion à la fois de se poser beaucoup de question sur nos besoins réels, et aussi le moment de cette sensation particulière ou l'on vient assembler plusieurs outils hétérogènes, dans un tout cohérent et efficace, qui constitue les nouveaux fondamentaux techniques de nos applications.
En gros c'est le moment d'assembler soi même sa stack.

Disclaimer : Les outils que je cite ici, sont ceux que nous utilisons au moment ou j'écris ces lignes. Vous savez tous que les écosystèmes changent, et qu'il est souvent nécéssaire de s'y adapter. Je vous conseille donc autant que possible de wrapper vos collaborateurs techniques dans des couches de services, qui vous fourniront une indirection précieuse, ou moment ou il faudra changer de lib. Car cela va arriver.

Le langage de programmation

Nous avons choisi python, depuis de nombreuses années, pour la richesse de son écosystème, et l'élégance de sa syntaxe, question de point de vue.
Mais surtout parce qu'une base en python ne ferme presque aucune options à priori.
Vous avez besoin d'un truc qui tourne sur du poste lourd ? faire une interface native est easy.
Besoin de mettre en place un backend d'API pour le Web, sans problème, il y a tout un tas de framework à disposition.
De gros volumes de données débarquent tout à coup ? Panda et numpy sont là.
Des besoins en IA ? tensor flow est votre ami, un ami un peu compliqué à comprendre, mais bon.
Les perfs de calculs deviennent critiques ? Cython vous permet d'externaliser des calculs vers du C++.

Les deux seuls trucs vraiment pénibles avec python sont le duck typing, et le modèle de threading.
Le duck typing peut contribuer a vous foutre le bordel dans une application si les devs ne sont pas rigoureux, faiblesse qui commence à être compensé par les typings dans les dernières versions.
Le modèle de threading induit par la présence du GIL est très très chelou, et fait de python un langage plutôt monothread. Cette limite est compensée par les frameworks asynchrones, qui permettent de faire du pipelining sans se poser de question. Mais quand il s'agit de faire du vrai multi-thread, ça reste quand même un peu énigmatique. La doc officielle conseil d'ailleurs de s'orienter vers du multi-processing quand on veut mettre en place un vrai système d'asynchronisme. Un peu frustrant quand même.

La gestion des dépendances et les environnements de développement

Nous sommes récemment passés de pipenv à Poetry. Ce dernier est beaucoup plus rapide, et plus efficace dans son utilisation quotidienne.

La couche web

Les requêtes web sont gérées par FastAPI. La doc n'est pas exempt de défaut, mais l'approche plutôt orienté librairie que framework nous a convaincu. L'outil n'essaie pas en permanence de nous tordre le bras pour que l'on rentre dans ce qu'il a prévu pour nous en terme d'organisation de code. Et ça, c'est impératif en DDD.
Le système d'injection de dépendance est très curieux de mon point de vue, et l'orientation très procédurale de la lib est un poil pénible à utiliser dans un contexte très objet, mais bon, de toute façon on ne passe que très très peu de temps dans les méthodes de fastAPI, on sort très vite vers du code standard, donc on s'y fait.
Accessoirement les perfs sont plutôt bonnes paraît-il. Bon après on reste en python, c'est pas non plus une ferrari, mais ça permet de servir 90% des besoins, pour peu qu'on s'en serve correctement. Les appli web sont de toutes façons généralement bloquées davantage par les I/O que par les calculs. L'inverse de l'embarqué en fait.
Nous avons aussi beaucoup bossé et beaucoup outillé Django, avant de nous en séparer pour les raisons évoquées.

Les accès a à la couche de persistance

Nous avons opté pour SQLAlchemy, lorsque nous avons besoin de modifier ou mettre à jour des données structurées. C'est pas le plus simple, mais c'est ce qui nous permet de garder un contrôle fin sur nos données et sur leur organisations.

La validation des entrées / sorties

C'est ici que pydantic entre en jeu. Nos définitions s'appuie sur les possibilités de validation de pydantic. Pratique pour assurer la stabilité des interfaces et de nos contrats.


J'enrichirais ce post des principales librairies que nous utilisons pour tout ce que nous appelons les collaborateurs techniques, passerelle de mail, logger, accès aux données, injection de dépendance etc.