Décisions architecturales avant de générer du code
Lino génÚre beaucoup de code rapidement, mais la qualité du résultat dépend des décisions prises avant la génération. Le choix des limites, du type de projet, de la stratégie de communication et du niveau acceptable de dette technique évite que la productivité initiale ne se transforme en retouche.
Utilisez cette page comme liste de contrÎle d'architecture pour aligner votre équipe, votre domaine et vos opérations avant de créer des services, modules et fonctionnalités avancés.
Type de projet
Avant de courir lino project new, dĂ©finir lâobjectif du systĂšme. Un projet administratif interne, un SaaS multi-tenant, un API public et une plateforme distribuĂ©e ont des besoins diffĂ©rents.
- Application simple : peu de contextes, dĂ©ploiement unique et faible besoin dâindĂ©pendance opĂ©rationnelle.
- Monolithe modulaire : plusieurs modules dans le mĂȘme processus, avec des limites explicites et des coĂ»ts opĂ©rationnels infĂ©rieurs.
- Microservices : services séparés, déploiement indépendant, communication asynchrone et plus grande complexité opérationnelle.
- SaaS : nécessite l'isolement des tenants, une sécurité renforcée, des secrets, une limitation des tarifs, de l'observabilité et des décisions claires en matiÚre de facturation/d'exploitation.
Cette décision définit également quelles préoccupations devraient surgir dÚs le premier jour. Un SaaS ne peut pas traiter le tenant comme un détail tardif ; un API public ne peut pas naßtre sans limitation des tarifs et sans contrats clairs ; une solution avec des événements doit penser à Outbox, à l'idempotence et à l'observabilité ; une application avec plusieurs cultures doit éviter les chaßnes dispersées dÚs le début.
Lors de la création de la fondation, enregistrez les principaux choix : cultures prises en charge, cache distribué, communication asynchrone, analyseurs de code, type de base de données, présence de l'application Web, authentification, tenant et travailleur. Ces options affectent les packages, les templates, AppHost, les paramÚtres, les secrets, les projets générés et l'effort requis pour modifier l'architecture ultérieurement.
Microservices modulaires et modulaires monolithiques
Le monolithe modulaire vous permet d'organiser le domaine en modules avec des contrats internes clairs, ce qui simplifie la construction, le débogage et le déploiement. Les microservices ne sont payants que lorsqu'il existe de bonnes raisons: une échelle indépendante, des équipes distinctes, des frontiÚres commerciales stables ou des exigences opérationnelles différentes.
Commencer par un monolithe modulaire ne signifie pas ignorer lâarchitecture. Cela signifie prĂ©server un dĂ©ploiement simple pendant que le domaine est encore en cours de dĂ©couverte, mais crĂ©er des limites internes qui empĂȘchent que tout ne devienne une masse unique d'entitĂ©s, de services et de tables partagĂ©es. Câest la diffĂ©rence entre « dĂ©marrer simplement » et « dĂ©marrer sans structure ».
| CritĂšre | Monolithe modulaire | Microservices |
|---|---|---|
| Déployer | Le plus simple, généralement unique | Indépendant par service |
| Cohérence | Plus facile de maintenir des transactions locales | Nécessite des événements, Outbox et une cohérence éventuelle |
| OpĂ©ration | CoĂ»t dâinfrastructure rĂ©duit | Plus d'observabilitĂ©, de files d'attente, de tentatives et d'automatisation |
| Refactorisation | Moins cher au début | Plus difficile lorsque les contrats ont déjà été publiés |
Lino prend en charge les deux chemins. La dĂ©cision doit suivre le domaine et la capacitĂ© opĂ©rationnelle de l'Ă©quipe, et pas seulement les prĂ©fĂ©rences techniques. Les microservices nĂ©cessitent l'automatisation du dĂ©ploiement, l'observabilitĂ© distribuĂ©e, la gestion des versions des contrats, la tolĂ©rance aux pannes du rĂ©seau, la messagerie, le retraitement et la gouvernance des donnĂ©es. Si lâĂ©quipe ne peut pas encore lâexploiter en toute sĂ©curitĂ©, une distribution trop prĂ©coce augmente souvent le risque.
Utilisez un monolithe modulaire lorsque la prioritĂ© est d'apprendre le domaine, de valider le produit et de garder l'opĂ©ration contrĂŽlable. Utilisez des microservices lorsque lâindĂ©pendance opĂ©rationnelle est dĂ©jĂ un besoin concret: Ă©chelle distincte, Ă©quipes rĂ©ellement propriĂ©taires, cycle de publication indĂ©pendant ou exigences dâinfrastructure incompatibles entre les parties du systĂšme.
Limites des services et des modules
Une bonne limite rĂ©duit le couplage et indique clairement Ă qui appartient chaque rĂšgle. Ăvitez de crĂ©er des services par table ou par Ă©cran. Les services et modules doivent reprĂ©senter les capacitĂ©s mĂ©tier.
- Catalogue: produits, catégories, informations commerciales et données consultées par les commerciaux.
- Ventes: commandes, panier, prix appliqués, instantanés et flux commercial.
- Action: disponibilités, réservations et mouvements.
- Sécurité: utilisateurs, rÎles, autorisations, authentification et jetons.
Une bonne limite a son propre langage, des rÚgles qui changent ensemble, des données clairement définies et des contrats explicites pour communiquer avec d'autres contextes. Une mauvaise limite apparaßt généralement comme un module « Commun », une entité partagée par plusieurs zones, un tableau consulté par tout le monde ou un service créé simplement parce qu'il y a eu un nouvel écran.
Lorsqu'un module a besoin des donnĂ©es d'un autre, choisissez entre API, un Ă©vĂ©nement d'intĂ©gration, une shadow entity ou un remodelage des limites. L'accĂšs direct Ă la rive d'un autre module est le signe d'un couplage structurel. MĂȘme lorsque deux modules s'exĂ©cutent dans le mĂȘme processus et utilisent la mĂȘme base de donnĂ©es physique, le schĂ©ma, les projets de persistance et les contrats doivent protĂ©ger les limites mĂ©tier.
- Signe de bonne limite : le module peut faire évoluer ses entités et ses migrations sans forcer un autre module à se recompiler en raison de détails internes.
- Signal de seuil faible : une simple modification d'une entitĂ© nĂ©cessite de revoir les Ă©crans, les requĂȘtes et les gestionnaires de modules qui ne devraient pas connaĂźtre cette entitĂ©.
- Signe de dépendance caché : le consommateur a besoin de « trop en savoir » sur les tableaux, les domaines techniques ou le rÚglement intérieur du producteur.
Dette technique consciente
La dette technique nâest pas nâimporte quelle imperfection. C'est une dĂ©cision de reporter la qualitĂ© en connaissant le coĂ»t futur. Le problĂšme est de crĂ©er une dette sans nom, sans propriĂ©taire et sans plan de paiement.
Dans un systÚme SaaS ou modulaire, la dette technique la plus dangereuse n'est pas seulement une longue méthode. C'est la dette qui limite l'évolution: modules qui ne peuvent pas changer séparément, données tenants sans isolation fiable, secrets au sein du référentiel, points de terminaison sensibles sans limites, événements sans retraitement ou intégrations sans contrat clair.
- Documentez les raccourcis pris pendant la génération et la personnalisation.
- Exécutez la compilation et les tests avant de passer à l'étape de génération suivante.
- Ăvitez de rĂ©soudre les problĂšmes gĂ©nĂ©rĂ©s par des hacks locaux rĂ©pĂ©tĂ©s ; ajustez le motif ou le modĂšle lorsque le motif est erronĂ©.
Traitez chaque décision architecturale comme vérifiable. Si vous choisissez de ne pas activer la messagerie, notez que les flux actuels ne reposent pas sur un traitement asynchrone. Si vous choisissez une colonne par tenant, assurez-vous des filtres et des tests. Si vous choisissez l'intégration synchrone, prenez en compte les délais d'attente, l'indisponibilité et les erreurs de contrat dans le cadre de la conception.
Stratégies de communication
Choisir la communication en fonction du besoin rĂ©el de cohĂ©rence, de latence, de traçabilitĂ© et de couplage. La question principale nâest pas « quelle technologie utiliser ? », mais « le producteur a besoin de la rĂ©ponse maintenant, si le consommateur nâannule pas lâopĂ©ration et Ă qui appartiennent les donnĂ©es ? ».
Dans les systĂšmes modulaires, l'erreur la plus courante est de transformer la communication en dĂ©pendance cachĂ©e: un module interroge la table d'un autre, rĂ©utilise une entitĂ© interne, injecte un rĂ©fĂ©rentiel externe ou crĂ©e un appel synchrone sans gĂ©rer l'Ă©chec. Cela semble productif au dĂ©but, mais cela rend chaque changement ultĂ©rieur plus risquĂ© car la frontiĂšre nâest plus explicite.
- Appel synchrone : bon pour consultation immédiate et dépendance acceptable. A éviter dans les longues cascades.
- ĂvĂ©nement de domaine : rĂ©action interne dans la mĂȘme limite d'application.
- ĂvĂ©nement d'intĂ©gration : communication entre modules, services ou systĂšmes, normalement avec Outbox.
- Entités fantÎmes : Copie locale minimum pour consultation et validation sans dépendre directement du producteur.
- Intégration externe HTTP : adapté aux services tiers, avec délai d'attente, nouvelle tentative, journaux et gestion des échecs.
Si la rĂšgle nĂ©cessite une mise Ă jour immĂ©diate, utilisez le flux synchrone ou revoyez la limite. Si vous acceptez une cohĂ©rence Ă©ventuelle, prĂ©fĂ©rez les Ă©vĂ©nements pour rĂ©duire le couplage. Lorsque le consommateur nâa besoin de lire quâun petit sous-ensemble de donnĂ©es provenant dâun autre contexte, une shadow entity peut ĂȘtre plus sĂ»re que dâexposer lâintĂ©gralitĂ© de lâentitĂ© dâorigine.
| Question | Direction recommandée |
|---|---|
| La rĂ©ponse est-elle requise pour terminer le cas dâutilisation ? | IntĂ©gration synchrone explicite, avec dĂ©lai d'attente, erreur prĂ©visible et contrat clair. |
| Le producteur doit-il confirmer la transaction mĂȘme si le consommateur est absent ? | ĂvĂ©nement d'intĂ©gration avec Outbox et traitement asynchrone. |
| Le consommateur nâa-t-il besoin que de valider ou de consulter un minimum de donnĂ©es ? | EntitĂ© fantĂŽme alimentĂ©e par un Ă©vĂ©nement ou une intĂ©gration, avec propriĂ©tĂ© locale du modĂšle de lecture. |
| Le changement se produit-il dans le mĂȘme contexte global ou dĂ©limité ? | ĂvĂ©nement de domaine ou logique locale de domaine, sans publier de contrat externe inutile. |
