2009-09-25 7 views
3

Je viens de terminer la lecture d'Eric Evans, «Conception orientée domaine: s'attaquer à la complexité au cœur du logiciel» et j'essaie d'écrire ma première application centrée sur le domaine (en C#).Premiers pas avec TDD et DDD

L'application sera utilisée par notre service d'assistance pour suivre l'attribution des ordinateurs aux utilisateurs.

J'ai esquissé un diagramme de classes simple pour refléter une partie du domaine. Il ressemble à ceci ...

Class diagram showing two classes: Owner and Computer. There is a one-way associate between Computer and Owner named 'Allocate to' http://www.freeimagehosting.net/uploads/183dd57031.jpg

J'ai aussi identifié mon premier long métrage (d'allouer un ordinateur à un utilisateur) et ai écrit un test pour elle ...

[Test] 
public void AllocateToUser() 
{ 
    var user = new Owner("user1"); 
    var computer = new Computer("computer1"); 

    computer.Allocate(user); 

    Assert.AreEqual(user.Username, computer.AllocatedTo.Username); 
} 

Enfin, j'ai écrit du code pour faire passer le test.

public class Computer 
{ 
    public Computer(string name) 
    { 
     Name = name; 
    } 

    public string Name 
    { get; private set; } 

    public Owner AllocatedTo 
    { get; private set; } 

    public void Allocate(Owner owner) 
    { 
     AllocatedTo = owner; 
    } 
} 

public class Owner 
{ 
    public Owner(string username) 
    { 
     Username = username; 
    } 

    public string Username 
    { get; private set; } 
} 

Jusqu'ici, tout va bien (je pense).

Toutefois, il est clair que cela ne s'applique pas à la persistance. Je pense que je dois introduire une classe de référentiel pour l'ordinateur. Quelque chose comme ça peut-être:

public class ComputerRepository 
{ 
    public void Store(Computer computer) 
    { 
     //Some persistence logic here (possibly using NHibernate?) 
    } 
} 

Maintenant, je suis coincé. Comment s'assurer que les modifications apportées à l'utilisateur alloué à un ordinateur sont transmises au référentiel?

Il me semble avoir les options suivantes:

  1. Modifier la mise en œuvre de la Allouer méthode de la classe d'ordinateur à instanstiate une instance de ComputerRepositry et invoquer la méthode de magasin.

  2. Créer une interface IComputerRepository; modifier le constructeur de l'ordinateur pour exiger qu'une instance d'une classe implémentant IComputerRepository soit fournie. Dans la méthode Allocate, appelez Store contre cette instance injectée.

  3. Créez un service (AllocationService) qui terminera un appel à Allouer et Stocker.

  4. passe resposibility au client, forçant deux étapes pour le code d'appel:

    • Invoke Allouer sur une instance de la classe informatique
    • instancier une instance de la ComputerRepository et appeler Store.

Aucune de ces semble satisfaisant:

  1. est difficile à tester, comme je serais instancié avec le dépôt directement dans la classe d'ordinateur.

  2. évite ce problème en utilisant l'injection de dépendances. Cependant, il est encore moche, car je dois passer dans une instance de IComputerRepository chaque fois que je veux instancier l'ordinateur.

  3. est trop procédural, ne parvenant pas à encapsuler le comportement dans les classes d'entités de domaine.

  4. semble juste moche.

Que devrais-je faire?

Répondre

5

Habituellement, je voudrais traiter le comportement et la persistance comme deux préoccupations différentes et les tester séparément.

Les objets de domaine doivent rester inconscients de l'existence des référentiels (bien que ce ne soit clairement pas l'inverse). Ce que nous avons fait dans cette situation est de créer un contrôleur (ou un service) chargé de charger les objets appropriés à partir de leurs référentiels, d'invoquer le comportement sur les objets puis d'appeler les référentiels pour maintenir les mises à jour.

Vous pouvez ensuite tester le contrôleur à l'aide d'un référentiel Mock pour vérifier que le contrôleur appelle le référentiel avec les objets mis à jour.