Aller au contenu

Architecture Vertical Slice

Introduction

Dans une application organisée par couches techniques, une même fonctionnalité peut être répartie entre un contrôleur, un service, un repository et des entités. Pour comprendre ou modifier cette fonctionnalité, il faut parcourir chacun de ces emplacements.

La Vertical Slice Architecture propose de regrouper le code autour des fonctionnalités de l’application. Chaque tranche verticale correspond à une fonctionnalité ou à un cas d’utilisation, tel que la création d'une commande, sa consultation ou son annulation. Elle rassemble les éléments nécessaires à son exécution, du traitement de la requête HTTP jusqu’à l’accès aux données.

Qu’est-ce que la Vertical Slice Architecture ?

Une tranche verticale représente un parcours fonctionnel de bout en bout. Dans une API ASP.NET Core, elle peut contenir un endpoint, ses contrats d’entrée et de sortie, la validation des données fournies, le cas d’utilisation et les requêtes nécessaires.

Architecture Vertical Slide - Arborescence

Le découpage peut varier : une petite fonctionnalité peut se résumer à un seul fichier, alors qu’une fonctionnalité complexe à plusieurs fichiers (avec une classe par fichier). L’objectif est de rendre visible où se trouve le code qui réalise une action donnée.

Une tranche n’est pas nécessairement un service indépendant. Plusieurs tranches peuvent partager le même processus ASP.NET Core et la même base de données. L'architecture Vertical Slice décrit l’organisation du code et des cas d’utilisation ; elle ne définit pas à elle seule le mode de déploiement.

Comment une tranche traite-t-elle une demande ?

Prenons la création d’une commande :

Architecture Vertical Slide - Exemple - Etape

La consultation d’une commande suit un autre parcours :

Architecture Vertical Slide - Exemple - Etape

Avec EF Core, un DbContext peut être injecté dans le traitement d’une tranche lorsque cet accès reste simple et compréhensible. EF Core présente le contexte comme une unité de travail et AddDbContext l’enregistre généralement avec une durée de vie limitée à la portée de la requête. Un repository dédié reste pertinent lorsqu’il exprime une responsabilité métier ou encapsule un accès réellement complexe.

Quel rapport avec l’architecture monolithique ?

Une application organisée en tranches verticales peut être un monolithe : elle est alors déployée comme une application unique. Elle peut aussi faire partie d’un système distribué. Les deux notions répondent à des questions différentes :

Question Choix concerné
Comment regrouper le code d’un cas d’utilisation ? Tranches verticales
Comment déployer l’application ? Monolithe ou plusieurs services

Dans une architecture monolithique organisée en tranches verticales, les avantages du déploiement unique coexistent avec une organisation du code par fonctionnalités. Les limites liées à une base de code ou à une base de données communes restent à gérer.

Les avantages

Une fonctionnalité plus facile à retrouver

Le code d’un cas d’utilisation est regroupé dans un emplacement identifiable.

Des changements mieux circonscrits

Une évolution peut rester dans sa tranche lorsque les responsabilités et les contrats sont bien définis.

Une structure adaptée à chaque besoin

Une lecture simple et une écriture métier complexe peuvent suivre des traitements différents.

Des tests centrés sur les usages

Les tests vérifient le comportement d’un cas d’utilisation et ses résultats attendus.

Une organisation progressive

Les abstractions sont introduites selon les besoins de chaque fonctionnalité, sans imposer le même découpage à toutes les tranches.

Les limites

Une duplication possible

Des tranches peuvent répéter des conversions ou des requêtes ; il faut distinguer la répétition acceptable d’une règle métier à factoriser.

Des frontières parfois difficiles à définir

Une tranche trop large devient difficile à maintenir, tandis qu’un découpage trop fin disperse un même parcours.

Des règles communes à protéger

Des invariants métier ne doivent pas être réimplémentés différemment dans plusieurs fonctionnalités.

Une coordination toujours nécessaire

Les changements de schéma, les transactions et les contrats partagés peuvent concerner plusieurs tranches.

Un risque de code peu structuré

Regrouper les fichiers par fonctionnalité ne suffit pas si les endpoints portent seuls toute la logique métier.

Quand cette architecture est-elle pertinente ?

Elle convient particulièrement à une application dont les fonctionnalités sont identifiables et évoluent à des rythmes différents. Une API métier comprenant des parcours tels que créer, valider, consulter et annuler une commande en est un bon exemple : chaque parcours possède ses entrées, ses règles et ses résultats.

Elle est également intéressante lorsqu’une équipe perd du temps à suivre une modification à travers de nombreux dossiers techniques. Regrouper les éléments par cas d’utilisation facilite alors la lecture et la maintenance.

Bonnes pratiques avec .NET

Nommer les tranches par action métier

Utiliser des noms comme CreateCommand ou CancelCommand pour identifier rapidement chaque cas d’utilisation.

Garder les endpoints lisibles

Confier au endpoint le contrat HTTP et placer les décisions métier complexes dans des classes adaptées.

Définir des contrats propres à chaque usage

Créer les objets d’entrée et de sortie nécessaires à la tranche sans exposer directement les entités d'*EF Core*.

Partager les invariants métier

Centraliser les règles qui doivent rester identiques entre plusieurs tranches dans un modèle ou un composant métier commun.

Choisir les abstractions selon le besoin

Utiliser directement *EF Core* pour un accès simple et introduire un contrat dédié lorsqu’il clarifie une responsabilité.

Vérifier les frontières utiles

Tester les règles métier et vérifier les requêtes *EF Core*, les transactions et les contrats HTTP importants par des tests d’intégration.

ASP.NET Core permet notamment de regrouper des routes d’API minimales avec MapGroup et d’appliquer des métadonnées ou des filtres à un groupe de endpoints. Ce sont des outils d’organisation possibles, sans être des conditions nécessaires à cette architecture.

Vertical Slices, couches et CQRS

Les architectures Vertical Slices, en couches et CQRS peuvent se combiner. Une tranche verticale peut conserver des responsabilités internes distinctes entre le endpoint, le traitement métier et la persistance des données. Elle change surtout l’unité principale d’organisation du code : on part de la fonctionnalité, puis on structure ce dont elle a besoin.

De même, séparer une commande d’une requête de lecture peut être utile lorsque leurs besoins diffèrent. Cela ne rend pas CQRS obligatoire pour toutes les fonctionnalités. Le critère reste la clarté du parcours et la maîtrise des règles métier.