2010-04-29 4 views
1

J'essaie de mettre en pratique la première approche du modèle et j'élabore un modèle de domaine. Mon exigence est assez simple: UserSession peut avoir plusieurs ShoppingCartItems. Je commencerais par dire que je vais appliquer les interfaces du modèle de domaine aux entités générées par Linq2Sql (en utilisant des classes partielles). Mon exigence se traduit par trois tables de base de données (UserSession, Product, ShoppingCartItem où ProductId et UserSessionId sont des clés étrangères dans la table ShoppingCartItem). Linq2Sql génère ces entités pour moi. Je sais que je ne devrais même pas traiter de la base de données à ce stade, mais je pense qu'il est important de le mentionner.Application du modèle de domaine au-dessus des entités Linq2Sql

La racine agrégée est UserSession car un ShoppingCartItem ne peut pas exister sans UserSession, mais je ne suis pas clair sur le reste. Qu'en est-il du produit? C'est une entité de manière défensive mais doit-elle être associée à ShoppingCartItem?

Voici quelques suggestions (ils pourraient tous être mises en œuvre incorrectes):

public interface IUserSession { 
    public Guid Id { get; set; } 
    public IList<IShoppingCartItem> ShoppingCartItems{ get; set; } 
} 

public interface IShoppingCartItem { 
    public Guid UserSessionId { get; set; } 
    public int ProductId { get; set; }   
} 

Un autre serait:

public interface IUserSession { 
    public Guid Id { get; set; } 
    public IList<IShoppingCartItem> ShoppingCartItems{ get; set; } 
} 

public interface IShoppingCartItem { 
    public Guid UserSessionId { get; set; } 
    public IProduct Product { get; set; }   
} 

Un troisième est:

public interface IUserSession { 
    public Guid Id { get; set; } 
    public IList<IShoppingCartItemColletion> ShoppingCartItems{ get; set; } 
} 

public interface IShoppingCartItemColletion { 
    public IUserSession UserSession { get; set; } 
    public IProduct Product { get; set; }  
} 

public interface IProduct { 
    public int ProductId { get; set; }  
} 

I J'ai l'impression que mon esprit est trop étroitement lié aux modèles de bases de données et aux tableaux, ce qui rend la chose difficile à saisir. Quelqu'un veut-il découpler?

Répondre

2

On dirait que vous êtes sur la bonne voie. La moitié de l'ensemble "faire DDD droit" a les bonnes classes de base. Jetez un oeil à ce grand DDD appliquée à C# ressource:

http://dddpds.codeplex.com/

Le code source est disponible et est très lisible. Donc, en ce qui concerne l'identification dans le modèle. L'ID est une chose de base de données et l'approche habituelle est de garder toute la persistance hors du modèle et de restreindre le modèle à la logique métier. Cependant, on fait normalement une exception pour l'identifiant et il enterre dans la classe de base du modèle comme ceci:

public class ModelBase { 
    protected readonly object m_Key; 
    public ModelBase(object key) { 
    m_Key = key; 
    } 
} 

Cette clé est utilisée par votre couche de persistance de parler à la base de données et est opaque. Il est tout à fait correct de baisser la clé au type requis, car vous savez de quoi il s'agit.

De plus, les objets de domaine se trouvent à peu près au fond de votre pile d'architecture (juste au-dessus de la couche Infrastructure). Cela signifie que vous pouvez en faire des classes concrètes. Vous ne disposerez pas de plusieurs implémentations des modèles de domaine, les interfaces sont donc inutiles, ce qui est à propos de Domain Driven Design - Domaine d'abord.

public Class UserSession : ModelBase { 
    public UserSession(Guid Id):base(Id) {} 

    public Guid Id { get{ return m_Key as Guid;} } 
    public IList<ShoppingCartItem> ShoppingCartItems{ get; set; } 
} 

public class ShoppingCartItem : ModelBase { 
    public ShoppingCartItem():base(null) {} 

    public UserSession UserSession { get; set; } 
    public Product Product { get; set; }   
} 
+0

Igor, et si je voulais ajouter Quantité à l'entité ShoppingCartItem? Aurais-je simplement ajouter en public int Quantité {get; définir;} à elle? – Thomas

+0

Oui. Cela me frappe comme une propriété de domaine, donc il appartient au modèle. –

1

panier d'achats typiques ou des exemples d'ordre de client préfèrent faire UserSession (ou ordre) la racine de l'agrégat. Les éléments individuels doivent être des enfants de cette session/commande. C'est à vous de décider si les articles individuels dans le panier doivent avoir un identifiant significatif. Je préférerais ne pas, puisque 5 widgets dans le panier sont indiscernables d'autres 5 widgets. Par conséquent, je voudrais modéliser des articles de chariot comme une collection d'objets de valeur.

Problème commun avec les articles de panier est de savoir s'ils doivent inclure le prix, ou non.Si vous incluez le prix, votre panier sera indépendant des changements de prix du produit. Il est très souhaitable si vous voulez stocker votre panier pour des raisons historiques, car il est utile de savoir combien les articles dans le panier coûtent selon le prix quand ils ont été achetés, et non selon le courant.

Le produit devrait former un agrégat définitif par lui-même. Période.

Maintenant, je ne sais pas si tout cela est facilement implémentable dans LINQ to SQL, mais vous pouvez essayer.

Questions connexes