Contexte: Création d'une application client intelligente sur la plate-forme .NET où vous avez un modèle de base de données complexe avec un nombre élevé de colonnes impliquées. Le style d'application naturel est un CRUD basé sur des données typiques. Dans certains cas, il y a aussi un peu de logique côté serveur et des validations quelque peu complexes. Vous avez le contrôle total du client et du serveur, de sorte que le besoin d'interopérabilité est au minimum.
Cette question a beaucoup de détails, des excuses pour cela, mais c'est parce que je veux mettre le bon contexte pour les réponses.
A quelques hypothèses
- Comme il est pas rare dans le monde Microsoft, la plupart des applications précédentes ont été écrites avec des jeux de données, il est donc la technologie la plus connue pour les développeurs impliqués. Mais disons que les développeurs connaissent bien la philosophie OO.
- Vous devrez exécuter des validations sur le client et le serveur.
- Vous ne montrez pas la plupart des données sous forme de tableau.
- Ce n'est pas une application intranet, donc vous ne pouvez pas assumer trop de la bande passante
La plus grande question: datasets ou des objets?Questions d'architecture d'application distribuée basée sur les données .NET de type CRUD
Si vous optez pour des ensembles de données que vous avez quelques points positifs et négatifs
- En termes de points positifs: Vous obtenez un peu de soutien de Microsoft en termes d'obtention des données de la base de données, obtenir les données sur le réseau et renvoyant les données modifiées sur le réseau en plus petits morceaux - puisque vous ne pouvez spécifier que pour envoyer des modifications. Envoyer moins de données est une bonne chose car il y a potentiellement un peu de données en jeu.
- Les négatifs sont: En termes de validation, de logique métier et ainsi de suite, vous obtenez une forme procédurale de code et vous ne bénéficiez pas des avantages du code orienté objet - comportement et données ensemble, un style plus naturel de travail et penser à ce que vous faites, et peut-être des liens plus étroits avec la logique de validation. Vous pouvez également détourner l'attention de l'avantage de placer l'ensemble de données dans une grille, puisque ce n'est pas le cas d'utilisation courant.
Si vous optez pour des objets, il est le même exercice, mais il y a plus d'options concernées:
Positifs: Comportement et données ensemble. Logique de validation plus proche. Plus facile de voir et de comprendre les relations entre les objets. Code plus lisible. Plus facile à tester unitaire. Mais il y a assez peu de choix et vous travaillez besoin de faire aussi bien:
OU/Cartographie
- Obtenir les données du modèle relationnel aux objets. Les OR-mappers ne sont pas si complexes et seront capables de le gérer correctement. Mais cela ajoute au temps de développement.
cartographie du contrat
- Il est généralement une bonne pratique de données cartographiques à partir d'objets côté serveur pour contracter des objets, DTO probablement pour. Comme il s'agit d'une application qui convient bien à l'architecture de style CRUD, les DTO n'ajoutent pas vraiment de valeur à l'image, mais simplement au travail de mappage.
code partagé
- Vous pouvez aller pour un scénario de code partagé, où l'assemblage avec les données de domaine et la logique est disponible sur le client et côté serveur. C'est un couplage serré, mais ce n'est pas nécessairement mauvais quand vous avez une application client-serveur naturellement couplée. Que vous choisissiez d'ajouter une couche de contrat ou non, vous devez envoyer des structures d'objets volumineuses Étant donné que nous contrôlons le client et le serveur, le transport et l'encodage doivent être codés en binaire sur TCP. Ça va aider. Avec les ensembles de données, vous avez la possibilité de renvoyer uniquement les modifications. Envoyer la structure entière de l'objet dans les deux sens est un problème de performance probable. Une option permettant d'envoyer la structure entière de l'objet consiste à identifier les modifications impliquées (Créer, Mettre à jour, Supprimer) et à envoyer uniquement des informations à ce sujet. En théorie, il n'est pas trop difficile d'envoyer l'ID de la racine agrégée au serveur ainsi que les changements, demander au serveur de charger paresseux la racine de l'agrégat, effectuer les modifications apportées, puis sauvegarder à nouveau. Mais la grande complexité impliquée est d'identifier les changements effectués. Avez-vous déjà choisi cette approche? Pourquoi? Comment faites-vous exactement cela?
Présentation
La technologie de l'interface utilisateur exacte est pas vraiment important pour la question, WinForms, Silverlight ou WPF est possible. Supposons que nous utilisons WPF puisqu'il s'agit d'un nouveau client intelligent. Cela signifie que nous avons une liaison bidirectionnelle et que nous pouvons utiliser MVVM correctement.
Les objets liés à dans l'interface utilisateur devront implémenter INotifyPropertyChanged et déclencher un événement chaque fois qu'une propriété est mise à jour. Comment résolvez-vous cela? Si vous optez pour le scénario de code partagé, vous pouvez l'ajouter aux objets de domaine, mais cela impliquera d'ajouter du code et de la logique du côté du serveur qui n'est jamais censé être utilisé ici. La séparation est plus naturelle si vous optez pour des objets de contrat, mais ce n'est pas beaucoup de valeur ajoutée juste pour ajouter une couche de mapping.
Technologies
Il y a quelques technologies disponibles qui peuvent aider à résoudre certains des problèmes, mais qui compliquent souvent les autres. Les utilisez-vous ou construisez-vous des choses à partir de rien?
**
- CSLA est possible, mais il rend les tests unitaires plus difficiles et semble ajouter un couplage plus étroit à l'accès aux données. Cela aide avec un certain nombre de problèmes, mais personnellement je n'ai aucune compétence avec cette technologie, donc si c'est un bon ajustement est un peu difficile à dire.
- WCF RIA Services serait possible pour une solution Silverlight, mais il y a certainement des limites impliquées. La taille des données est une.
- WCF Data Services est une autre approche pour obtenir quelque chose rapidement, mais REST n'est pas beaucoup d'aide, et vous n'avez pas non plus le support de la validation que vous avez dans les services RIA.
Résumé
Si vous êtes arrivé jusqu'ici, j'espère que vous avez une idée de l'endroit où je veux en venir. J'ai essayé de le réduire pour éviter de parler de tout en même temps, mais le développement distribué est complexe, donc vous devez considérer beaucoup de parties.
Mise à jour
Merci pour les réponses les gars! J'essayais de poser la question assez ouverte pour ouvrir des réponses variables, mais assez spécifique pour répondre à quelques exigences non inhabituelles.
Il existe différents facteurs qui ont des avantages et des inconvénients différents et qui varient d'un système à l'autre. Chacun ajoute habituellement à la complexité de trouver une solution. Un des points de cette question était d'obtenir des réponses en particulier avec quelques exigences supplémentaires qui ne correspondent pas nécessairement directement à la réponse qui est souvent la bonne aujourd'hui - avec une interface utilisateur basée sur les tâches. Je ne suis pas un "gars CRUD", si vous voulez. Mais quelques systèmes, pour diverses raisons (le plus souvent l'héritage), ont un bon ajustement pour CRUD.
De nombreuses applications d'entreprise ont des exigences similaires qui tirent dans des directions différentes:
affaires liées
- Vue: données Affichage à l'utilisateur et mettre à jour les mêmes données (Reads et CUDS - Créer, Update, Delete)
- validation: règles métier
UI liées
- validation: règles de l'interface utilisateur
- mises à jour de l'interface utilisateur: code spécifique pour obtenir simplement l'interface utilisateur de mettre à jour sur les changements d'objet (INotifyPropertyChanged)
liés au réseau
- Taille des données: La quantité de données que vous envoyez sur le fil
DB liée
- Lazy chargement
SRP/réutilisation liée
- Cartographie: Causé par de multiples couches d'objets/séparation des préoccupations
Maintenance/modification
- Modifications: Ajout de nouvelles informations (colonnes/champs)
- Montant du Code
- Réutiliser et "raisons de changer"
limitions techniques
- Suivi des modifications
Mais ce ne sont que quelques très spécifiques. Vous devez toujours savoir quelles sont les «capacités» que vous trouvez les plus importantes et, par conséquent, quel degré d'évolutivité, de disponibilité, d'extensibilité, d'interopérabilité, d'utilisabilité, de maintenabilité et de testabilité vous avez besoin.
Si je voudrais essayer de généraliser quelque chose pour la plupart des situations, je dirais quelque chose comme:
client
- Utilisation MVVM pour la séparation et la testabilité
- Création de la machine virtuelle sur le dessus de DTO
- Mettre en oeuvre INotifyPropertyChanged dans la machine virtuelle.
- L'utilisation XamlPowerToys, PostSharp ou d'autres moyens d'aider à cela peut être utile
- séparé Lit et CUDS dans l'interface utilisateur
- Faire tâche CUDS base, et utiliser des commandes ou similaires à envoyer ces opérations sur le côté serveur
serveur
- sur mesure faire un DTO par écran
- OU utiliser l'approche multi-requête décrite par Ayende dans http://msdn.microsoft.com/en-us/magazine/ff796225.aspx
- Utilisez AutoMapping pour éviter le fastidieux, manuel et sans aucun rapport avec le problème que vous essayez de résoudre l'étape, cette cartographie est
- Que le modèle de domaine soit concerné par les opérations commerciales principalement, y compris les opérations liées CUD, et lit pas
- Évitez réutilisabilité qui ajoute au nombre de raisons de changer
- d'éviter les problèmes d'encapsulation
- (Et que permettre à l'architecture de style CQRS et peut-être mise à l'échelle séparée de lit et CUDS dans le temps)
- Essayez de trouver une approche de validation qui correspond bien à ce qui doit être fait (bonne lecture: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/02/15/validation-in-a-ddd-world.aspx)
est-ce neccessarily l'approche que je prendrais dans cette situation particulière? Eh bien, c'est ce que je voulais lancer une discussion sur :) Mais il semble que c'était plus difficile que je l'espérais (en dehors de vous deux).
Je ne suis certainement pas en désaccord avec les principes :) Mais surtout la partie sur le fait d'avoir un peu de données est censée faire partie de ce problème. Oui, les ensembles de données incluent l'envoi de plus de données qu'un modèle d'objet, et personnellement je n'aime pas aller le jeu de données, mais il a une fonction pratique de seulement envoyer les changements après un changement (= beaucoup moins de données). Non pas que ce soit la fonction de tueur, mais quelque chose de similaire serait bien pour un modèle d'objet où aller de la manière des commandes n'est pas vraiment une option –
Vous pourriez essayer les entités de suivi automatique dans Entity framework http://blogs.msdn.com/b /efdesign/archive/2009/03/24/self-tracking-entities-in-the-entity-framework.aspx, il s'agit d'un terrain d'entente entre DTO et DataSets. –