8
votes

Les classes de données doivent-elles être réutilisées à travers des couches et des applications ou mappées dans des classes spécifiques à la couche?

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.

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.

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?


1 commentaires

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.


3 Réponses :


0
votes

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?

Qu'est-ce que la pureté de la couche vous achète?

Donc, je dirais que la meilleure approche consiste à transmettre ces entités modèles sans crainte.


0 commentaires

9
votes

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.

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.

mais s'il est une application axée sur les données lorsque les clients accèdent à certaines données, modifiez-le et enregistrez-le, puis vous n'avez probablement pas besoin de cette superposition compliquée? Cela semble simple alors gardons cela simple. Si elle est une application axée sur les données, pourquoi non seulement créer un WCF DataServices contexte sur le haut de votre base de données et laissez-le faire tout le travail sale pour vous lorsque vous accédez à vos données sur la WCF sans même penser à DTO, mappages, etc.

S'il est non 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.

Au lieu de cela, l'interface utilisateur enverra probablement Commandes au serveur afin de demander au système de faire quelque chose . 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 une logique commerciale, il sera probablement déclenché par une commande du client qui n'a pas besoin de savoir comment Désactiver des comptes ou comment faire d'autres choses. Il sait juste et peut commande le système à faire quelque chose.

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.

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.

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.

Vous n'êtes pas obligé de choisir un pour tout. Donc, vous n'avez pas à toujours créer 3 objets similaires simplement parce que c'est "le chemin" ou toujours les entités passent jusqu'à l'interface utilisateur. Mais ce que vous les devront faire est de distinguer clairement des contextes et de définir où l'approche va être utilisée.

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.

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.


0 commentaires

7
votes

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.

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, vous construirez essentiellement une application monolithique . Ne vous méprenez pas: il n'y a rien de mal à construire une application monolithique si tout ce que vous faites est une application de crud glorifiée, mais il est essentiel de faire explicitement cette décision.

Il y a au moins ces alternatives:

  • Maintenir une superposition stricte. Le coût de la cartographie reste, mais le code est découplé.
  • construire une application monolithique. Effondrement tout ce que vous pouvez effondrer. Gardez-le aussi simple que possible. Ça va être étroitement couplé, mais cela peut devenir si simple que cela n'a pas d'importance.
  • Faites quelque chose de radicalement différent, comme la construction d'un application CQRS ou un mashup de SOA.

    Personnellement, je préfère la troisième option ces jours-ci.


2 commentaires

Qu'en est-il des objets de valeur (comme distance , point , triangle , argent , mailaddress ) 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.