web-dev-qa-db-fra.com

Est-ce une mauvaise pratique d'utiliser un seul point de terminaison pour effectuer plusieurs tâches similaires?

Donc, le scénario est que l'on me demande de reconcevoir et de refactoriser une API REST en combinant plusieurs points de terminaison qui effectuent des tâches similaires.

Par exemple, j'ai maintenant 10 points de terminaison différents qui sont tous utilisés pour télécharger différentes ressources, par exemple upload_job, upload_script, upload_action, upload_sound ... L'idée principale est de réduire le nombre de points de terminaison en les combinant en un seul point de terminaison de téléchargement. L'endroit où le fichier sera téléchargé sera déterminé par le paramètre de type de fichier dans le corps de la requête POST.

Cela ressemble à une violation claire du principe de responsabilité unique, donc ce que je demande, c'est que si la combinaison de plusieurs points de terminaison de téléchargement en un seul point de terminaison de téléchargement est une mauvaise pratique?

De plus, si c'est une mauvaise pratique, quelles sont les alternatives qui peuvent réduire le nombre de points de terminaison?

9
lincredibleJC

À un certain moment, lors de la conception de fonctions, qu'il s'agisse de points de terminaison d'API, de méthodes de bibliothèque, etc., vous devez déterminer ce qu'est une "responsabilité unique". Il n'y a pas de meilleure pratique définitive sur ce genre de chose. Chaque choix a des compromis.

En quoi la fonctionnalité diffère-t-elle entre chaque point de terminaison? S'ils partagent beaucoup de fonctionnalités, il est logique qu'ils fassent partie de la même responsabilité.

Prenons par exemple l'arithmétique de base. Ajouter, soustraire, multiplier et diviser. Si mon seul objectif était de réduire le nombre de terminaux, je ferais:

doMath(string operator, string... operands)

Mais ce point final devrait lever quelques drapeaux. C'est très vague et non descriptif. Pas très idéal. Je ne serais même pas en mesure de commencer à utiliser cette fonction/point final sans documentation précise et mise à jour. Je pourrais aussi aller dans la direction opposée complète et éviter complètement les paramètres:

add5and5()
add10and5()
multiple4and8()
...

Il devrait être assez évident pourquoi cela n'a guère de sens. De toute évidence, nous avons besoin d'une sorte de terrain d'entente:

add(int op1, int op2)
subtract(int op1, int op2)
multiply(int op1, int op2)
divide(int op1, int op2)

Pas une mauvaise solution maintenant. Mais pourquoi 4 points finaux sont-ils meilleurs que 1? Eh bien, nous avons seulement besoin de faire de l'arithmétique de base. Par conséquent, nous pouvons être raisonnablement sûrs que notre API ne sera pas gonflée plus tard. Cependant, si nous avions une API qui faisait littéralement toutes sortes de calculs, il serait peut-être judicieux de regrouper l'arithmétique de base en un seul point de terminaison ou fonction!

De même, si vous prévoyez d'ajouter de plus en plus de points de terminaison de "téléchargement", votre API commencera à être un peu gonflée à moins que vous ne les combiniez. Bien sûr, la taille de votre API peut être à vous et à votre cas d'utilisation. Découvrez comment vos clients utiliseront l'API pour comprendre cela.

Posez-vous ces questions:

  • Ces points de terminaison partagent-ils beaucoup de fonctionnalités?
  • Est-il probable que davantage de fonctionnalités de "téléchargement" devront être ajoutées à l'API?
  • L'API fait-elle plus que des téléchargements?
  • Une refactorisation importante sera-t-elle nécessaire chez vos consommateurs si vous modifiez les signatures des terminaux à l'avenir?

Plus vous pouvez répondre "oui" à ces questions, plus vous obtenez d’avantages en réduisant le nombre de points de terminaison en déchargeant la fonctionnalité dans votre paramètre.

13
Clay07g

Je suis d'accord avec @ Hans-MartinMosner que la manière reposante est de POST ou PUT vers une ressource logique telle que /api/script ou /api/sound.

Le fait que les données (fichiers alias) sont différentes est ensuite modélisé par le nom de la ressource logique. Il est alors possible d'utiliser des paramètres spécifiques au type ou applicables à tous les types de ressources.

C'est alors une question de jugement de savoir si vous avez des points de terminaison avec beaucoup de paramètres facultatifs qui couvrent un grand nombre de variations de nombreux types de sous-ressources qui sont plus spécifiques mais qui partagent beaucoup de paramètres similaires.

Cette série Tweet a une vue intéressante pour savoir quand casser une méthode:

quand [une variable est] déclarée, nous frappons immédiatement un if, dont les deux branches la définissent, c'est un indice fort que le if est une méthode extractible.

Nous pouvons généraliser cela pour dire que si vous avez un paramètre facultatif et que vous avez immédiatement une instruction case ou si une instruction qui a deux chemins avec un retour anticipé est une indication forte que vous devriez envisager d'en faire deux points de terminaison. Pourtant, s'il s'agit uniquement de détails d'implémentation internes, vous ne voudriez pas le faire car cela ne serait pas clair pour les clients utilisant votre API et ils devraient lire la documentation des deux méthodes pour comprendre laquelle utiliser.

1
simbo1905