Pourquoi un petit vocabulaire fixe est-il considéré comme un avantage pour les services RESTful?

13

Ainsi, un service RESTful a un ensemble fixe de verbes dans son vocabulaire. Un service Web RESTful les prend des méthodes HTTP. Il y a certains avantages supposés à définir un vocabulaire fixe, mais je ne comprends pas vraiment le point. Peut-être que quelqu'un peut l'expliquer.

Pourquoi un vocabulaire fixe tel que décrit par REST est-il meilleur que de définir dynamiquement un vocabulaire pour chaque état? Par exemple, la programmation orientée objet est un paradigme populaire. RPC est décrit pour définir des interfaces fixes, mais je ne sais pas pourquoi les gens supposent que RPC est limité par ces contraintes. Nous pourrions spécifier dynamiquement l'interface tout comme un service RESTful décrit dynamiquement sa structure de contenu.

REST est censé être avantageux en ce sens qu'il peut se développer sans étendre le vocabulaire. Les services RESTful se développent dynamiquement en ajoutant plus de ressources. Qu'y a-t-il de si mal à étendre un service en spécifiant dynamiquement un vocabulaire par objet? Pourquoi ne pas simplement utiliser les méthodes définies sur nos objets comme vocabulaire et demander à nos services de décrire au client quelles sont ces méthodes et si elles ont ou non des effets secondaires?

Essentiellement, j'ai l'impression que la description d'une structure de ressources côté serveur équivaut à la définition d'un vocabulaire, mais nous sommes alors obligés d'utiliser le vocabulaire limité dans lequel interagir avec ces ressources.

Un vocabulaire fixe dissocie-t-il vraiment les préoccupations du client des préoccupations du serveur? Je dois sûrement m'inquiéter de la configuration du serveur, c'est normalement l'emplacement des ressources dans les services RESTful. Se plaindre de l'utilisation d'un vocabulaire dynamique semble injuste car il nous faut de toute façon raisonner de manière dynamique pour comprendre cette configuration. Un service RESTful décrit les transitions que vous pouvez effectuer en identifiant la structure d'objet via hypermédia.

Je ne comprends tout simplement pas ce qui rend un vocabulaire fixe meilleur que tout vocabulaire dynamique auto-descriptif, qui pourrait facilement très bien fonctionner dans un service de type RPC. Est-ce juste un mauvais raisonnement pour limiter le vocabulaire du protocole HTTP?

Réflexion

Juste pour clarifier mes pensées un peu mieux que moi. Supposons que vous conceviez une API à usage général, peut-être même pas orientée Web. Seriez-vous heureux si quelqu'un dit que vous ne pouvez utiliser ces noms de méthode que sur vos objets? REST n'est pas limité à HTTP, mais considérez la situation où chaque API que vous écrivez, orientée Web ou autrement constituée simplement d'objets contenant les méthodes GET POST PUT et DELETE. Donc, la méthode object.foo que vous vouliez définir n'est pas possible. Vous devez définir un nouvel objet appelé foo et appeler sa méthode GET. C'est essentiellement ainsi que fonctionne REST, et cela me met un peu mal à l'aise d'y penser. Vous n'avez pas une meilleure compréhension générique de ce que fait foo, vous avez juste été obligé de créer un nouvel objet pour ce qui est essentiellement une méthode sur un objet parent. De plus votre API n'est pas moins complexe, vous venez de masquer la complexité de l'interface en créant plus d'objets. Les services Web RESTful nous obligent à adopter une interface qui peut être suffisante ou non dans le contexte de l'API que nous exposons. Il y a peut-être une bonne raison de le faire avec des API Web, mais une bonne raison de ne pas adopter des interfaces standard pour chaque objet dans chaque API à usage général. Un exemple pratique serait apprécié.

Matt Esch
la source
Pour aider les utilisateurs à analyser rapidement vos questions et réponses, vous pouvez envisager d'ajouter vos «mises à jour» en tant que réponses distinctes (en particulier la section «une autre mise à jour»). Ceci est encouragé: blog.stackoverflow.com/2011/07/…
Johann
@Johann merci, les autres mises à jour existent maintenant comme réponse acceptée pour cette question.
Matt Esch

Réponses:

9

