Strictement parlant, un référentiel offre une sémantique de collection pour obtenir/placer des objets de domaine. Il fournit une abstraction autour de votre implémentation de la matérialisation (ORM, hand-rolled, mock) afin que les consommateurs des objets du domaine soient découplés de ces détails. En pratique, un référentiel résume généralement l'accès à des entités, c'est-à-dire des objets de domaine avec une identité, et généralement un cycle de vie persistant (dans la version DDD, un référentiel fournit un accès à des racines agrégées).
Une interface minimale pour un dépôt est la suivante:
void Add(T entity);
void Remove(T entity);
T GetById(object id);
IEnumerable<T> Find(Specification spec);
Bien que vous verrez des différences de nommage et l'ajout de la sémantique Save/saveOrUpdate, ce qui précède est l'idée « pure ». Vous obtenez l'ICollection Ajouter/Supprimer des membres plus quelques trouveurs.Si vous n'utilisez pas IQueryable, vous verrez aussi des méthodes de recherche sur le référentiel comme:
FindCustomersHavingOrders();
FindCustomersHavingPremiumStatus();
Il y a deux problèmes liés à l'utilisation IQueryable dans ce contexte. Le premier est la possibilité de divulguer au client les détails de la mise en œuvre sous la forme des relations de l'objet du domaine, c'est-à-dire des violations de la loi de Demeter. La seconde est que le référentiel acquiert des responsabilités de recherche qui peuvent ne pas appartenir au référentiel d'objet de domaine proprement dit, par exemple, trouver des projections qui concernent moins l'objet de domaine demandé que les données associées. En outre, l'utilisation de IQueryable 'interrompt' le modèle: Un référentiel avec IQueryable peut ou non fournir un accès aux 'objets de domaine'. IQueryable donne au client beaucoup d'options sur ce qui sera matérialisé lorsque la requête est finalement exécutée. C'est l'idée maîtresse du débat sur l'utilisation de IQueryable. En ce qui concerne les valeurs scalaires, vous ne devez pas utiliser un référentiel pour renvoyer des valeurs scalaires. Si vous avez besoin d'un scalaire, vous obtiendrez généralement cela de l'entité elle-même. Si cela semble inefficace, c'est le cas, mais vous ne le remarquerez peut-être pas, en fonction de vos caractéristiques/exigences de charge. Dans les cas où vous avez besoin d'autres vues d'un objet de domaine, pour des raisons de performances ou parce que vous devez fusionner des données de plusieurs objets de domaine, vous avez deux options.
1) Utilisez le référentiel de l'entité pour trouver les entités spécifiées et le projet/mappage vers une vue aplatie. 2) Créez une interface finder dédiée au retour d'un nouveau type de domaine qui encapsule la vue aplatie dont vous avez besoin. Ce ne serait pas un référentiel, car il n'y aurait pas de sémantique de collection, mais il pourrait utiliser des dépôts existants sous les couvertures. Une chose à considérer si vous utilisez un référentiel «pur» pour accéder aux entités persistantes est que vous compromettez certains des avantages d'un ORM. Dans une implémentation «pure», le client ne peut pas fournir de contexte sur la façon dont l'objet de domaine sera utilisé, donc vous ne pouvez pas dire au référentiel: 'hé, je vais juste changer la propriété customer.Name, donc don ne vous embêtez pas à obtenir ces références pleines d'empressement. D'un autre côté, la question est de savoir si un client devrait savoir à ce sujet. C'est une épée à double tranchant. En ce qui concerne l'utilisation de IQueryable, la plupart des utilisateurs semblent être à l'aise pour «casser» le motif afin d'obtenir les avantages de la composition dynamique des requêtes, en particulier pour les responsabilités du client telles que la pagination/le tri. Dans ce cas, vous pourriez avoir:
Add(T entity);
Remove(T entity);
T GetById(object id);
IQueryable<T> Find();
et vous pouvez en finir avec toutes ces méthodes sur mesure du Finder, qui encombrent vraiment le référentiel que vos besoins de requête croître.
Je suis tombé sur le post de jbogard sur ce sujet aujourd'hui: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/09/02/ddd-repository-implementation-patterns.aspx – pfries
+1: ". La plupart des gens semblent être à l'aise avec 'casser' le modèle pour obtenir les avantages de la composition de requête dynamique ... " –