modèle pour partager des objets entre l'API et l'application

9

J'ai de sérieux doutes sur la conception de mon application Web.

Je voulais séparer la logique métier de l'interface, j'ai donc créé une API Web qui gère toutes les demandes à la base de données.

Il s'agit d'une API Web ASP.NET avec le framework Entity et une unité de travail et un modèle de référentiel générique. Jusqu'à présent, tout va bien.

PROBLÈME

Là où j'ai besoin d'aide, je n'arrive pas à trouver un moyen efficace de partager des objets entre l'API et l'application.

Je ne veux pas sérialiser directement l'objet entité, je pensais que ce serait une mauvaise pratique car si le modèle d'entité change, je pourrais finir par sérialiser de gros objets sans raison.

Comment est-il mis en œuvre maintenant

Parce que mon interface est une application Web ASP.NET en C # et que mon API est en C #, j'ai créé une bibliothèque commune avec la définition de toutes mes classes que je veux partager entre elles.

Je sais que cette solution ne fonctionnera pas lorsque je développerai une application Android, je devrai recréer mes cours en Java mais ce n'est pas mon plus gros problème.

Le problème est que j'ai l'impression de toujours convertir mes objets.

EXEMPLE

Voici un exemple de mon flux de travail:

Je commence avec un modèle avec tous les objets et les annotations de données pour mon formulaire, puis l'utilisateur POSTERA ce modèle à un contrôleur.

Dans le contrôleur, je dois convertir ce modèle en classe dans ma bibliothèque commune, puis envoyer cet objet à mon API.

Ensuite, un contrôleur de mon API intercepte l'appel et convertit cet objet en objet entité pour mettre à jour la base de données.

J'ai donc 3 cours

  1. Le modèle de la vue avec toutes les annotations de données pour la validation (Client)
  2. Les classes de bibliothèque communes pour partager les objets (DLL)
  3. Les classes d'entité (API)

J'ai le sentiment de faire quelque chose de vraiment mauvais. Y a-t-il quelque chose de plus élégant? Je voudrais m'assurer d'avoir une bonne solution à ce problème avant que le projet ne devienne trop gros.

Marc
la source
Si ma question n'est pas claire, n'hésitez pas à poser des questions.
Marc
Pour moi, ce n'est pas clair quelle architecture vous avez implémentée (c'est peut-être le libellé .net qui me laisse perplexe) - est-ce une architecture à 3 niveaux: client, serveur, db?
Andy
Oui, j'ai une application Web qui utilise une API Web. L'API est celle avec la logique métier avec la base de données.
Marc

Réponses:

12

Je sais qu'il peut sembler que vous convertissez constamment des objets dans les deux sens entre vos objets de base de données, vos objets de transfert de données, vos objets client avec une logique de validation et ainsi de suite, mais je dirais que non, vous ne faites rien de mal .

Chacun de ces objets peut représenter la même unité d'information, mais ils ont des responsabilités très différentes. L'objet de base de données est votre interface de communication avec la base de données et doit être conservé dans la couche de base de données car il peut ou non avoir des annotations de métadonnées de base de données différentes et / ou des détails inutiles sur l'implémentation de la base de données.

Votre objet de transfert de données est l'interface de communication avec vos consommateurs d'API. Ceux-ci doivent être aussi propres que possible pour faciliter leur consommation à partir de différentes langues / plates-formes. Cela peut imposer certaines restrictions sur leur apparence et leur comportement en fonction des consommateurs d'API que vous souhaitez prendre en charge.

Vos objets clients avec logique de validation ne font vraiment pas partie de votre projet API, ils font partie de votre projet consommateur. Ceux-ci ne peuvent pas être les mêmes que les objets de transfert de données dans ce cas puisque vous ajoutez des logiques spécifiques au client supplémentaires (dans ce cas des attributs de validation) sur lesquels le serveur ne sait rien (et ne devrait rien savoir!) Vous ne devriez pas comptez ces objets dans le cadre de votre API, car ils ne le sont vraiment pas. Ils sont très spécifiques aux applications grand public et certaines applications qui consomment votre API pourraient même ne pas avoir besoin de créer ces objets et pourraient tout aussi bien survivre sur vos objets de transfert de données. Par exemple, si vous n'aviez pas besoin de validation, vous n'auriez pas besoin d'une couche supplémentaire d'objets complètement identiques à vos objets de transfert de données.

