Je crée une application WPF utilisant un service WCF pour interagir avec la source de données. J'utilise DI pour le client et le serveur WCF pour vous assurer un code découplé, mais je ne sais pas comment gérer le transfert de données à partir d'une interface utilisateur à l'interface utilisateur. P>
Pour conserver les couches, les données distinctes sont actuellement transférées de la base de données à l'interface utilisateur par plusieurs étapes de mappage. Sur les entités de données côté serveur sont mappées sur des objets de domaine qui sont à nouveau mappés sur des contrats de données de service. Sur les classes de proxy WCF côté client sont mappées sur les images de vue. P>
Certains développeurs de l'œuvre affirment que cette "copie" de données entre des classes apparemment identiques crée un problème de maintenance car tant de classes doivent être mises à jour lorsqu'un changement est introduit. Au lieu de cela, ils disent que vous devriez utiliser des classes partagées à travers les couches car nous contrôlons à la fois l'application client et le service WCF. Je m'inquiète trop de la quantité de travail impliquée et de voir une pénalité de performance potentielle, mais d'autre part à l'aide d'une classe partagée sur les couches / abstractions pourraient créer un couplage serré comme je le vois. Quelle est la meilleure approche? p>
3 Réponses :
Je ne vois rien sacré sur les couches. Avoir des versions spécifiques à une couche de chacune de chaque entité du modèle augmenterait beaucoup le nombre de classes. C'est inutile, à mon avis. Il viole le principe sec: pourquoi continuer à me répéter? P>
Qu'est-ce que la pureté de la couche vous achète? P>
Donc, je dirais que la meilleure approche consiste à transmettre ces entités modèles sans crainte. P>
Utilisation de DTO comme objets métier n'est pas la meilleure décision que vous puissiez faire. De mon expérience, je peux dire que, généralement lorsque vos objets sont identiques pour toutes les couches, il y a probablement un problème avec l'architecture quelque part. P>
Dans un scénario d'affaires réel Il est tout à fait improbable qu'une logique commerciale sur un serveur et une logique commerciale sur un client ait le même contexte et fonctionnent avec les mêmes objets. Et s'ils ont exactement la même structure avec la base de données ... HMMM ... sonne comme une application axée sur les données. P>
mais s'il S'il est non strong> une application axée sur les données, vous avez probablement une logique commerciale compliquée de votre côté serveur, et cette logique commerciale fonctionne généralement avec des objets qui n'ont aucun sens que son contexte. Il n'a pas de sens pour pousser ces objets tout au long de l'interface utilisateur. P>
Au lieu de cela, l'interface utilisateur enverra probablement Commandes em> au serveur afin de demander au système de faire quelque chose em>. Par exemple, il enverra une commande "DisableAccount (ID = 123)" au lieu de charger de la comptabilité, modifier son indicateur isenabled sur false et le repousser.
S'il y a est strong> une logique commerciale, il sera probablement déclenché par une commande em> du client qui n'a pas besoin de savoir comment em> Désactiver des comptes ou comment faire d'autres choses. Il sait juste et peut commande em> le système à faire em> quelque chose. P>
Donc, dans ce client de scénario (l'interface utilisateur) n'a pas besoin du même objet que le serveur a. Il peut avoir besoin de certaines données à afficher à l'utilisateur, mais elle sera définitivement dans un format qui a du sens pour la vue du client, pas pour la logique commerciale. Il contiendra probablement des données dénormalisées, combinées en quelque sorte. p>
Dites, l'utilisateur pour l'interface utilisateur n'est pas un DO mappé sur la table des utilisateurs. C'est une autre DTO, contenant des données et des statistiques des utilisateurs de différentes tables, traitées en quelque sorte. Le client n'a pas besoin de connaître la structure interne du stockage de données du serveur, il n'est donc pas nécessaire de l'exposer. Obtenez les données pertinentes et envoyez les commandes appropriées, c'est-à-dire. P>
Dire tout cela, je devrais souligner que ce n'est pas un choix binaire que vous faites. Pour des fonctionnalités simples, vous pouvez utiliser une approche simple, pour les fonctionnalités où la logique commerciale a du sens que vous pouvez faire les autres choses. p>
Vous n'êtes pas obligé de choisir un pour tout. Donc, vous n'avez pas à toujours em> créer 3 objets similaires simplement parce que c'est "le chemin" ou toujours em> les entités passent jusqu'à l'interface utilisateur.
Mais ce que vous les em> devront faire est de distinguer clairement des contextes et de définir où l'approche va être utilisée. p>
Dans 80%, vous finirez probablement de quelque chose de simple (comme WCF DataServices), et vous n'avez pas besoin de faire quoi que ce soit, et c'est bien comme dans beaucoup d'opérations que vous souhaitez simplement modifier les données. p>
mais dans d'autres 20% (qui est le "noyau" de votre application) où la véritable logique commerciale vit - vous pouvez également vouloir ce type de séparation non seulement pour les objets, mais aussi pour les responsabilités entre vos couches. P >
Tout ce que la cartographie crée un fardeau de maintenance. Que ce soit ou non, il est justifié dépend de ce que vous construisez et à quel point la logique commerciale est complexe. P>
Cependant, il est très important de réaliser que Une fois que vous commencez à partager des structures de données à travers les couches et les niveaux, l'architecture n'est plus découplé . Si vous faites cela, Il y a au moins ces alternatives: p>
Personnellement, je préfère la troisième option ces jours-ci. P>
Qu'en est-il des objets de valeur (comme distance code>,
point code>,
triangle code>,
argent code>,
mailaddress code> ) qui proviennent de la couche de domaine. Si leurs classes devraient également être dupliquées dans la couche de service afin de maintenir une superposition stricte?
@Lightman, je trouve que j'ai souvent besoin de le faire lorsque je crée une architecture en couches, car les objets de valeur doivent être immuables, ce qui tend à s'adapter mal avec des préoccupations frontalières telles que Guis d'événement ou (DE) la sérialisation des valeurs sur le fil.
Le partage de classes de données WCF peut ne pas être réalisable dans tous les scénarios. Par exemple, si vous utilisez des attributs de WCF pour modifier les noms des propriétés et types renvoyés par des services, les classes générées seront définies dans l'ensemble de services de WCF. Cela fait que tous les clients dépendent du service WCF pour activer le partage. Juste pour dire que cela peut mettre des contraintes de la vie réelle sur les amout de partage qui est effectivement accompli.