J'essaie de réévaluer notre architecture n-couche et j'aimerais avoir quelques suggestions basées sur vos expériences. Voici notre conception typique n-couche .NET (parfois n-tier).Conception de couche métier/service n-couche
Project.UI
Project.Services
Project.Business
Project.Model
Project.DataAccess
DataAccess se compose généralement de Entity Framework 4
et Repository
classes. Je tente de suivre le concept Aggregate Root
afin d'éviter d'avoir un référentiel pour la table, plus facile à dire qu'à faire dans mon expérience. J'ai tendance à avoir une correspondance d'environ 70% entre les dépôts et les tables.
Le modèle se compose généralement de mes entités Entity Framework 4
, j'utilise avec succès les entités EF Self-Tracking.
Business est ce que je lutte avec le plus. J'ai généralement une classe Manager
pour chaque Repository
. Cette classe contiendra des méthodes telles que .Add() qui effectuera une validation métier avant de les transférer vers repository.Add().
Services, typiquement je ne mettrai en œuvre que si en fait je cherche à créer une solution basée sur le service Web. Cette couche sera chargée de marshaler les demandes/réponses entre les DTO et les entités. Et surtout fournir l'interface plus coarse grained
. Par exemple, un TradingService.SubmitTrade(), qui est vraiment un facade
pour une transaction commerciale qui pourrait inclure AccountManager.ValidateCash(), OrderManager.SubmitOrder(), etc.
Préoccupations
Ma couche d'affaires est très entité centré, c'est vraiment le lien entre les entités et le référentiel, avec validation entre les deux. J'ai vu de nombreuses conceptions où le Service Layer est ce qui contient une référence aux dépôts (en ignorant par essence la "couche de gestion"). En substance, il sert le même but que ma couche d'affaires, il effectue la validation, mais sa responsabilité (et son nom) est un niveau plus élevé, une transaction commerciale plus grossière. En utilisant l'exemple ci-dessus, TradingService.submitTrade() ne délèguera pas à des classes de business manager, il interrogera lui-même les dépôts nécessaires, effectuera toutes les validations, etc.
J'aime mon design dans le sens où je peux réutiliser une entreprise méthode de couche dans plusieurs appels de service, mais je déteste le fait que pour chaque référentiel, j'ai un gestionnaire de couche de gestion correspondant, ce qui crée des tonnes de travail supplémentaire. Peut-être que la solution est un type différent de regroupement au niveau de la couche Business? Par exemple, combinez des classes Manager individuelles telles que PhoneManager et EmailManager (notez que j'ai les entités Phone et Email) dans une classe Logical Manager telle que ContactsManager (notez que je n'ai pas de type d'entité "Contact"). Avec des méthodes telles que ContactManager.GetPhones() et ContactManager.GetEmail(), etc.
Je suppose plus que tout que je me demande comment les autres organisent et délèguent des responsabilités, qu'ils aient la couche de service, la couche de gestion, les deux, etc. Ce qui contient la référence de contexte ORM, etc.
Avez-vous déjà eu un appel de service qui couvre plusieurs classes de gestionnaire d'entreprise? En d'autres termes, votre interface de service pourrait être encore plus grossière que les chefs d'entreprise. Par exemple, ContactService.CreateUser(), déléguera (servira de façade) à UserManager.CreateUser() et ContactManager.AddEmail(), et ContactManager.AddPhone(), etc. Même si nous avons regroupé la logique liée au courrier électronique et au téléphone dans ContactsManager , il n'y a rien de mal à avoir PhoneRepository et EmailRepository. Il me semble que les dépôts ne peuvent pas être "logiques" comme les gestionnaires. – e36M3
Rarement, mais c'est arrivé. Je préfère garder le plus de logique possible dans la couche de gestion, car elle est disponible si quelqu'un vient me voir plus tard et souhaite qu'une page Web fasse exactement les mêmes choses que le service (et oui, cela arrive). La page Web peut appeler la même logique de couche de gestion que le service, plutôt que d'appeler le service (ils sont sur le même serveur dans mon cas). Donc ce que je ferais dans un cas comme celui-ci est d'avoir une méthode de gestion d'entreprise qui peut elle-même utiliser d'autres chefs d'entreprise. J'essaie de l'éviter sauf quand il y a un réel gain de simplicité. – Tridus
Je sais ce que vous voulez dire, j'utilise DI pour créer mes gestionnaires pour leur fournir les dépôts requis via le constructeur. Un gestionnaire qui crée un autre gestionnaire exigerait que les gestionnaires connaissent le conteneur d'ID. Cependant, sans cela, il semble parfois que je duplique la logique en copiant et collant. Par exemple DataEntryManager.EnterPrice() et FileManager.UploadPriceFile(). Vous pouvez imaginer qu'après avoir analysé le "fichier des prix", nous aurions dû insérer des prix. Je peux dupliquer une partie de cette logique ou avoir FileManager réutiliser DataEntryManager. – e36M3