3

Récemment, j'ai eu du mal à comprendre si certaines méthodes, fonctions dans mon architecture étaient au bon endroit; dans la bonne couche. Je veux suivre the repository pattern of Martin Fowler pour découpler ma couche de service de la base de données.Modèle de référentiel sans objet de domaine pour récupérer des valeurs scalaires

La définition expliquée par Martin Fowler sur son site web, dire:

Un dépôt médiatise entre les couches de domaine et de cartographie de données, agissant comme une collection d'objets de domaine en mémoire.

Le problème est que j'ai beaucoup d'exigences où je dois obtenir par exemple la somme de toutes les factures. Comme vous pouvez le comprendre, la somme de toutes les factures est une valeur scalaire. Si je suis la définition de Martin Fowler, ce que je devrais faire est de créer une fonction qui retourne une liste d'objets de domaine de ma couche de dépôt qui est reçue par la couche de service qui boucle les objets pour calculer le total. Il est également possible que je ne comprenne pas l'essence de ce que ce modèle signifie ...

Je sais que les performances ne devraient pas être un problème lors de la conception de l'application parce que la maintenabilité est meilleure mais dans le cas, c'est à mon avis une perte de temps complète dans le développement et la performance pour ne pas créer une fonction dans la couche du référentiel qui renvoie une valeur décimale correspondant au total des factures et renvoie cette même valeur à partir de la couche de service. Matérialiser une liste d'objets et ensuite utiliser une seule propriété est une exagération même si vous pouvez ajouter une stratégie de chargement paresseux avec un ORM.

Est-il correct de renvoyer une valeur scalaire à partir de la couche de référentiel ou devrais-je résister à la tentation et toujours retourner les objets de domaine de cette couche et traiter toute la logique métier dans la couche de service?

J'ai également beaucoup d'endroits où mes présentateurs appelle directement mon dépôt au lieu d'appeler la couche de service qui appelle alors la couche de dépôt. C'est correct; acceptable d'appeler ce modèle de référentiel en dehors de la couche de service?

Notez que je ne souhaite pas renvoyer un résultat IQueryable de ma couche de référentiel car cela sera en totale contradiction avec le Law of Demeter.

En outre, je ne veux pas définir la requête directement dans ma couche de service, car je veux être en mesure de tester complètement cette couche; ne pas faire de test d'intégration.

+0

Je ne vois aucun problème à renvoyer une valeur scalaire. Quant à l'appel du référentiel à partir de l'interface utilisateur est correct dans certaines situations (remplissage de liste déroulante par exemple). C'est ok si ce n'est pas traité avant montré. C'est juste mon opinion si – Mathieu

Répondre

1

J'ai eu des problèmes similaires et j'ai fini par avoir une base et des interfaces de référentiel dérivées. La base aurait des méthodes standard: Fetch, Update, etc. tandis que l'interface dérivée aurait des méthodes spécifiques (obtenir la valeur scalaire, dans votre cas).

public interface IRepository { ... } 

et

public interface IInvoiceRepository : IRepository 
{ 
    int GetTotal(); 
} 

Vous créez ensuite une classe InvoiceRepository qui implémente l'interface. Il est préférable d'implémenter la logique métier dans une classe distincte, par exemple InvoiceBusinessObject qui reçoit une injection de dépendance de type IInvoiceRepository (utilisez un paramètre dans le constructeur). N'utilisez jamais l'implémentation dans votre couche de gestion.

public class InvoiceBusinessObject 
{ 
    private IInvoiceRepository rep; 

    public InvoiceBusinessObject(IInvoiceRepository rep) 
    { 
    this.rep = rep; 
    } 

    public int GetTotal() 
    { 
    return rep.GetTotal(); 
    } 
} 

La couche de service peut instancier la classe InvoiceRepository et injecter l'instance dans la classe d'objets métier:

public int GetTotalFromService() 
{ 
    IInvoiceRepository rep = new InvoiceRepository(); 
    InvoiceBusinessObject bizObj = new InvoiceBusinessObject(rep); 
    return bizObj.GetTotal(); 
} 
+0

De cette façon semble très compliqué IMO et je ne pense pas qu'il est approprié pour un objet métier de ne cacher qu'un dépôt. – MikeSW

2

Le problème est facilement résolu avec CQRS (comme concept). Avoir un référentiel de requête spécialisé qui peut être utilisé par l'interface utilisateur (ou par le contrôleur lors de l'utilisation de MVC). Ce repo peut interroger directement le db (les entités ORM cela n'a pas vraiment d'importance) et retourner ce dont vous avez besoin. Conservez les objets de domaine "lourd" et le référentiel correspondant uniquement lors de la mise à jour du modèle.

Questions connexes