web-dev-qa-db-fra.com

Réutilisation du DTO pour différents types de demande / réponse vs explicitation de ce qui est requis / de ce qui doit être retourné

J'ai commencé à me demander si je ne tombais pas dans un contre-modèle ici, alors veuillez conseiller sur les meilleures pratiques.

Je conçois une API REST avec un ensemble de différents points de terminaison et je voulais envelopper les paramètres de demande et de réponse dans Nice DTO.

Par exemple, quelques points finaux:

public async Task<JobStateResponse> GetJobState(JobStateRequest request);
public async Task<JobDownloadRespose> DownloadJob(JobDownloadRequest request);
public async Task<CreateJobResponse> CreateJob(CreateJobRequest request);

Le problème est que ces demandes et réponses sont des DTO relativement similaires, par exemple:

public class JobStateResponse{
    public int TaskId {get;set;}
    public string ExternalId {get;set;}
    public State State {get;set;}
}
public class JobDownloadResponse {
    public int TaskId {get;set;}
    public string ExternalId {get;set;}
    public string JobContent {get;set;}
}

J'ai pensé à créer une classe de base pour ceux-ci et à l'hériter, mais dans certains cas, certaines propriétés peuvent être redondantes ... Ce qui signifie que les méthodes n'indiquent pas clairement quels paramètres sont nécessaires pour qu'elles fonctionnent correctement.

Je veux dire, exposer un point de terminaison API avec un paramètre DTO qui a 7 propriétés mais n'a vraiment besoin que de 2 sons assez mauvais ...

D'un autre côté, maintenir des DTO séparés pour la plupart des points de terminaison semble être une surpuissance également, et aussi un enfer de maintenance.

Et aussi le la dernière chose que je veux, c'est une relation complexe de plusieurs classes base-base pour les requêtes car cela peut être un problème de maintenance encore pire.

Alors, quelle est la bonne approche pour la gestion des réponses aux requêtes <>?

EDIT: En ce qui concerne les indicateurs "basés sur l'opinion" - je recherche les meilleures pratiques pour gérer cela. Je sais que cela peut se faire de plusieurs manières, mais je veux éviter une mine/un anti-motif. De plus, je dois dire que je suis assez satisfait des réponses jusqu'à présent.

20
Bartosz

Des DTO séparés et simples vous rendront la vie infiniment plus facile. Cela nécessitera plus de code, mais ce sera un code simple et ennuyeux, facile à tester et qui permettra à vos interfaces de changer et d'évoluer indépendamment.

Créez un DTO pour chaque point de terminaison de demande et un DTO distinct pour chaque réponse. Sinon, vous finirez par être triste.

Si vous trouvez des éléments communs à plusieurs points de terminaison, extrayez-les dans leur propre objet et incluez-les dans les deux.

Et oui, utiliser l'héritage ici serait faux. Restez fidèle aux modèles de composition et tout ira bien.

22
Rob Conklin

L'utilisation d'un DTO séparé vous permet d'optimiser le transfert de données par le comportement des appels d'accès aux données, il vous permet également de restreindre l'accès aux propriétés que vous ne souhaitez pas exposer. Bien qu'il s'agisse davantage de code, vous définissez exactement ce qui est exposé et vous en avez le contrôle total.

5
Mark Redman

Vous voulez certainement séparer les DTO par point final en 2 groupes: ceux de demande et ceux de réponse.

Maintenant, en parlant d'héritage, vous pourriez avoir la classe de demande de base et la classe de réponse de base qui comprendrait des éléments généraux et non spécifiques (par exemple, le message d'encapsulation de demande et de réponse dans lequel vous branchez vos données), mais vous ne voulez pas mélanger l'héritage entre la demande et côté réponse.

Comme d'autres l'ont déjà souligné, c'est un peu plus de code au début, mais de cette façon, vous ne toucherez jamais le mur. Au contraire, les mélanger vous donnera très bientôt d'énormes refactorings où vous perdrez plus de temps et de nerfs que de commencer de manière claire et séparée.

2
dee zg