93 votes

Modèle de référentiel vs DAL

Est-ce que c'est la même chose ? Je viens de finir de regarder Tutoriel sur la vitrine de Rob Connery et il semble qu'il s'agisse de techniques similaires. Je veux dire que lorsque j'implémente un objet DAL, j'ai les méthodes GetStuff, Add/Delete etc. et j'écris toujours l'interface en premier afin de pouvoir changer de db plus tard.

Est-ce que je confonds les choses ?

89voto

Kim Major Points 2733

Vous n'êtes certainement pas celui qui confond les choses. :-)

Je pense que la réponse à la question dépend du degré de purisme que vous voulez avoir.

Si vous voulez un point de vue strictement DDD, cela vous mènera sur une voie. Si vous considérez le référentiel comme un modèle qui nous a aidés à normaliser l'interface de la couche qui sépare les services et la base de données, vous en prendrez un autre.

De mon point de vue, le référentiel n'est qu'une couche d'accès aux données clairement spécifiée ou, en d'autres termes, un moyen normalisé de mettre en œuvre votre couche d'accès aux données. Il existe quelques différences entre les différentes implémentations de référentiel, mais le concept est le même.

Certaines personnes imposeront davantage de contraintes DDD au référentiel, tandis que d'autres utiliseront le référentiel comme un médiateur pratique entre la base de données et la couche de services. Un référentiel comme un DAL isole la couche service des spécificités de l'accès aux données.

Un problème d'implémentation qui semble les différencier est qu'un référentiel est souvent créé avec des méthodes qui prennent une spécification. Le référentiel renvoie les données qui répondent à cette spécification. La plupart des DALs traditionnels que j'ai vus, auront un ensemble plus large de méthodes où la méthode prendra un nombre quelconque de paramètres. Bien que cela puisse sembler une petite différence, c'est un gros problème lorsque vous entrez dans le domaine de Linq et des Expressions. Notre interface de référentiel par défaut ressemble à ceci :

public interface IRepository : IDisposable
{
    T[] GetAll<T>();
    T[] GetAll<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
    void Delete<T>(T entity);
    void Add<T>(T entity);
    int SaveChanges();
    DbTransaction BeginTransaction();
}

S'agit-il d'un DAL ou d'un référentiel ? Dans ce cas, je pense que c'est les deux.

Kim

5 votes

J'arrive tard, mais pourquoi T[] et non List<T> (ou similaire) ?

29 votes

Peut-être que IEnumerable<T> serait la meilleure solution.

1 votes

Je pense que IQueryable<T> serait le meilleur choix, car il permet de chaîner des méthodes et de différer l'exécution en laissant la base de données faire tout le travail.

44voto

Jeromy Irvine Points 5308

Un référentiel est un modèle qui peut être appliqué de nombreuses façons différentes, tandis que la couche d'accès aux données a une responsabilité très claire : le DAL doit savoir comment se connecter à votre stockage de données pour effectuer des opérations CRUD.

Un répertoire peut être un DAL, mais il peut aussi se situer devant le DAL et servir de pont entre la couche des objets métier et la couche des données. L'implémentation utilisée varie d'un projet à l'autre.

23voto

ngieschen Points 2630

Une différence importante est qu'une DAO est un moyen générique de gérer la persistance pour toute entité de votre domaine. Un référentiel, quant à lui, ne traite que les racines agrégées.

26 votes

La première chose à comprendre est qu'un référentiel en tant que modèle fait partie d'un système plus large connu sous le nom de conception pilotée par le domaine. Dans DDD, les objets du domaine sont regroupés en agrégats, chacun ayant une racine d'agrégat. Par exemple, PurchaseOrder est une racine d'agrégat et OrderItems sont des enfants au sein de la racine d'agrégat. Un référentiel ne traite que des racines d'agrégats. C'est-à-dire qu'un OrderItem, par exemple, n'est jamais chargé indépendamment de sa racine agrégée. Ainsi, vous n'auriez jamais un référentiel OrderItem dans DDD. Cependant, dans un système non DDD, vous pourriez avoir un OrderItemDao puisque Dao n'est pas limité aux racines agrégées.

