8
votes

Dans une architecture en couches utilisant un cadre d'entité, devrais-je renvoyer des cours de Poco de la BLL? (Directives d'architecture nécessaires)

J'ai lu trop probablement et souffre d'une surcharge d'informations. J'apprécierais donc une orientation explicite.

De ce que j'ai rassemblé, je peux utiliser le modèle T4 de T4 de VS2010 pour générer des cours de POCO qui ne sont pas liés directement à l'EF. Je les placerais dans leur propre projet alors que mon DAL aurait une classe dérivée ObjectContext, non?

Une fois que j'ai ces classes, est-ce une pratique acceptable de les utiliser dans la couche d'interface utilisateur? C'est-à-dire que l'une des classes générées est bookinfo qui détient des trucs sur des livres pour une bibliothèque publique (titre, édition, pages, résumé, etc.).

My Bll contiendrait une classe booksbll par exemple comme: xxx

donc, mes images dans mon application UI MVVM communiqueront avec la classe BLL ci-dessus et échangeront Bookinfo instances. Est-ce que ça va?

En outre, MVVM Postes sur la bande Suggérez la mise en œuvre IDATEERRORINFO à des fins de validation. Est-ce que ça va si je implique ladite interface sur la classe POCO générée? Je vois des échantillons que ceux-ci ont généré des classes de POCO contiennent toutes les propriétés virtuelles et Stuf et j'espère que l'ajout de ma propre logique irait bien?

Si cela fait une différence, à l'heure actuelle, mon application n'utilise pas WCF (ou Toute chose de réseautage).

En outre, si vous voyez quelque chose de terriblement faux avec la façon dont j'essaie de construire mon BLL, n'hésitez pas à offrir de l'aide dans cette zone.

Mise à jour (informations supplémentaires à la demande):

J'essaie de créer une application d'automatisation de la bibliothèque. C'est NON NABLEMENT BASE SUR PREMIÈRE.

Je pense avoir des couches comme suit:

  • Un projet composé de classes de POCO générées (Bookinfo, auteur, membre, éditeur, contact, etc.)
  • Un projet avec la classe dérivée ObjectContext (DAL?)
  • Une couche logique d'entreprise avec des classes comme celle que j'ai mentionnée ci-dessus (Booksblll, auteursbll, etc.)
  • une couche UI WPF à l'aide du motif MVVM. (D'où ma sous-question sur la mise en œuvre IDATAERRORINFO).

    Je me demande des choses comme à l'aide d'une instance de Booksbll dans une classe ViewModel, appelant résolvesearch () dessus pour obtenir un Liste et le présenter ... c'est-à-dire en utilisant les classes de POCO partout.

    ou devrais-je avoir des classes supplémentaires qui reflètent les classes de POCO exposées de mon BLL?

    Si des détails sont nécessaires, veuillez demander.


8 commentaires

Premièrement, pensez que vous devriez savoir, c'est qu'il n'y a pas de réponse «juste» à cette question - il existe plutôt de nombreuses solutions qui fonctionnent différemment. Ce n'est pas facile de choisir celui qui correspond parfaitement à vos besoins. C'est pourquoi vous obtenez une surcharge d'informations. Pour donner la "bonne" réponse, nous aurons besoin d'un peu plus d'informations sur l'application que vous construisez.


@Mark: Je peux voir comment les conseils d'architecture seraient subjectifs, mais que diriez-vous des questions spécifiques, c'est-à-dire. Utilisation de classes de POCO dans une couche d'interface utilisateur et mettez-vous en œuvre IDATAERRORINFO sur les classes de POCO? En tout cas, je vais essayer d'ajouter plus de détails sur mon projet.


@ForeverLearn: Si vous implémentez IDATAERRORINFO, vos classes ne sont plus pocos. L'idée de Pocos est qu'elles ne contiennent pas de code relatif aux préoccupations extérieures. Ainsi, si vous utilisez IDATAERRORINFO pour faciliter la validation des formulaires, vous ne faites plus face à POCOS. Ma compréhension en MVVM est que le "modèle" est le modèle d'application, pas le modèle de domaine, de sorte que votre domaine Pocos ne serait pas lié à vos contrôles d'interface utilisateur. Je ne connais pas les exemples dont vous parlez, mais j'espère sûrement que cela va bien d'ajouter votre propre logique à vos cours de logique d'entreprise, sinon ils seraient assez inutiles.


@ Codemonkey1: Oh ... <_>. Cela signifie-t-il donc que j'ai besoin de créer un tout nouveau ensemble de classes presque équivalentes dans mon BLL? (Bookinfobll, Authorbll, etc.)?


Je ne suis pas un expert sur le sujet Whalt, mais je suis presque positif, il ne devrait y avoir aucun problème. Je pense que c'est l'une des raisons de l'Efcodefirst également (examinez-vous si vous n'êtes pas déjà parce que cela devrait vous aider à beaucoup)


@ForeverLearn: a affiché une réponse parce que je suis resté à court de personnages dans les commentaires.


