9 votes

DDD dans un système orienté règles configurable

Excusez mon ignorance, je suis relativement novice en matière de DDD, alors soyez indulgent.

Je travaille sur un grand système de gestion de données basé sur la configuration. Le système est construit en spécifiant des éléments de configuration (comme des règles de gestion, des processus et des validations) dans une syntaxe externe. Disons simplement que cette syntaxe était un conglomérat d'un DSL basé sur Groovy et de Drools.

J'aime les idées de simplicité qu'offre DDD, notamment la séparation des préoccupations d'infrastructure des concepts fondamentaux du domaine.

Cependant, j'ai du mal à appliquer certains des concepts de la DDD en raison de la nature configurable du système. Le comportement (processus), la validation et les règles de gestion sont définis en dehors du système. Ainsi, les entités du domaine n'ont intrinsèquement pas de comportement propre. Elles sont plutôt délicates pour le "validateur", le "moteur de règles" ou le "moteur de flux de travail".

Je vais clarifier avec un exemple. Disons que mon système gère les employés d'une entreprise. Sans trop réfléchir, vous imaginez que j'ai une entité "employé" et une entité "entreprise" dans mon domaine.

En suivant DDD, j'essaie de modéliser un scénario dans lequel un employé est promu. On pourrait voir apparaître une nouvelle méthode sur l'employé appelée promote (Employee.promote). Nous pourrions avoir une règle de gestion, indiquant qu'un employé ne peut pas être promu deux fois dans la même année (oui, tout ceci est inventé). Je pourrais donc avoir quelque chose comme :

public void promote( EmployeeLevel newLevel ) {
  if ( hasBeenPromotedThisYear( this ) {
    throw new InvalidPromotionException

Eh bien, dans l'application avec laquelle je travaille, cette règle de gestion serait externalisée vers un moteur de règles. En suivant DDD, je pourrais faire quelque chose comme :

if( promotionRules.isEligibleForPromotion(this)

Pour externaliser mes règles. Cependant, le système est beaucoup plus générique que cela. L'opération "promotion" elle-même est définie comme un "processus" par une configuration externe. Ainsi, au moment de la compilation, je ne saurais même pas si j'ai une opération de "promotion" disponible pour cet employé. Mon objet "employé" devient donc très dépouillé du point de vue du code, déléguant toutes les fonctionnalités à la configuration. Cela pourrait ressembler à quelque chose comme :

public class Employee {
  public void execute( Process process )

Ou alternativement

public class EmployeeProcess {
  public void process( Employee employee )

Ma question est la suivante : DDD a-t-il vraiment un sens dans cette application ? Devrais-je plutôt modéliser la collaboration des processus, les validations, les règles métier (moteur de règles) dans un sens autre que DDD ?

J'aime l'architecture en oignon, et je peux utiliser UI -> App Services -> Core -> Infrastructure pour garder une bonne séparation des préoccupations. Mais le noyau pourrait être constitué des collaborateurs mentionnés ci-dessus, par opposition à de véritables "concepts de domaine".

Une partie de moi pense que, dans ce cas, les "concepts de domaine" SONT les validateurs, les processeurs, les règles de gestion, car ils constituent le langage omniprésent dont nous parlons lorsque nous discutons de notre système. Dans ce cas, j'aurais des entités sans comportement réel (pour la plupart), et des concepts de domaine en termes de processeurs, de validateurs, de moteurs de règles qui réalisent le comportement dans le système.

J'ajoute un peu plus d'informations. Compte tenu de ma question ci-dessus, je travaillais à une solution qui ressemblerait à ceci :

org.example.app

org.example.domain - Employé - Entreprise - Niveau de l'employé

org.example.domain.shared - Processus - BusinessRule - Validateur

org.example.infrastructure

J'espère que ce petit bout de phrase apporte un peu de clarté.

Ainsi, les concepts Process, BusinessRule et Validator se trouveraient à l'intérieur du domaine, mais supporteraient le modèle de domaine en termes de ce que fait le système.

2voto

Andrey Adamovich Points 9404

De Wikipedia :

La conception pilotée par le domaine (DDD) est une approche du développement de logiciels pour besoins complexes en reliant profondément l'implémentation à un modèle évolutif de la modèle évolutif du concepts commerciaux fondamentaux .

Je pense que le validateur, le processus, la règle ne sont pas des concepts de base de votre entreprise. Ce sont plutôt des abstractions logicielles communes.

Je ne suis pas un grand fan de la DDD "by-the-book", mais pour être plus "orienté domaine", votre DSL et vos règles devraient en fait être construits autour de vos concepts d'entreprise pour donner plus de sens à cela.

Sous le capot, vous pouvez toujours utiliser des validateurs, des processus, des gestionnaires, des exécuteurs, etc., mais votre DSL/règlement sera plus lisible si vous y utilisez des concepts commerciaux plutôt que des abstractions logicielles.

MISE À JOUR : Puisque vous utilisez Groovy pour définir votre DSL, vous pouvez utiliser la résolution dynamique des noms de méthodes et la fonctionnalité de construction de Groovy pour créer des règles et des classes lisibles. Vous pouvez également tirer parti du principe "convention over configuration" pour intégrer une certaine logique. Par exemple, en Groovy, vous pouvez essayer de construire quelque chose de similaire à :

if (employee is "promotable") {
  start "promotion" for employee
}

is sera une méthode sur un objet de domaine de base qui vérifiera l'existence de la classe EmployeePromotableValidator, par exemple, qui peut aussi être une classe Groovy qui tire parti de l'expressivité du DSL de Groovy.

class EmployeePromotableValidator extends Validator<Employee> {

  boolean validate(Employee employee) {
    employee.age > 25 && employee.workingYears > 2
  }

}

start sera une méthode sur votre règle de base script qui recherchera EmployeePromotionProcess qui, elle aussi, peut être une classe Groovy.

Dans ce cas, le modèle de spécification est très simple, car il fait partie intégrante du langage :

if (employee is "promotable" && 
    employee is "advanced" && 
    employee.salary < 10000) {
  start( "salary increase", "10%" ) for employee
}

En général, les DSL avec l'aide de langages (semi-)fonctionnels comme Groovy/Scala peuvent être utilisés pour cacher les abstractions logicielles et rendre votre logique métier plus proéminente dans le code. Avec un simple Java, vous vous retrouverez avec beaucoup de code passe-partout qui finira par cacher toutes vos intentions.

1voto

Arnis L. Points 18316

Cela dépend de la nature exacte de votre domaine d'activité.

Si vous construisez une application de gestion de la relation client (crm) extra configurable - quelque chose qui se construit et qui fait tout - alors votre domaine d'activité consiste à rendre cela possible, d'où des noms comme Process , Executors etc. font partie de votre domaine.

Si vous créez une application qui doit suivre les informations relatives aux employés et à leur capacité de promotion, c'est que votre domaine d'activité concerne les employés, les chèques de salaire et les mesures de performance. Dans ce cas, traitez Process , Executors et autres objets similaires comme des intrus dans votre domaine.

À un certain niveau - même le langage de programmation lui-même est un outil envahissant qui brouille la solution du problème que vous dessinez dans votre esprit. Mais il est nécessaire, sinon vous ne seriez pas en mesure de le matérialiser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X