2009-11-02 11 views
12

Je cherche un exemple simple pour illustrer les avantages de l'utilisation d'un modèle de domaine riche. Idéalement, j'aimerais avoir une liste de codes avant et après (qui devrait être aussi courte que possible). La liste avant le code devrait montrer le problème résolu en utilisant un modèle de domaine anémique, et beaucoup de code de couche de service assez procédurale, et la liste de code après devrait montrer le même problème étant résolu en utilisant un riche, orienté objet modèle de domaine.Existe-t-il un exemple de modèle de domaine riche?

Idéalement, la liste de codes devrait être en Java ou Groovy, mais tout ce qui est assez similaire (par exemple C#) le ferait.

+2

Malheureusement, il est très difficile de décrire les avantages dans une réponse courte. Si vous écrivez un système qui contient beaucoup de comportement, par opposition à simplement insérer/mettre à jour/supprimer, vous pouvez bénéficier de l'encapsulation de la logique dans un ensemble de classes (vos modèles de domaine). Vous ne verrez probablement pas les avantages tant que vous n'aurez pas une solution suffisamment grande et que la logique de votre domaine est suffisamment complexe. Dans ce cas, il est très agréable que votre logique de domaine soit encapsulée dans un seul endroit. –

Répondre

-5

Cela ne répond pas exactement à votre question, mais je vois le contraire de la conception axée sur le domaine comme une conception axée sur la base de données. Dans une conception pilotée par base de données, le schéma de base de données est créé en premier, puis vous créez vos classes en toute connaissance de l'aspect du schéma. L'avantage est que vous comprenez mieux ce qui se passe «sous le capot» et minimisez les effets de l'inadéquation de l'impédance. Cependant, l'inconvénient est que le schéma de base de données, parce qu'il est relationnel plutôt qu'objectif, ne traduit pas vraiment aux objets (par exemple, il n'y a pas de concept de collection dans les bases de données relationnelles). Dans la conception pilotée par domaine, vous créez en théorie vos objets de données comme vous le feriez pour n'importe quelle autre classe, et vous traitez la base de données simplement comme une couche de persistance. En termes de Layman, la base de données est seulement un conteneur de stockage et vous ne vous souciez pas comment les objets sont stockés, seulement qu'ils sont stockés en quelque sorte. Cela élimine le décalage d'impédance et vous avez une chose de moins à s'inquiéter. En pratique, cependant, vous devez toujours être conscient de la façon dont les objets sont stockés, et il peut y avoir des problèmes de performances lorsque l'ORM que vous utilisez essaie de cracher une requête SQL complexe.

Edit:

Voici un exemple de ce que la conception pilotée par le domaine devrait être, en principe. Disons que vous avez une classe de personne, comme si (en C#):

public class Person 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public Address Address { get; set; } 
    public ICollection<Person> Relatives { get; set; } 
    public Company Employer { get; set; } 
} 

Maintenant, dans une base de données relationnelle, cela traduira probablement 3 tables, une table de personne, table d'adresses, et table de l'entreprise, avec tas de relations entre eux. Cependant, ceci est très différent de la façon dont le programmeur voit cet objet. Le programmeur le voit comme une instance d'un objet Person avec 4 paramètres, dont l'un est ICollection. Cela ne correspond pas très bien à la structure de la table de base de données, d'où la «non concordance d'impédance», ou en termes de Laymen, une différence de disposition entre le modèle relationnel et le modèle objet.

Dans la conception pilotée par le domaine, je devrais être en mesure de le faire:

Person person = new Person(); 
// set each property to something 
Database.Save(person); 

Maintenant, l'objet de personne est sauvée. Je peux le récupérer comme ceci:

Person databasePerson = Database.Get<Person>(idOfPerson); 

et il va retourner mon objet Person, tout comme la façon dont il était avant que je sauvé. De cette façon, je ne suis pas du tout préoccupé par la façon dont la base de données est en train de l'enregistrer, ou de s'inquiéter de la non-concordance d'impédance. Je l'enregistre simplement et le récupère au besoin.

C'est en théorie cependant. En pratique, vous devrez probablement spécifier manuellement le 'mapping', ou comment les classes savent quelle table/colonne dans la base de données pour obtenir des données. Cela peut devenir assez complexe lorsque vous essayez de mapper des types plus complexes tels que des dictionnaires et autres ADT, et aussi lorsque vous essayez de tirer des données de plusieurs tables dans une classe.

+4

Je ne pense pas que ce soit un exemple de modèle de domaine riche, car le domaine que vous décrivez ne contient aucun comportement. – JasonTrue

+1

Ce n'est pas un domaine riche. Dans un domaine riche, vous n'auriez probablement aucun setters, ou seulement quelques uns. – Martin

+0

Vous parlez de mapping relationnel objet qui est un concept totalement différent. Votre classe Person contient une structure de données, rien de plus. Vous avez besoin de méthodes et d'encapsulation (dissimulation de données et d'implémentation) pour le transformer en un objet réel. – inf3rno

2

Je pense que personne n'a fait ce genre de comparaison et si cela avait été le cas, ce ne serait pas petit. Domain Driven Design essaie de résoudre la complexité et un exemple simple ne contient pas de complexité. Peut-être Domain Driven design Step by Step

+0

lien est vicié .. – xenoterracide

3

Je vais vous donner un exemple simple de véritable code de production:

Person.groovy:

List addToGroup(Group group) { 
    Membership.link(this, group) 
    return groups() 
    } 

Membership.groovy:

static Membership link(person, group) { 
    def m = Membership.findByPersonAndGroup(person, group) 
    if (!m) { 
     m = new Membership() 
     person?.addToMemberships(m) 
     group?.addToMemberships(m) 
     m.save() 
    } 
    return m 
} 

Chaque fois que je veux pour lier une personne à un groupe, je peux juste faire personne.addToGroup (groupe)

Le code de procédure serait quelque chose comme ça, sur votre contrôleur:

def m = Membership.findByPersonAndGroup(person, group) 
if (!m) { 
     m = new Membership() 
     person?.addToMemberships(m) 
     group?.addToMemberships(m) 
     m.save() 
} 

À première vue, on peut dire que vous pouvez envelopper que dans une fonction et vous êtes bon pour aller. Mais l'avantage de la conception de domaine riche IMHO est qu'il est plus proche de la façon dont vous pensez, donc plus proche de rationaliser. Dans cet exemple particulier, je veux juste ajouter une personne à un groupe, et le code lira juste cela.

Ceci est un exemple court comme vous l'avez demandé, mais il est facile de développer cet exemple et de voir que vous pouvez créer des interactions complexes avec la modélisation de domaine appropriée.

Vous pouvez également voir le Transaction Script de Martin Fowler par rapport à Domain Model pour une brève explication de ces deux modèles, que je considère liés à DDD.