La terminologie «verbe» et «nom» est quelque peu malheureuse ici. Comme vous l'avez déjà mentionné, vous pouvez facilement créer un objet pour la fonction. Tous les langages orientés objet, à l'exception de Java, ont cette transformation intégrée et en Java, vous finissez par le faire tout le temps de toute façon, vous vous retrouvant avec beaucoup d'objets avec une seule méthode et souvent un appelé "invoquer", "exécuter", "appliquer" ou quelque chose comme ça (c'est donc les langages de programmation où la distinction "verbe" / "nom" n'a pas de sens).

Les "verbes" de REST sont plus comme classer vos méthodes en getters, setters (deleters; peuvent être considérés comme des setters) et autres. Et essayer de tout faire avec des getters et des setters. La raison en est:

  1. Sémantique plus facile face à un échec de communication, car les getters et les setters sont idempotents. L'obtention de la ressource deux fois n'a aucun effet supplémentaire, pas plus que la définition de la valeur qu'elle a déjà.
  2. Définir une sémantique qui peut être utilisée en mettant éventuellement en cache un proxy qui ne comprend pas l'interface spécifique. Les getters sont mis en cache et les setters sont connus pour invalider le cache.

HTTP a été conçu dès le départ avec à la fois les caches et la tolérance aux pannes, donc ces deux points conduisent à quatre méthodes de base:

  • GETest un getter. Il est supposé ne pas modifier l'état du serveur et renvoyer la même valeur à chaque fois avec possibilité de spécifier la politique d'expiration et de revalidation.
  • PUTet DELETEsont le setter et le deleter (= setter avec nil). Ils ne sont normalement pas utilisés dans le contexte d'un site Web normal, mais ont un sens pour REST.
  • POST est un évier de cuisine générique "invoke" pour lequel les caches ne peuvent rien supposer.

REST est un modèle de conception décrivant comment utiliser HTTP brut ou des protocoles réseau similaires pour implémenter une interface qui permet de gérer facilement les échecs par une nouvelle tentative et qui fonctionne bien avec les procurations de mise en cache.

