Conception Pilotée par le Domaine (DDD)

La conception dirigée par le domaine (ou DDD, de l'anglais domain-driven design) est une approche de la conception logicielle fondée sur deux principes :

  1. les conceptions complexes doivent être basées sur une modélisation. Par exemple UML ou modèle entité-association ;

  2. l'accent doit être sur le domaine et la logique associée. Et à ce titre il constitue l'une des couches de l'architecture en couches (entre les couches utilisateur et infrastructure par exemple).

C'est une approche pour adresser les problèmes complexes à l'aide d'une connexion forte à l'implémentation d'un modèle aux coeurs de métiers en perpétuel évolution. 

Les promesses du DDD sont les suivantes :
  • Placing the project's primary focus on the core domain and domain logic
  • Basing complex designs on a model
  • Initiating a creative collaboration between technical and domain experts to iteratively cut ever closer to the conceptual heart of the problem.
Domain-driven design is not a technology or a methodology. DDD provides a structure of practices and terminology for making design decisions that focus and accelerate software projects dealing with complicated domains.

The term was coined by Eric Evans in his book of the same title.

Le langage omniprésent est le point de départ du DDD. Le principe de cet ubiquitous language est que chaque classe, méthode, variable etc. doit être nommée avec le plus grand soin afin que le code raconte au travers de ses objets l’histoire du métier, que le code retranscrive au plus près les réalités métier. L'objectif du recours à un langage omniprésent est que tout le monde parle le langage métier partout même dans le code, afin de s'assurer que le code n’est pas pollué par la technique et qu'il raconte le métier.

Les couches du DDD

Couche d'Interface Utilisateur

Optionelle. Responsible for drawing the screens the users use to interact with the application and translating the user’s inputs into application commands. It is important to note that the “users” can be human but can also be other applications connecting to our API, which corresponds entirely to the Boundary objects in the EBI architecture;

Couche Applicative

Orchestrates Domain objects to perform tasks required by the users: the Use Cases. It does not contain business logic. This relates to the Interactors in the EBI architecture, except that the Interactors were any object that was not related to the UI or an Entity and, in this case, the Application Layer only contains the objects relevant to a Use Case. This layer is where the Application Services belong, as they are the containers where the use case orchestration happens, using repositories, Domain Services, Entities, Value Objects or any other Domain object;

Couche du Domaine

This is the layer that contains all the business logic, the Domain Services, Entities, Events and any other object type that contains Business Logic. It obviously relates to the Entity object type of EBI. This is the heart of the system. The Domain Services will contain the Domain logic that does not quite fit in an Entity, usually orchestrating several entities in accomplishing some domain action;

Couche d'Infrastructure

The technical capabilities that support the layers above, ie. persistence or messaging.

Contextes Finis

Bounded contexts define a context where an isolated part of the model applies. The isolation can be achieved by decoupling technical logic, by code base segregation, by database schema segregation and also in terms of team organisation. The degree to which we isolate the bounded context is, as usual, dependent on the actual situation: the needs and possibilities we have.

Shared Kernel

In some situations, despite our desire to have completely isolated and decoupled components, it makes sense for some domain code to be shared by multiple components.

This will allow components to stay decoupled from each other, although coupled to that same shared code, the shared kernel.

That is the case, for example, with events that are triggered by one component and listened to by another one or several components. But it can also be the case with service interfaces and even entities.

Nevertheless, we should keep the shared kernel small, and be very careful when changing it so we don’t inadvertedly break other code using it. It is important that the code in the shared kernel is not changed without consultation with the other development teams using it.

Ressources

Commentaires

Posts les plus consultés de ce blog

Sécurité des Applications

Principes de la Programmation Orientée Objet

Principe de Responsabilité Unique