@ Codemonkey1: Je ne suis pas d'accord avec votre avis sur idataerrrorinfo . Cette interface est un simple contrat de System.componentModel pour signaler un état d'objet modèle. Il n'a rien directement à voir avec l'interface utilisateur, bien qu'elle soit principalement utilisée dans ce contexte. Si vous refusez de la mettre en œuvre sur les classes de POCO, vous devez payer le prix de la complexité supplémentaire. Vous ne pouvez pas justifier un prix plus élevé que par le purisme de conception et de modèle (à moins que vous n'ayez peut-être pas écrit de code en tant qu'artiste).


@Slauma: Je n'ai pas dit qu'il ne devrait pas le faire, seulement qu'il brise l'idée d'un poco. La question sur idataerrorinfo est floue, car elle est mise en œuvre dans le seul but d'interagir avec une technologie d'interface utilisateur spécifique, mais je pourrais être d'accord avec vous que cela pourrait toujours être appelé POCO. Cependant, il mélange toujours des préoccupations de l'interface utilisateur avec les préoccupations commerciales, ce qui n'est pas toujours mauvais mais ne fait pas de maillage dans le but de créer une architecture en couches.


3 Réponses :


4
votes

Ce que vous faites est fondamentalement le motif de référentiel, pour lequel l'entité cadre et POCO sont un excellent ajustement.

Donc, mes images de vie dans mon application UI MVVM communiqueront avec la classe BLL ci-dessus et échangeront des instances BookInfo. Est-ce que ça va?

C'est exactement ce que sont exactement les objets POCO; Il n'y a pas de différence entre les classes générées et comment vous les écririez à la main. C'est votre objetContext qui encapsule toute la logique autour de la persistance de toutes les modifications de la base de données, ce qui n'est pas directement exposé à votre UI.

Je ne suis personnellement familier avec idataerrrorinfo mais si, si maintenant, vos entités ne seront utilisées que dans cette application unique, je ne vois aucune raison de ne pas la mettre directement dans les classes générées. L'ajout au modèle T4 serait idéal si cela est possible, il vous éviterait de la signifier à la main pour chaque classe si les messages d'erreur suivent tout modèle logique.

En outre, si vous voyez quelque chose de terriblement faux avec la façon dont j'essaie de construire mon BLL, n'hésitez pas à offrir de l'aide dans cette zone.