Il ne correspond pas facilement à l'API de programmation orientée objet classique. Je pense que c'est en fait une bonne chose. Les défis de l'interfaçage sur le réseau, qui sont intrinsèquement peu fiables et où les allers-retours sont beaucoup plus lents que le transfert d'une quantité même modérée de données nécessitent une approche de conception différente de celle de l'API en cours de traitement, donc quand cela semble différent, les gens n'essaient pas d'appliquer une expérience invalide de l'autre domaine (c'est le fléau de SOAP, XML-RPC et autres; cela ressemble à des appels de procédure, mais ne fonctionne pas comme ça et finit par être pénible à travailler).

Jan Hudec
la source
2

L'idée essentielle est que la complexité est exprimée à travers la représentation des ressources, et donc des verbes supplémentaires ne sont pas nécessaires. Comme certains l'ont dit - "Dans REST, les noms sont bons, les verbes sont mauvais."

Si vous regardez les quatre verbes REST, ils peuvent être mappés aux opérations CRUD de base, vous permettant essentiellement de faire ce que vous voulez avec vos ressources. C'est -

POST - Créer la ressource

GET - Lire la ressource

PUT - Mettre à jour la ressource

DELETE - Supprimer la ressource

De quoi d'autres avez-vous besoin?

Craig Schwarze
la source
Je peux faciliter un verbe dans un service RESTful en créant une ressource pour le faire. Comme vous le dites, je n'ai pas besoin de verbes supplémentaires mais simplement de plus de ressources. Je ne vois tout simplement pas pourquoi il vaut mieux prétendre qu'un verbe abstrait est un substantif alors que ce que je veux faire est vraiment un verbe. Il semble que les verbes soient contraints de force sans raison, et j'évite le problème en créant des noms qui effectuent les actions requises lorsqu'ils sont accessibles avec un petit ensemble de verbes. Pourquoi serait-il préférable de faire cela? Il doit y avoir une bonne raison à cela, quelque chose que je peux quantifier comme exemple pratique.
Matt Esch
4
Obtenez une liste de toutes les ressources, obtenez une liste de toutes les ressources avec des contraintes données, mettez à jour ou supprimez un tas de ressources en même temps, créez deux types de ressources ensemble ensemble atomiquement (pour que les deux créations échouent ou réussissent), supprimez toutes les ressources satisfaire une condition donnée ... La liste des choses que l'on peut vouloir faire est assez longue. On peut les intégrer dans une API REST, mais ce n'est pas toujours naturel. Cela n'aide pas non plus que GET n'autorise pas un corps, de sorte que des conditions de filtrage complexes deviennent difficiles.
Andrea
PATCHer des ressources est aussi plutôt cool.
Wyatt Barnett
2

Considérons un langage où toutes les constructions (telles que les fonctions) sont des objets. Ensuite, les verbes RESTful appellent simplement des conventions et des instructions d'affectation. Pour JavaScript, vous pouvez définir une syntaxe de verbe fixe comme INVOKE pour appeler une fonction, DELETE (identique à delete dans js) pour supprimer un objet sur un autre objet, SET pour affecter une valeur et RETURN pour renvoyer une valeur. Nous pourrions utiliser les verbes HTTP pour signifier la fonction POST - invocation équivalente, PUT - assigner une valeur, GET - retourner une valeur, - DELETE - supprimer un objet. J'étais pris dans l'idée que les méthodes HTTP décrivaient en fait des méthodes d'objet, des interfaces d'objet réelles, que je n'arrivais pas à voir qu'elles pouvaient en fait décrire des concepts de niveau beaucoup plus bas, tels que les constructions de langage de base qui sont clairement fixes et finies en tout des langues sensées.

Et bien sûr, il est utile pour le routage / proxy d'avoir un vocabulaire fixe sur lequel réfléchir.

Matt Esch
la source
1
  • Parce qu'un programmeur professionnel prévoit des centaines, sinon des milliers de noms de méthode autrement. Ce qui semble inutile à un petit plus petit peut être très important à mesure que l'application devient plus grande.

  • Parce qu'il n'y a pas besoin de normes sur les noms de méthode lorsqu'ils sont déjà définis.

  • Parce que l'objectif principal du code est d'être lisible sans ces traductions supplémentaires.

  • Parce qu'il encourage et aide à identifier «quand» une autre classe devrait être organisée.

  • Lorsque vous reprenez le code, il est raisonnable et réellement possible de comprendre quoi et comment il le fait beaucoup plus rapidement.

  • Il fournit un vocabulaire commun et donc un niveau d'abstraction afin que vous puissiez vous concentrer sur d'autres détails et voir les modèles.

  • Cela facilite la recherche de bogues car le code et les approches communs peuvent être facilement vérifiés.

  • Lorsque vous travaillez avec plusieurs `` couches '' comme celle du développement Web, savoir quelles URL correspondent à quels noms d'action est très pratique pour le débogage.

Dans l'ensemble, vous n'en avez pas «toujours» besoin, mais comme la plupart des normes, il est très logique de chercher à l'utiliser!

Michael Durrant
la source
Abordé dans l'ordre 1) Un programmeur prévoit donc des centaines sinon des milliers de ressources autrement? Nous anticipons déjà les méthodes dans les bibliothèques que nous utilisons. 2) Nous avons donc besoin de normes pour les noms de méthode mais pas pour les noms de ressource? Je ne parviens pas à suivre cette logique. 3) Je ne sais pas ce que vous entendez par traductions. Si vous me dites qu'une ressource existe, je dois la comprendre. Si je vous dis qu'une méthode existe, vous devez la comprendre. La seule chose qui m'importe vraiment, c'est laquelle de mes actions aura des effets secondaires 4) Pourriez-vous développer
Matt Esch
5) pourriez-vous à nouveau vous développer. Je suis un programmeur. J'ai l'habitude de travailler avec des structures d'objets bien définies. Pourquoi n'utiliserions-nous pas ce même mécanisme pour définir toutes nos API si c'est vraiment mieux? 6) Aucun niveau d'abstraction ne vaut la peine d'être pris en compte sans justification 7) Encore une fois, pourriez-vous développer. Si nous bénéficions de cette manière, nous devrions certainement coder toutes nos API comme ceci. 8) Je m'attendrais à ce que n'importe quel objet expose directement ses méthodes. / object / method ne peut pas être confondu. Nous définissons les normes en choisissant de les adopter. Je manque de motivation pour le moment.
Matt Esch
Matt vous semblez un peu argumentatif mais je dirai que pour 2) je n'ai pas dit que la ressource n'aurait pas besoin de normes 3) vous n'aurez pas besoin de comprendre une méthode telle que 'mettre à jour' ou 'nouvelle' ou créer 'parce que vous savez exactement ce que ceux-ci font selon les normes. Mais qu'en est-il de «MsgToPrimary», qu'est-ce que cela fait? Créer un msg? Mettre à jour un statut? Envoyer un e-mail? 7) Oui, la plupart des API pourraient en bénéficier et beaucoup le font. J'essaierais de me concentrer sur la notion que les normes et conventions standard sont utiles et je peux voir que vos mises à jour le montrent.
Michael Durrant
J'essaie simplement de comprendre les avantages. Les contre-arguments solides doivent être traités pour clarifier le problème. Je comprends toujours qu'un ensemble fixe de verbes est en quelque sorte une description de langue, mais je ne suis pas vraiment d'accord pour dire qu'il est plus facile à comprendre. Vous ne pouvez pas enlever un ensemble expressif de verbes et dire bon, nous comprenons maintenant tous les verbes, quand nous ne comprenons pas toutes les ressources. Les ressources remplacent les verbes. Nous remplaçons le verbe arbitraire foo par une ressource appelée foo. Notre compréhension de foo n'est pas plus claire qu'elle ne l'était quand foo était un verbe.
Matt Esch
1