Pour moi, il semble que chacun des trois types d'objet correspond très bien à une seule responsabilité qui est un codage propre et de bonnes pratiques. Malheureusement, un code propre et de bonnes pratiques signifient parfois que vous écrivez beaucoup de code supplémentaire et que vous sautez dans des cerceaux supplémentaires "juste parce que". Et pendant le codage, il peut être difficile d'apprécier la valeur que cela vous donne - mais dès que vous publiez votre application et commencez à la prendre en charge ou à ajouter de nouvelles fonctionnalités pour la prochaine version, vous commencerez probablement à apprécier que vous avez pris le temps de séparer correctement ces préoccupations en premier lieu. (Sans oublier que vous '

Je déteste également écrire du code de conversion entre différents types d'objet comme celui-ci, mais ma solution est généralement l'une des suivantes:

  • Utilisez une bibliothèque qui effectue la majeure partie de la conversion d'objets pour vous - par exemple, si vous utilisez C #, vous pouvez utiliser la fantastique bibliothèque AutoMapper ( http://automapper.org/ ). Je pense qu'il existe quelques autres bibliothèques comme celle-ci, mais AutoMapper est la plus puissante que j'ai vue jusqu'à présent.
  • Si vous ne trouvez pas de bibliothèque pour vous aider avec vos conversions d'objets, écrivez un ensemble de méthodes utilitaires pour les convertir entre elles. Cela peut être nul, mais cela en vaut la peine à long terme, écrivez la méthode de conversion la première fois que vous devez convertir quelque chose - n'attendez pas.
wasatz
la source
Merci pour vos explications mais j'ai toujours du mal à comprendre quelque chose. Je ne comprends pas pourquoi la couche de transfert de données n'a pas de validation? Et si j'oublie certaines validations pour ma prochaine application mobile? Au moins, cela ne validerait pas lorsque j'appelle l'API au lieu de faire une exception dans mon modèle de base de données. Je ne suis pas sûr de comprendre.
Marc
1
Je ne dis pas que vous ne devriez pas valider au niveau de l'API. Pour être honnête, c'est l'endroit le plus important pour valider. La validation dans votre application n'est qu'une "fonctionnalité intéressante" pour aider vos utilisateurs à ne pas commettre d'erreurs, la validation de vos objets de transfert de données permet de garder les données malveillantes et erronées à l'écart. Étant donné que ces différents cas d'utilisation cependant, vous pourriez avoir besoin d'utiliser différents cadres de validation (vous allez utiliser différents cadres de validation si votre application et votre api ne sont pas écrits dans la même langue) et vous pouvez valider des choses légèrement différentes à chaque niveau (Cont dans le commentaire suivant)
wasatz
1
Vous devez donc valider vos objets de transfert de données. Mais vous devez également vous assurer que la façon dont vous les validez n'introduit pas accidentellement de dépendances sur un autre framework . Et bien sûr, comme je l'ai dit plus tôt, vous ne pouvez vraiment pas être sûr que vos objets de transfert de données ont été validés du tout ou qu'ils ont été validés par le même framework - vous devez donc "valider deux fois".
wasatz
2
Principalement, vous devriez essayer de voir votre application et votre API comme deux applications complètement différentes et distinctes. Vous pouvez les développer en même temps, et ils peuvent être dans le même projet solution / éclipse de Visual Studio. Mais ce sont vraiment deux programmes complètement séparés. Lorsque vous travaillez dans votre application, essayez «d'oublier» que vous êtes celui qui a créé l'API et utilisez-le comme vous le feriez avec une API tierce normale. De cette façon, vous aurez une meilleure chance de voir comment les autres se sentiront lors de l'utilisation de votre API et de corriger les pires parties dès le début.
wasatz
1
Et la même chose est bien sûr vraie lorsque vous travaillez sur votre projet d'API, essayez d'imaginer que vous écrivez un service que de nombreux développeurs tiers vont utiliser. Essayez de ne pas trop penser à votre application actuelle, mais plutôt de garder votre esprit plus sur "quels services suis-je en train de fournir" et en supposant que tous ceux qui utilisent votre API (y compris vous-même) sont de mauvaises personnes qui essaient de tuer votre serveur et vous faire supprimer toute votre base de données.
wasatz