0 votes

NG, merci ! J'avais commencé à le voir de cette façon, mais cela rend les choses plus claires. Il va falloir que je commence à lire toute la littérature sur le DDD !

0 votes

@bingle, excellente description des racines agrégées et de la façon dont les objets enfants sont chargés par un référentiel. Où se trouve un référentiel dans une application multicouche ? Je pourrais le voir dans une bibliothèque de la couche d'accès aux données, mais comme il charge des objets enfants, devrait-il plutôt se trouver dans la bibliothèque de la couche logique ? Mon instinct me dit que c'est la couche d'accès aux données, mais je voulais avoir votre avis sur la question.

12voto

Thomas Jung Points 571

Je cherchais une réponse à une question similaire et je suis d'accord avec les deux réponses les mieux classées. En essayant de clarifier cette question pour moi-même, j'ai trouvé que si Les spécifications, qui vont de pair avec le modèle de référentiel, sont implémentées en tant que membres de première classe du modèle de domaine, alors je peux

  • réutiliser Définitions des spécifications avec différents paramètres,
  • manipuler les paramètres des instances de spécification existantes (par exemple, pour les spécialiser),
  • moissonneuse-batteuse les,
  • exécuter une logique d'entreprise sur eux sans jamais avoir à accéder à la base de données,
  • et, bien sûr, test unitaire Ils sont indépendants des implémentations réelles du référentiel.

Je peux même aller jusqu'à dire que sauf si le pattern Repository est utilisé avec le pattern Specification, ce n'est pas vraiment un "Repository", mais un DAL. Un exemple artificiel en pseudo-code :

specification100 = new AccountHasMoreOrdersThan(100)
specification200 = new AccountHasMoreOrdersThan(200)

assert that specification200.isSpecialCaseOf(specification100)

specificationAge = new AccountIsOlderThan('2000-01-01')

combinedSpec = new CompositeSpecification(
    SpecificationOperator.And, specification200, specificationAge)

for each account in Repository<Account>.GetAllSatisfying(combinedSpec)
    assert that account.Created < '2000-01-01'
    assert that account.Orders.Count > 200

Voir La spécification de Fowler Essai pour plus de détails (c'est sur cette base que je me suis basé).

Un DAL aurait des méthodes spécialisées comme

IoCManager.InstanceFor<IAccountDAO>()
    .GetAccountsWithAtLeastOrdersAndCreatedBefore(200, '2000-01-01')

Vous pouvez voir comment cela peut rapidement devenir lourd, en particulier parce que vous devez définir chacune des interfaces DAL/DAO avec cette approche. y mettre en œuvre la méthode d'interrogation DAL.

Dans .NET, les requêtes LINQ peut est une façon de mettre en œuvre les spécifications, mais la combinaison des spécifications (expressions) peut ne pas être aussi facile qu'avec une solution maison. Certaines idées à ce sujet sont décrites dans cette question SO .

2voto

eglasius Points 26221

Mon opinion personnelle est qu'il s'agit de cartographie, vous voyez : http://www.martinfowler.com/eaaCatalog/repository.html . Ainsi, la sortie/l'entrée du référentiel sont des objets de domaine, qui sur le DAL peuvent être n'importe quoi. Pour moi, il s'agit d'un ajout/restriction important, car vous pouvez ajouter une implémentation de référentiel pour une base de données/un service/quelque chose d'autre avec une mise en page différente, et vous avez un endroit clair où vous concentrer pour faire le mappage. Si vous n'utilisez pas cette restriction et que le mappage est effectué ailleurs, le fait d'avoir différentes façons de représenter les données peut avoir un impact sur le code à des endroits où il ne devrait pas être modifié.

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