L'alternative est quelque chose d'horrible: WSDL (aka Web Service Definition Language), qui est un moyen (maladroit) de décrire par programmation (quelque peu) arbitraire APIS.

REST limite sévèrement les verbes, poussant presque toutes les variations spécifiques à l'application dans la charge utile du document. L'avantage de cela est que de nombreuses implémentations client peuvent communiquer avec de nombreux services hétérogènes. Les clients et les serveurs peuvent être complètement inconnus les uns des autres, certains n'étant pas encore écrits.

Il y a un podcast dans lequel Stefan Tilkov explique bien REST .

cbare
la source
1

Oui, une api de repos a un ensemble fixe de verbes, mais il ne doit pas être limité à (ou inclure GET, POST, PUT, DELETE). Je considérerais GET, POST, PUT, DELETE comme une implémentation par défaut de REST qui fonctionne pour 80% de tous les systèmes.

D'autres systèmes qui implémentent plus que des opérations crud peuvent (et font) implémenter leurs propres verbes pour leurs API REST. Des verbes comme publier, consommer, noter, commenter, rechercher, parcourir peuvent être ajoutés et implémentés dans un système REST. Alors que certains pourraient dire qu'un vocabulaire plus large pourrait le rendre plus compliqué, ma réponse est que cela dépend. Si votre utilisateur cible est un responsable technique qui comprend ce qu'est un POST, alors oui, cela pourrait être plus compliqué; cependant, si les utilisateurs cibles de votre API sont de vraies personnes (c'est-à-dire des personnes qui ne codent pas et ne savent pas ce qu'est un POST), les vrais verbes sont beaucoup plus faciles à utiliser. En fait, avoir un ensemble approprié de verbes pour votre API aide à garder les URL courtes (ce qui est important si vous voulez que les utilisateurs les tapent dans un navigateur. Si vous utilisez un vocabulaire personnalisé, vous ' Je veux m'assurer que votre API et ses verbes sont bien documentés. Lorsque vous utilisez une API REST personnalisée, vous souhaitez vous assurer que vos «actions en lecture seule» en tant que HTTP GET et «écrire des actions» avec POST.

Le réseau social pour adolescents, Piczo.com, (qu'il repose en paix) comportait une API REST étendue (y compris les verbes mentionnés ci-dessus) qui a été mise en œuvre dans 7 langues différentes!

Andrew
la source
0

C'est simple c'est bien.

Il y a des cas où vous avez besoin de verbes et de complexité supplémentaires, mais la plupart des problèmes peuvent être réduits à de simples actions CRUD sur les ressources, et c'est ce que REST essaie de promouvoir. Lorsque vous pensez à la plupart des applications Web, au final, elles lisent et conservent les enregistrements dans un magasin de données, qui utilisent les mêmes actions très simples.

object.foo () est tout bon, mais que fait-il? Que revient-il? Modifie-t-il l'état de l'objet ou l'une de ses dépendances? Pouvez-vous l'appeler deux fois et obtenir le même résultat ou cela vous donnera-t-il deux valeurs différentes? Si vous avez également object.bar (), doivent-ils être appelés dans un ordre spécifique?

Il faut beaucoup de connaissances pour utiliser une API riche, et elles ont généralement leurs propres conventions (c'est-à-dire que setFoo va muter l'objet, getBar est probablement idempotent, dispose () ou destroy () signifie qu'il n'y a pas d'autres appels sur le même objet sera possible, etc ...)

ptyx
la source