Aller au contenu

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é.

Architecture monolithique

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).