Architecture monolithique
Introduction
Dans une application basée sur une architecture monolithique, les fonctionnalités sont déployées et exécutées comme un ensemble. Une application ASP.NET Core peut contenir une API, des traitements métier et l'accès aux données, répartis dans plusieurs projets .NET mais publiés ensemble. Les composants communiquent généralement dans le même processus, par des appels de méthodes.
Prenons comme exemple un site de vente en ligne. Le catalogue, le panier et les commandes peuvent être organisés en modules distincts, tout en appartenant à une même application déployée sur une ou plusieurs instances. Lorsqu’une fonctionnalité change, une nouvelle version de l’application est déployée. Lorsque la charge augmente, on peut ajouter des instances, mais chacune embarque l’application dans son intégralité.
Monolithe simple et monolithe modulaire
Un monolithe simple peut suffire pour une petite application. À mesure que les fonctionnalités se multiplient, une architecture monolithe modulaire permet de regrouper le code par capacité métier et de définir des frontières entre les modules.
Les avantages
Un déploiement simplifié
L’application est construite et publiée comme un seul ensemble.
Des échanges directs
Les composants peuvent communiquer dans le même processus, sans appel réseau.
Un développement plus accessible
Une seule application facilite le démarrage et le débogage.
Une cohérence des données plus simple à gérer
Lorsque des composants partagent une même base de données, certaines requêtes peuvent être exécutées dans une même transaction.
Moins de composants à superviser
L’hébergement et la supervision demandent moins de coordination qu’avec plusieurs services autonomes.
Les limites
Un déploiement commun
La modification d’une fonctionnalité conduit généralement à reconstruire et redéployer l’application dans son intégralité.
Une mise à l’échelle globale
Ajouter des instances pour répondre à une forte charge réplique aussi les fonctionnalités qui ne sont pas nécessaires.
Une isolation limitée des défaillances
Une forte consommation de ressources ou une défaillance grave peut affecter les autres fonctionnalités du même processus.
Une évolution plus difficile si le code est couplé
Lorsque les responsabilités sont mélangées, une modification locale peut avoir des effets de bord difficiles à anticiper.
Quand cette architecture est-elle un choix pertinent ?
L’architecture monolithique convient particulièrement lorsqu'on souhaite développer une application qui ne contient pas de services indépendants. Elle reste pertinente lorsque les besoins de déploiement et de mise à l’échelle sont globalement similaires d’une fonctionnalité à l’autre. La taille du code, à elle seule, n’impose pas de passer à des services séparés : un logiciel de taille importante peut rester maintenable si ses responsabilités et ses dépendances sont maîtrisées, à condition qu'il respecte les bonnes pratiques de conception et de développement (.NET / C#).
Le choix mérite d’être réexaminé lorsqu’une partie de l’application doit être déployée ou dimensionnée indépendamment, ou lorsque des équipes ont besoin de faire évoluer leurs composants à des rythmes différents.
Bonnes pratiques avec .NET
Organiser le code par responsabilité
Regrouper les traitements liés à une même fonctionnalité et rendre leurs points d’entrée identifiables.
Définir le sens des dépendances
Éviter les références circulaires.
Préserver les frontières des modules
Faire communiquer les fonctionnalités par des abstractions plutôt que par des accès à leurs classes internes.
Garder les décisions métier au bon endroit
Implémenter les règles dans les composants métier, les endpoints ASP.NET Core devant uniquement gérer les échanges HTTP.
Encadrer l’accès aux données
Utiliser EF Core selon les besoins des fonctionnalités, sans laisser les entités de persistance devenir des contrats publics de l’API (privilégier des DTO).
