Symfony ExpressionLanguage : Comment utiliser ce composant ?
Le composant Symfony ExpressionLanguage : qu'est-ce que c'est ? Quand et comment l'utiliser ? Comment créer des expressions lors de cas plus complexes ?
Sommaire
Le Domain Driven Design, décrit dans le livre d’Eric Evans “Domain Driven Design, Tackling Complexity in the Heart of Software”, permet de mieux appréhender la complexité d’un projet en partageant une approche et un langage communs par tous les membres impliqués dans la construction d’une application.
Sa définition peut être énoncée en 3 points clés :
Les experts métiers utilisent leur propre jargon, tandis que les développeurs ont leur propre langage pour discuter de la façon dont ils vont implémenter techniquement ce qui est exprimé par le métier. Ainsi, une déconnexion survient entre le vocabulaire utilisé dans le code et celui utilisé dans les discussions quotidiennes. Eric Evans souligne ici un point crucial : utiliser le modèle en tant que pierre angulaire du langage. Impliquer l’équipe à s’exercer à utiliser ce langage partagé entre tous les membres de l'équipe et dans le code. Utiliser le même vocabulaire à l’écrit, à l’oral, dans les diagrammes… Cela rendra toute communication plus cohérente et explicite. Le fort couplage entre le langage et le modèle permet ainsi de réduire toute confusion et de rendre le design lisible. Tout changement dans le langage partagé impliquera donc forcément du changement dans le code. Il est important de revoir le design, renommer les méthodes ou classes pour convenir à l'évolution du modèle.
Dans une application complexe, de nombreuses choses sont mélangées au sein du code : notre code métier est couplé avec notre base de données, notre interface utilisateur, des librairies externes… Cela engendre une plus grande difficulté pour faire évoluer le code, et même le comprendre. Nous perdons le plus important dans la représentation de notre code métier : sa compréhension et son évolutivité. Le Domain Driven Design permet de répondre à ce problème en isolant complètement le code métier de notre application et en éliminant toute dépendance superflue : infrastructure, interface utilisateur, logique applicative…
Ainsi l’architecture adoptée du Domain Driven Design est composée de 4 couches. Voyons cela plus en détail.
Cette couche contient l’information sur le domaine. C’est le coeur de l’application. C’est ici que votre code métier vit. Le stockage de données est une tache délaissée à la couche infrastructure. Nous détaillerons plus profondément comment modéliser notre métier dans la partie suivante.
Cette couche a pour responsabilité de présenter les informations observables du systèmes à l’utilisateur et interpréter ses intentions vis-à-vis du système.
Cette couche est responsable de la coordination de l’activité de l’application. Aucune logique métier n’est présente dans cette couche, et elle ne maintient aucun état des objets du domaine. Cependant, elle peut contenir un état de progression d’une tache applicative.
Cette couche cache les détails d'implémentation technique de l’application, et s'occupe de la persistance des données du modèle. La communication entre les couches fait parti du rôle de l’infrastructure. Ainsi, tout ce qui est choix d’ORM, de serializer ou tout autre détail technique est implémenté dans cette couche. Cela a un gros bénéfice : la couche domaine n’est pas du tout consciente des choix techniques, et donc aucune dépendance n’est introduite avec notre modèle.
Ce découpage en couches permet aux objets du domaine de se concentrer à modéliser le métier, car ils n’ont pas la responsabilité de se persister en base de données, de s’afficher… Voilà donc un autre point intéressant : l'indépendance du domaine, le fait de se concentrer uniquement sur le modèle du domaine, et l'isoler de tout système externe.
Nous venons de voir que la couche domain est celle qui contient toute la logique métier. La modélisation du domaine est faite avec de nombreux éléments. Voyons en quelques uns en détail.
Ce sont des objets avec une identité et un cycle de vie (ex: un Customer, un Purchase)
Elément clé du Domain Driven Design, un Value Object peut être défini de la sorte : un objet dont la notion d’égalité n’est pas basée sur son identité mais sur ses attributs. Ainsi, une date, une devise ou encore une adresse sont des candidats naturels pour devenir des Value Objects.
Les Value Objects permettent de nommer explicitement des concepts clés de notre modèle, d’en améliorer la lisibilité et la communication. Il est fortement conseillé de rendre les Value Objects immuables, car s’ils sont partagés, ils peuvent mettre en péril l’intégrité des données.
Quand certaines opérations agissent sur notre domaine et qu'elles ne sont pas la responsabilité d'une entité ou d'un value object, il est nécessaire de créer un service du domaine. Le nom de ce service doit faire parti du ubiquitous language.
Les événements métiers permettent de modéliser l'information sur l'activité du domaine. Un domain event est une représentation de quelque chose qui s'est passé dans le domaine.
Pour chaque entité qui nécessite un accès, il faut créer une interface qui définira l’ajout et la suppression, ainsi que la sélection d’objets selon différents critères. L’implémentation de cette interface sera effectuée dans la couche infrastructure (notre domaine ne sait pas comment les objets sont persistés ou récupérés)
Un dernier aspect que j’aimerai aborder concerne le pattern specification. Ce dernier ne fait pas parti des building blocks du Domain Driven Design, mais présente de nombreux avantages. Très simple à mettre en place, il permet d’encapsuler vos règles métiers dans une classe avec une sémantique précise.
<?php
class RocketCanBeLaunched implements Specification
{
public function isSatisfiedBy($rocket)
{
foreach ($rocket->getAstronauts() as $astronaut) {
if (false === $astronaut->isReady()) {
return false;
}
}
return true;
}
}
Les spécifications ont un réel intérêt car elles présentent les avantages suivants :
Il est clair que définir ses règles métiers au travers de spécifications accroît la lisibilité et la maintenabilité de votre application.
Tous ces patterns permettent ainsi une meilleure séparation des responsabilités et ont pour objectifs de rendre explicite notre modèle.
Le Domain Driven Design permet donc de se focaliser sur le métier, plutôt que la technique. Afin d'obtenir un domaine autonome, notre application peut être divisée en quatre couches : Presentation, Application, Domain et Infrastructure.
Penser à sa modélisation métier en communiquant et en utilisant un langage partagé au sein de l’équipe permettra une meilleure lisibilité. De plus, prendre du recul avant d’implémenter une fonctionnalité pour savoir dans quel contexte cette dernière intervient vous garantira une meilleure maintenabilité, ainsi qu’une plus grande aisance lors de la lecture de votre code. Le ubiquitous language et les outils de modélisation du modèle permettent de faire apparaître l'intention dans le code, et d'expliciter les contextes. N'est-ce pas une approche intéressante?
Domain Driven Design : des armes pour affronter la complexité
Auteur(s)
Romain Pierlot
Diplomé de l'ISEP en 2013, Romain Pierlot est ingénieur en Etudes et Développement chez Eleven Labs, avec qui il s'amuse comme un petit fou.
Vous souhaitez en savoir plus sur le sujet ?
Organisons un échange !
Notre équipe d'experts répond à toutes vos questions.
Nous contacterDécouvrez nos autres contenus dans le même thème
Le composant Symfony ExpressionLanguage : qu'est-ce que c'est ? Quand et comment l'utiliser ? Comment créer des expressions lors de cas plus complexes ?
Découvrez comment réaliser du typage générique en PHP : introduction et définition du concept, conseils et explications pas-à-pas de cas pratique.
Découvrez un cas d'usage d'intégration d'un CRM avec une application e-commerce, en asynchrone, avec Hubspot et RabbitMQ