I.4. Le model-driven design et les building blocks

Après avoir travaillé avec les experts du domaine métier pour créer un Ubiquitous Language, avoir identifié les contextes de notre domaine, et mappé les communications, on se retrouve avec des modèles qui constituent l'élément de base qui compose notre architecture.

Rappel: les bounded contexts : c’est des modèle et des bounded contexts.

Il existe plusieurs façons de traduire notre modèle en code, bien évidemment, plusieurs bonnes implémentations, mais le résultat n’est pas toujours garanti. Cela depends clairement du développeur.

I.4.1. Le model-driven design

Généralement, l’approche la plus utilisée (mais pas la meilleure) est ce qu’on appelle analysis model.Cette approche est un résultat de l’analyse du business domain, comme un certain niveau de connaissance est construit autour du métier core de notre modèle, le résultat peut être analytiquement correct. Sauf que, comme le design du software est exclu à ce niveau et les équipes de développement aussi, il n’y a pas de mapping entre le modèle et le code. Et donc, au moment de l’implémentation les développeurs peuvent apercevoir de petits détails qui les obligent à faire des modifications du code (pour résoudre de problème de persistance et de performance), ce qui implique un changement dans le modèle d’origine.

La meilleure approche utilisée est de:

  • Lier la modélisation du domaine (l’analyse) et la conception (design). C’est ce qu’on appelle le model-driven design.
  • Impliquer les développeurs dans le processus de modélisation. Ce qui leur permet de comprendre très bien le modèle et prendre en charge la responsabilité de garantir son intégrité.

NB: Chaque développeur doit être impliqué dans un certain niveau de discussion sur le modèle et avoir un contact avec les experts du domaine et échanger à travers le Ubiquitous Language.

I.4.2. Les Building blocks

Le but de ces modèles est de présenter certains des éléments clés de la modélisation d'objet et de la conception de logiciels d’un point de vue axé sur le domaine.

Les building Blocks présentés par le schéma ci-dessous sont des patterns qui nous aident à concevoir nos modèles au seins des bounded contexts, et donc nos bounded contexts.

En microservices, comme on a disposition ces blocs pour construire nos bounded context. Nous devons se focaliser essentiellement sur l’aspect responsabilité des bounded contexts, comme l’explique le pattern Responsibility Layers décrit dansla structuration à grande échelle.

  • Les entités

Les entités sont les objets les plus importants dans le modèle, ils sont représentés par des ID uniques. Cet Id reste le même pendant le le cycle de vie de l’objet.

Attention, ce n’est pas toujours évident que l’ID ne change pas dans un cycle de vie d’un objet. Un exemple, dans la POO, les instances d’objets sont dans la mémoire un avec un id mais cela n’est pas garanti. Les instances sont déplacées et changées. Ceci, n’est pas un exemple d’implémentation du pattern entité.

L’id ne peut pas être la référence de l’instance dans la mémoire.

  • Les Value objects

Les value objects sont aussi des objets qui décrivent certaines valeurs du domaine sans avoir besoin d'être uniques. En effet, rendre tout unique n’est pas très pratique pour le maintien et la performance de notre système.

Il est très recommandé que les objets valeurs soient immuables, ils sont créés et jamais changés. Quand, on veut modifier on crée un autre object value. Cela facilite le partage des objets.

  • Les services

Quand on crée , les Concepts clés du domaine sont introduits dans la langue:

  • Les noms de leurs parts sont facilement mappés en objets.
  • Les verbes associés au nom identifiés deviennent une partie du comportement de ces objets.

Mais, dans certains cas il y a des actions qui n'appartiennent à aucun objet. Ces actions représentent en grande partie le comportement de notre domaine. Ils ne peuvent pas être ignorés dans la conception de notre modèle.

Ajouter ces comportements à des objets peut gâcher notre objet réel, et dans ce cas nous préférons les implémenter dans des fonctions séparés.

Par exemple, transférer de l'argent d'un compte à l'autre, devrait il être dans le compte d'envoi ou le compte de réception? Il se sent mal placé dans l'un ou l'autre.

Quand un tel comportement est identifié dans notre domaine, la bonne pratique est de le déclarer dans un service.

  • Les agrégats

Un agrégat est un groupe d’objets associés qui sont considérés comme une unité aux changements de données. L'agrégat est délimité par une frontière qui sépare les objets à l'intérieur de l’extérieur. Chaque agrégat a une racine (root). La racine est une Entité, et c'est la seule objet accessible depuis l'extérieur.

Les agrégats assurent l’intégrité des données. Par exemple, la suppression des roots dans les agrégats implique la suppression de tous les objets autour, car ça n’a pas de sens d’avoir des entités non référencées par un root dans les agrégats.

Il est possible que les root dans les agrégats passent des éléments d'objets internes à des objets externes mais à condition de faire une copie des object values et ne pas passer des références. Comme ça on ne s’occupe pas de ce qui arrive à ces objets à l'extérieur car cela n’affecte pas en aucun cas l’intégrité de l'agrégat.

Mais comment créer ces agrégats:

  • Encapsuler les entités et les objets values dans des clusters, essayer des créer des frontières.
  • Choisir une entité pour être le root, bien entendu celle qui est la plus adaptée, dans le modèle, pour exposer son id unique à l’extérieur
  • Faire en sorte que tout accès extérieur de l'agrégat, passe uniquement par le root.

Dans un système microservices, nous pouvons voir par exemple que le CRUD ne doit exister que pour modifier directement le root entity, les modifications des autres entités passent par des actions exécutés sur le root.

Diagramme : exemple d'agrégats avec des objets internes associés (entités et object values) et des objets externes , sous forme de copie et pas de référence.

  • Les Factories

Les entités et les agrégats peuvent être généralement complexes. C’est parfois très compliqué de les créer dans l’entité racine (ou root). Parfois, un objet client (extérieur) peut créer un agrégat et passer des paramètres, mais quand c’est laborieux et que ça nécessite une connaissance interne au structure (par rapport au relation entre les objets et les règles de gestion), et pour ne pas casser le principe d’encapsulation entre les contextes, nous utilisons le concept de Factory.

NB: la création des entités et des agrégats dans un constructeur d'agrégat est contradictoire avec le principe de domaine et la définition d'agrégat. (Comme le dit Eric Evans: c’est comme avoir une imprimante qui se construit toute seule dans une usine d'électronique)

La Factory est utilisée pour encapsuler les connaissances nécessaires à la création d'objets, et elle est particulièrement utile pour créer des agrégats.

NB: quand le root est créé, tous les objets encapsulés par les agrégats sont créés avec. Il est important que le processus de création soit atomique (aucune chance que le processus de création ne soit fait à moitié).

NB: Il y a des moments où une Factory n'est pas nécessaire, et un simple constructeur suffit. Surtout quand le processus est simple et qu’il n y a pas la complexité de créer des objets dans des objets.

  • Le repository

Tout comme le Factory qui s’occupe de la création des objets, le repository est aussi pattern qui gère le cycle de vie des objets dans le model-driven design.

  • Il encapsule la logique qui permet la récupération des références et la manipulation des objets.
  • Il réduit la complexité de gérer tout ce qui est infrastructure et persistance au niveau du domaine.
  • Son effet est le découplage entre le besoin de stocker des objets ou de leurs références, et accéder à Infrastructure de persistance sous-jacente.
  • A chaque appel, il invoque une requête qui passe par le root de l'agrégat et qui peut traverser les associations des entités et des objets values pour exécuter des opérations.

results matching ""

    No results matching ""