Ce n'est pas terriblement faux par quelque moyen que ce soit, mais si vous envisagez d'écrire des tests d'unité contre votre BLL (que je recommanderais), vous souhaitez modifier votre objetContext Membre à iObjectContext . De cette façon, vous pouvez remplacer toute classe d'implémentation de l'interface iobjectContext au moment de l'exécution (telle que votre réel objetContext ), ce qui vous permettra de tester contre un contexte en mémoire (c'est-à-dire moqué) et ne doit pas avoir à toucher la base de données.

De même, pensez à remplacer votre Liste avec une interface de quelque sorte comme ilist ou ibindinglist ou le dénominateur commun le plus bas ienumerable . De cette façon, vous n'êtes pas lié directement à la liste des classes spécifiques et si vos besoins changent avec le temps, ce qui a tendance à se produire, il réduira le refactoring nécessaire pour remplacer votre liste < BookInfo> avec quelque chose d'autre, en supposant tout ce que vous le remplacez avec implémente l'interface que vous avez choisie.


1 commentaires

Merci pour les suggestions. Je vais les mâcher un peu.



3
votes

Vous ne devez pas besoin faire quoi que ce soit en particulier ... Comme Mark dit, il n'y a pas de réponse "droite". Toutefois, si votre demande est suffisamment simple que vous allez simplement dupliquer vos cours (E.G. Bookinfoui & Bookinfobll), vous recommandez simplement d'utiliser les classes de l'entreprise. La couche supplémentaire ne servirait pas de but, et cela ne devrait donc pas exister. Eric Evans à DDD recommande même de mettre toute votre logique dans la couche d'interface utilisateur si votre application est simple et possède très peu de logique commerciale.

Pour faire la distinction, la couche d'application doit avoir des classes qui modèle ce qui se passe dans l'application et la couche de domaine doit avoir des classes qui modèle ce qui se passe dans le domaine. Par exemple, si vous avez une page de recherche, votre couche d'interface utilisateur peut récupérer une liste d'objets de LivresearchResults à partir d'un livreRechervice dans la couche d'application, qui utiliserait le domaine pour tirer une liste de BookInfo.


5 commentaires

Votre exemple était en fait ce qui m'a conduit à cette question dans le premier palais. Je pensais que ma classe "LivresearchResult" n'était vraiment pas différente d'une classe de bookinfo ordinaire ... Alors, quel était le point d'avoir une nouvelle classe et que je me suis demandé si je pouvais utiliser directement la classe Bookinfo dans ma viewModel (en tant que POCO généré) .


Eh bien, je supposerais que Bookinfo contient des propriétés pour le titre, l'auteur, l'éditeur et que ces deux de ceux-ci sont des types complexes avec leurs propres ensembles de propriétés. Mais, est-ce que LivrearchResult se souciait vraiment de tous les détails, ou est-ce qu'il a peut-être juste besoin de BooktiTle, d'authorname, de publication? Il s'agit d'un exemple trivial, mais vous pouvez commencer à voir comment les modèles de LivresearchResult exactement ce dont nous avons besoin pour le résultat de la recherche sans tenir compte de ce qui peut être présent ou que vous ne pouvez pas être présent dans l'objet livre de notre entreprise.


Je suppose que tu pourrais avoir raison. J'ai tous les éléments liés à Bookinfo affichés, mais uniquement des noms d'auteurs et de nom d'éditeur. Et peut-être également autorisé, d'activer un clic sur un nom d'auteur et d'ouvrir une vue associée Affichage des détails de l'auteur. Mais, pour dire, addbook (), je devrais toujours passer à une image miroir de la bandité originale ... Sauf avec IdataERrorInfo implémenté sur elle. Hmm...


Si vous ne prévoyez pas une complexité supplémentaire plus tard, il semble que vous puissiez vous échapper avec une couche d'interface utilisateur et d'accès aux données, et vos classes d'entité pouvaient mettre en œuvre toutes les interfaces dont ils ont besoin pour la liaison et la validation de l'interface utilisateur.


D'accord. Merci pour les pensées de suivi.



2
votes

Les réponses à vos questions peuvent dépendre de la taille et de la complexité de votre application. Je crains donc d'avoir des arguments valides pour répondre à vos questions avec oui et non aussi.

Personnellement, je répondrai à vos deux questions principales avec oui:

est-il une pratique acceptable d'utiliser des classes POCO (domaine) dans la couche d'interface utilisateur?

Je suppose avec "la couche d'interface utilisateur", vous ne voulez vraiment pas dire la partie de la vue du motif MVVM, mais les images de vue. (La plupart des spécialistes MVVM discuteraient de laisser une vue directement référencer le modèle du tout, je crois.)

Il n'est pas inhabituel d'envelopper un POCO de votre projet de domaine en tant que propriété dans une vue de vue et de lier ce POCO emballé directement à la vue. Le Big Pro est: C'est facile. Vous n'avez pas besoin de classes de menuLodel supplémentaires ou de propriétés répliquées dans une viewModel, puis copiez ces propriétés entre les objets.

Toutefois, si vous utilisez WPF, vous devez prendre en compte que le moteur de liaison écrira directement dans vos propriétés POCO si vous les liez à une vue. Cela pourrait ne pas toujours être ce que vous voulez, surtout si vous travaillez avec des entités attachées et changées dans un formulaire WPF. Vous devez penser aux scénarios d'annulation ou à la manière dont vous restaurez les propriétés après une annulation qui a été modifiée par le moteur de liaison.

Dans mon projet actuel, je travaille avec des entités détachées: je charge le POCO à partir de la couche de données, détachez-le du contexte, jetez le contexte, puis travaillez avec cette copie dans la vue et liez-le à la vue. La mise à jour dans la couche de données se produit en créant un nouveau contexte, chargement de l'entité d'origine à partir de la DB par ID, puis mettant à jour les propriétés du POCO modifié qui a été lié à la vue. Donc, le problème des changements indispensables d'une entité attachée disparaît avec cette approche. Mais il y a aussi des inconvénients pour travailler avec des actionnements détachés (la mise à jour est plus complexe par exemple).

est-ce correct si je implémente l'interface idataerrrorinfo sur la classe POCO générée?

Si vous liez vos entités POCO à une vue (via une vue d'emballageModel), il ne s'agit pas seulement d'ok mais vous ne devez même pas Implément idataerrrorinfo sur la classe POCO si vous voulez exploiter la validation de la propriété intégrée du moteur de liaison WPF. Bien que cette interface soit principalement utilisée avec les technologies d'interface utilisateur, elle fait partie de System.componentModel Espace de noms et donc non directement liés à aucun espaces de noms d'interface utilisateur. Fondamentalement idatarserrorinfo n'est qu'un simple contrat qui prend en charge la déclaration de l'état de l'objet, qui pourrait également être utile en dehors d'un contexte d'assurance-chômage.

La même chose est vraie pour l'interface inotifyproperTychanged que vous auriez également besoin d'implémenter sur vos classes de POCO si vous les liez directement à une vue.

Je vois souvent des opinions qui ne seraient pas d'accord avec moi pour plusieurs raisons architecturales. Mais aucune de ces opinions ne fait valoir qu'une autre approche est plus facile. Si vous voudriez strictement voudriez éviter d'avoir des classes de modèle POCO dans votre couche de viewModel, vous devez ajouter une autre couche de cartographie avec une complexité et une programmation supplémentaires et un effort de maintenance. Donc, je voterais: gardez-le simple aussi longtemps que vous n'avez pas de raison convaincante et d'avantage clair pour rendre votre architecture plus complexe.


1 commentaires

Merci. Beaucoup de points pondérables, en particulier le scénario d'annulation.