Analyser une application et identifier les limites de décomposition
Pour déplacer son application vers une architecture de microservices, Fabrikam doit évaluer son application actuelle et déterminer l’étendue et la limite de chaque microservice. Pour ce faire, la société utilise l’infrastructure de conception orientée domaine (DDD, domain-driven design). Voyons comment appliquer cela à l’application.
Notes
Cet article n'a pas vocation à apporter une analyse complète et exhaustive du domaine. Nous avons délibérément abrégé l’exemple pour n’illustrer que les points principaux. Pour plus d’informations sur DDD (Domain-Driven Design, Conception pilotée par le domaine), consultez la section « En savoir plus » dans le résumé à la fin de ce module.
Qu’est-ce qu’une conception orientée domaine ?
DDD est une approche de la conception des systèmes initialement introduite en 2005 par Erik Evans dans son ouvrage Domain-Driven Design: Tackling Complexity in the Heart of Software (conception orientée domaine : combattre la complexité au cœur du logiciel). Cette approche se compense de trois éléments clés :
- Se concentrer sur le domaine principal et la logique de domaine.
- Structurer la conception sur un modèle du domaine.
- Mettre en place une collaboration itérative entre les équipes techniques et les partenaires commerciaux pour améliorer constamment le système.
DDD fournit une infrastructure constituant la base d’un ensemble bien organisé de microservices. Elle comporte deux phases distinctes, l’une stratégique, l’autre tactique. Dans la phase stratégique de la conception orientée domaine, vous définissez la structure à grande échelle du système. Cette phase garantit que votre architecture demeure axée sur les fonctionnalités commerciales. La phase tactique, quant à elle, offre un jeu de modèles de conception à valoriser pour créer le modèle du domaine. Ces modèles comprennent les entités, les agrégats et les services de domaine. Ces modèles tactiques vous aident à concevoir des microservices à la fois cohérents et souplement couplés.
Pendant la phase stratégique de la conception, vous mappez le domaine d’entreprise et définissez les limites de contexte de vos modèles de domaine. La phase tactique consiste à définir vos modèles de domaine avec davantage de précision. Les modèles tactiques sont appliqués au sein d’une seule limite de contexte. Au sein d’une architecture de microservices, nous nous intéressons aux modèles d’entités et d’agrégats. En appliquant ces modèles, nous nous donnons les moyens d’identifier les limites naturelles des services au sein de notre application. En règle générale, un microservice ne doit pas être plus petit qu’un agrégat, et pas plus grand qu’une limite de contexte.
À un niveau élevé, vous pouvez scinder ce processus en quatre étapes :
- Analysez le domaine d’entreprise afin d’appréhender les exigences fonctionnelles de l’application. Cette étape produit une description informelle du domaine, qui peut être affinée en un ensemble plus formel de modèles de domaine.
- Définissez les limites de contexte du domaine. Chaque limite de contexte comporte un modèle de domaine représentant un sous-domaine spécifique de l’application dans son ensemble.
- Au sein d’une limite de contexte, appliquez des modèles tactiques de la conception orientée domaine afin de définir les entités, les agrégats et les services de domaine.
- Identifiez les microservices dans votre application à l’aide des résultats de l’étape précédente.
Examinons de plus près le déroulement de chacune de ces étapes.
Analyser le domaine d’entreprise
La conception orientée domaine vise dans un premier temps à modéliser le domaine d’entreprise et à créer un modèle de domaine. Le modèle de domaine est un modèle théorique du modèle d’entreprise. Il répartit et organise la connaissance du domaine, en fournissant un langage commun pour les développeurs et les experts du domaine.
Commencez par mapper l’ensemble des fonctions d’entreprise et leurs connexions. Cette analyse est un effort collaboratif qui implique des experts du domaine, des architectes logiciels et d’autres parties prenantes. Il n’est pas nécessaire de recourir à aucun formalisme particulier. Dessinez un schéma ou établissez une esquisse sur un tableau blanc.
À mesure que vous enrichissez le schéma, vous pouvez commencer à identifier des sous-domaines distincts. Quelles fonctions sont étroitement liées ? Quelles sont les fonctions au cœur de l’entreprise, quelles sont celles prenant en charge les services auxiliaires ? À quoi ressemble le graphique de dépendance ? Durant cette phase initiale, vous ne vous intéressez pas aux technologies ni aux détails de l’implémentation. Cela dit, vous devez identifier où il convient d’intégrer l’application avec les systèmes externes, tels que les systèmes CRM, de traitement des paiements ou de facturation.
Définir les limites de contexte
Le modèle de domaine comprend des représentations des composantes réelles, comme les utilisateurs, les drones ou les colis. Cela ne signifie pas pour autant que chaque partie du système doive utiliser la même représentation pour une composante donnée.
Par exemple, les sous-systèmes qui gèrent la réparation des drones et l’analyse prédictive doivent représenter de nombreuses caractéristiques physiques des drones. Ces caractéristiques incluent l’historique de maintenance, le kilométrage, l’âge, le numéro de modèle et les détails des performances. Toutefois, lors de la planification d’une livraison, ces éléments importent peu. Le sous-système de planification doit simplement connaître la disponibilité des drones, ainsi que les horaires prévus de collecte et de livraison.
Si nous essayons de créer un modèle unique pour chacun de ces sous-systèmes, cela pourrait s’avérer inutilement complexe. Par ailleurs, l’évolution au fil du temps du modèle serait ralentie, dans la mesure où les modifications doivent être validées par plusieurs équipes travaillant sur des sous-systèmes séparés. Il est souvent préférable de concevoir des modèles séparés qui représentent la même entité réelle (dans ce cas, un drone) dans deux contextes différents. Chaque modèle comporte uniquement les fonctionnalités et attributs qui sont pertinents au sein de son contexte spécifique.
C’est là que le concept DDD de contextes limités entre en jeu. Une limite de contexte correspond tout simplement au périmètre, au sein d’un domaine, dans lequel s’applique un modèle de domaine particulier. Dans le cadre du schéma précédent, nous pouvons regrouper les fonctionnalités par modèle de domaine.
Définir les entités, les agrégats et les services
La phase tactique consiste à définir vos modèles de domaine avec davantage de précision. Les modèles tactiques sont appliqués au sein d’une seule limite de contexte. Au sein d’une architecture de microservices, nous nous intéressons aux modèles d’entités et d’agrégats. En appliquant ces modèles, nous nous donnons les moyens d’identifier les limites naturelles des services au sein de notre application. En règle générale, un microservice ne doit pas être plus petit qu’un agrégat, et pas plus grand qu’une limite de contexte.
Il existe plusieurs modèles tactiques de conception orientée domaine à prendre en compte :
- Entités : Une entité est un objet présentant une identité unique et permanente. Par exemple, dans une application bancaire, les clients et les comptes sont des entités.
- Objets de valeur : Un objet de valeur n’a aucune identité. Ce sont ses valeurs d’attributs qui le définissent et il est immuable. Comme exemples typiques d’objets de valeur, citons les couleurs, les dates et les heures, ainsi que les valeurs de devise.
- Agrégats : Un agrégat définit la limite de cohérence autour d’une ou plusieurs entités. La finalité d’un agrégat est de modéliser les éléments transactionnels invariants. Les composantes du monde réel présentent des réseaux complexes de relations. Les clients créent des commandes, les commandes contiennent des produits, les produits ont des fournisseurs, etc. Si l’application modifie plusieurs objets connexes, comment garantit-elle la cohérence ? Comment effectuer le suivi des éléments invariants et comment les appliquer ?
- Services de domaine et d’application : Dans la terminologie de la conception pilotée par domaine, un service est un objet implémentant une certaine logique sans avoir aucun effet sur l’état. Evans fait la différence entre les services de domaine, qui encapsulent la logique du domaine, et les services d’application, qui fournissent une fonctionnalité technique. Les services d’application incluent généralement des fonctionnalités techniques telles que l’authentification utilisateur ou l’envoi d’un SMS. Les services de domaine sont souvent utilisés pour modéliser un comportement valable sur plusieurs entités.
- Événements de domaine : Les événements de domaine peuvent servir à communiquer des signalements à d’autres composantes du système. Comme leur nom le suggère, les événements de domaine doivent avoir une signification au sein du domaine. Par exemple, « un enregistrement a été inséré dans une table » n’est pas un événement de domaine. « Une livraison a été annulée » est un événement de domaine. Les événements de domaine sont particulièrement pertinents dans une architecture de microservices. Les microservices étant distribués sans partager de magasins de données, ils tirent parti des événements de domaine pour se coordonner entre eux.
Dans son système, l’équipe de développement Fabrikam a identifié les entités suivantes :
- Livraison
- Package
- Drone
- Compte
- Confirmation
- Notification
- Étiquette
Les quatre premiers éléments, associés à la livraison, au colis, au drone et au compte, sont tous des agrégats représentant des limites de cohérence transactionnelles. Les confirmations et les notifications sont des entités enfants des livraisons. Les étiquettes sont des entités enfants des packages.
Les objets de valeur de cette conception correspondent à la position (Location), l’heure d’arrivée estimée (ETA), le poids du colis (PackageWeight) et la taille du colis (PackageSize).
Il existe deux événements de domaine :
- Lorsqu’un drone est en vol, l’entité Drone transmet l’événement DroneStatus qui décrit l’emplacement du drone et son état, par exemple en vol ou à terre.
- L’entité de livraison transmet les événements DeliveryTracking à chaque changement d’étape de la livraison. Il peut par exemple s’agir d’une création de livraison, d’un report, d’une échéance proche ou d’une fin de mission (DeliveryCreated, DeliveryRescheduled, DeliveryHeadedToDropoff et DeliveryCompleted, respectivement).
Notez que ces événements décrivent les éléments importants du modèle de domaine. Ils ont trait à une situation au sein du domaine, et ne sont liés à aucune construction particulière de langage de programmation.
L’équipe en charge du développement a identifié un domaine supplémentaire de fonctionnalités qui ne peut être pris en compte dans aucune des entités décrites jusqu’à présent. Une partie du système doit coordonner l’ensemble des étapes associées à la planification et à la mise à jour d’une livraison. L’équipe de développement a ajouté deux services de domaine à la conception. Un planificateur coordonne les étapes. Un superviseur surveille l’état de chaque étape afin de détecter si des étapes ont échoué ou expiré.
Identifier les microservices
Nous sommes maintenant prêts à passer du modèle de domaine à la conception de l’application. Il s’agit d’une approche que vous pouvez utiliser pour dériver des microservices à partir du modèle de domaine.
- Commencez avec un contexte limité. En général, les fonctionnalités d’un microservice ne doivent pas couvrir plus d’un contexte limité. Par définition, un contexte limité marque la limite d’un modèle de domaine particulier. S’il s’avère qu’un microservice associe des modèles de domaines différents, cela peut signifier que vous devez affiner votre analyse de domaine.
- Ensuite, examinez les agrégats dans votre modèle de domaine. Les agrégats font souvent de bons candidats pour les microservices. Un agrégat bien conçu présente de nombreuses caractéristiques d’un microservice bien conçu :
- Un agrégat est dérivé des besoins de l’entreprise, plutôt que des problèmes techniques, tels que les accès aux données ou la messagerie.
- Un agrégat doit avoir une cohésion fonctionnelle élevée.
- Un agrégat est une limite de persistance.
- Les agrégats doivent être couplés en laissant une marge de manœuvre.
- Les services de domaine font également de bons candidats pour les microservices. Les services de domaine sont des opérations sans état entre plusieurs agrégats. Un workflow impliquant plusieurs microservices en est un exemple type. Plus tard, nous voyons un exemple de service de domaine dans l’application de livraison par drone.
- Enfin, réfléchissez aux exigences non fonctionnelles. Examinez les facteurs tels que la taille de l’équipe, les types de données, les technologies, ainsi que les exigences d’extensibilité, de disponibilité et de sécurité. Ces facteurs peuvent vous amener à décomposer davantage un microservice en deux (ou plusieurs) services plus petits ou, à l’inverse, à combiner plusieurs microservices.
Il est important d’être pragmatique et de ne pas oublier que la conception orientée domaine est un processus itératif. En cas de doute, commencez avec des microservices généraux. Il est plus facile de fractionner un microservice en deux services plus petits que de refactoriser une fonctionnalité entre plusieurs microservices existants.
Appliquer la conception orientée domaine à l’application de drone
Pour l’application de Fabrikam, tous ces services résident dans l’application monolithique existante. Une fois qu’elle a identifié où décomposer son application en microservices, la société commencera par le service de colis.
Le service de colis dispose actuellement d’une équipe de développement dédiée. Il affiche des problèmes de performances liés à la scalabilité et constitue un candidat de choix pour lancer la décomposition de l’application.