Warum wird ein kleines festes Vokabular als Vorteil für RESTful-Services angesehen?


13

Ein RESTful-Service hat also einen festen Satz von Verben im Wortschatz. Ein RESTful-Webdienst entnimmt diese den HTTP-Methoden. Es gibt einige vermeintliche Vorteile, ein festes Vokabular zu definieren, aber ich verstehe den Punkt nicht wirklich. Vielleicht kann es jemand erklären.

Warum ist ein festes Vokabular nach REST besser als die dynamische Definition eines Vokabulars für jeden Staat? Objektorientierte Programmierung ist beispielsweise ein beliebtes Paradigma. Es wird beschrieben, dass RPC feste Schnittstellen definiert, aber ich weiß nicht, warum Leute annehmen, dass RPC durch diese Einschränkungen eingeschränkt ist. Wir könnten die Schnittstelle dynamisch spezifizieren, so wie ein RESTful-Service dynamisch seine Inhaltsstruktur beschreibt.

REST soll dahingehend vorteilhaft sein, dass es wachsen kann, ohne den Wortschatz zu erweitern. RESTful-Services wachsen dynamisch, indem Sie mehr Ressourcen hinzufügen. Was ist so falsch daran, einen Service durch dynamische Angabe eines objektspezifischen Vokabulars zu erweitern? Warum verwenden wir nicht einfach die Methoden, die für unsere Objekte definiert sind, als Vokabular und lassen unsere Dienste dem Kunden beschreiben, was diese Methoden sind und ob sie Nebenwirkungen haben oder nicht?

Grundsätzlich habe ich das Gefühl, dass die Beschreibung einer serverseitigen Ressourcenstruktur der Definition eines Vokabulars entspricht, wir dann aber gezwungen sind, das begrenzte Vokabular zu verwenden, um mit diesen Ressourcen zu interagieren.

Entkoppelt ein festes Vokabular wirklich die Anliegen des Clients von den Anliegen des Servers? Ich muss mich sicherlich um eine Konfiguration des Servers kümmern, dies ist normalerweise die Ressourcenposition in RESTful-Diensten. Sich über die Verwendung eines dynamischen Vokabulars zu beschweren, erscheint unfair, da wir dynamisch überlegen müssen, wie wir diese Konfiguration irgendwie verstehen können. Ein RESTful-Service beschreibt die Übergänge, die Sie durchführen können, indem Sie die Objektstruktur über Hypermedia identifizieren.

Ich verstehe einfach nicht, was ein festes Vokabular besser macht als ein selbstbeschreibendes dynamisches Vokabular, das in einem RPC-ähnlichen Dienst sehr gut funktionieren könnte. Ist dies nur eine schlechte Begründung für das einschränkende Vokabular des HTTP-Protokolls?

Betrachtung

Nur um meine Gedanken ein wenig klarer zu machen als ich es getan habe. Angenommen, Sie entwerfen eine Allzweck-API, möglicherweise nicht einmal mit Blick auf das Web. Würden Sie sich freuen, wenn jemand sagt, dass Sie diese Methodennamen nur für Ihre Objekte verwenden können? REST ist nicht auf HTTP beschränkt, sondern berücksichtigt die Situation, in der jede von Ihnen geschriebene, dem Web zugewandte oder anderweitig einfach aus Objekten bestehende API die Methoden GET POST PUT und DELETE enthält. Daher ist diese object.foo-Methode, die Sie definieren wollten, nicht möglich. Sie müssen ein neues Objekt namens foo definieren und dessen GET-Methode aufrufen. Genau so funktioniert REST, und es ist mir ein wenig unangenehm, darüber nachzudenken. Sie haben kein besseres allgemeines Verständnis für die Funktionsweise von foo. Sie mussten lediglich ein neues Objekt für eine Methode erstellen, die im Wesentlichen für ein übergeordnetes Objekt gilt. Darüber hinaus ist Ihre API nicht weniger komplex, Sie haben gerade die Komplexität der Benutzeroberfläche durch das Erstellen weiterer Objekte verborgen. RESTful-Webservices zwingen uns, eine Schnittstelle zu verwenden, die im Kontext der von uns bereitgestellten API ausreicht oder nicht. Vielleicht gibt es einen guten Grund, dies mit Web-konformen APIs zu tun, aber einen guten Grund, nicht für jedes Objekt in jeder Allzweck-API Standardschnittstellen zu verwenden. Ein praktisches Beispiel wäre wünschenswert.


Um Benutzern das schnelle Analysieren Ihrer Fragen und Antworten zu erleichtern, können Sie Ihre "Updates" als separate Antworten hinzufügen (insbesondere den Abschnitt "Ein weiteres Update"). Dies wird empfohlen
Johann

@Johann danke, die weiteren Updates existieren nun als akzeptierte Antwort auf diese Frage.
Matt Esch

Antworten:


9

Die Terminologie "Verb" und "Nomen" ist hier etwas unglücklich. Wie Sie bereits erwähnt haben, können Sie problemlos Objekte für Funktionen erstellen. Alle objektorientierten Sprachen mit Ausnahme von Java haben diese Transformation integriert, und in Java wird sie ohnehin die ganze Zeit ausgeführt, und es werden viele Objekte mit einer einzigen Methode und häufig mit "Aufrufen", "Ausführen", "Anwenden" oder ähnlichem bezeichnet (Es sind also die Programmiersprachen, in denen die Unterscheidung "Verb" / "Nomen" eigentlich keinen Sinn ergibt).

Die "Verben" von REST ähneln eher der Klassifizierung Ihrer Methoden in Getter, Setter (Deleter; können als Setterarten betrachtet werden) und andere. Und versuchen, alles mit Gettern und Setzern zu machen. Der Grund dafür ist:

  1. Einfachere Semantik angesichts eines Kommunikationsfehlers, da sowohl Getter als auch Setter idempotent sind. Das zweimalige Abrufen der Ressource hat keine zusätzlichen Auswirkungen und setzt sie auch nicht auf den Wert, den sie bereits hat.
  2. Definieren einiger Semantiken, die verwendet werden können, indem möglicherweise ein Proxy zwischengespeichert wird, der die spezifische Schnittstelle nicht versteht. Getter werden zwischengespeichert, und es ist bekannt, dass Setter den Cache ungültig machen.

HTTP wurde von Anfang an mit Blick auf Caches und Fehlertoleranz entwickelt. Diese beiden Punkte führen zu vier grundlegenden Methoden:

  • GETist ein Getter. Es wird davon ausgegangen, dass der Serverstatus nicht geändert wird und jedes Mal derselbe Wert zurückgegeben wird, mit der Möglichkeit, Ablauf- und Verlängerungsrichtlinien festzulegen.
  • PUTund DELETEsind der Setter und Deleter (= Setter mit Null). Sie werden normalerweise nicht im Kontext eines normalen Webs verwendet, sind jedoch für REST sinnvoll.
  • POST ist eine generische "aufrufende" Küchenspüle, für die Caches nichts annehmen können.

REST ist ein Entwurfsmuster, das beschreibt, wie Sie HTTP-Rohdaten oder ähnliche Netzwerkprotokolle verwenden, um eine Schnittstelle zu implementieren, die die einfache Behandlung von Fehlern durch einfaches Wiederholen ermöglicht und gut mit Caching-Proxys zusammenarbeitet.

Es entspricht nicht leicht einer normalen objektorientierten Programmierschnittstelle. Ich finde es eigentlich eine gute Sache. Die Herausforderungen einer Schnittstelle über ein Netzwerk, die von Natur aus unzuverlässig ist und bei denen Roundtrips viel langsamer sind als die Übertragung selbst mäßiger Datenmengen, erfordern einen anderen Entwurfsansatz als die In-Process-API Ungültige Erfahrungen aus der anderen Domäne (das ist der Fluch von SOAP, XML-RPC und ähnlichem; es sieht aus wie Prozeduraufrufe, funktioniert aber nicht so und ist am Ende schmerzhaft).


2

Die Grundidee ist, dass die Komplexität durch die Ressourcendarstellung ausgedrückt wird und daher keine zusätzlichen Verben erforderlich sind. Einige haben es so formuliert: "In REST sind Substantive gut, Verben sind schlecht."

Wenn Sie sich die vier REST-Verben ansehen, können sie den grundlegenden CRUD-Operationen zugeordnet werden, sodass Sie im Wesentlichen mit Ihren Ressourcen tun können, was Sie wollen. Das ist -

POST - Erstellt die Ressource

GET - Lesen Sie die Ressource

PUT - Aktualisieren Sie die Ressource

LÖSCHEN - Löschen Sie die Ressource

Was brauchst du noch?


Ich kann ein Verb in einem RESTful-Service unterstützen, indem ich eine Ressource dafür erstelle. Wie Sie sagen, ich brauche keine zusätzlichen Verben, nur mehr Ressourcen. Ich verstehe einfach nicht, warum es besser ist, so zu tun, als ob ein abstraktes Verb ein Substantiv ist, wenn das, was ich tun möchte, wirklich ein Verb ist. Es scheint, als wären Verben ohne Grund zwangsweise eingeschränkt, und ich vermeide das Problem, indem ich Substantive erstelle, die die erforderlichen Aktionen ausführen, wenn auf sie mit einer kleinen Gruppe von Verben zugegriffen wird. Warum sollte es besser sein, das zu tun? Es muss einen guten Grund dafür geben, was ich als praktisches Beispiel quantifizieren kann.
Matt Esch

4
Eine Liste aller Ressourcen abrufen, eine Liste aller Ressourcen mit bestimmten Einschränkungen abrufen, eine Reihe von Ressourcen gleichzeitig aktualisieren oder löschen, zwei verschiedene Ressourcentypen atomar zusammen erstellen (sodass beide Kreationen fehlschlagen oder erfolgreich sind), alle Ressourcen löschen Befriedigung einer gegebenen Bedingung ... Die Liste der Dinge, die man tun möchte, ist ziemlich lang. Man kann sie in eine REST-API einbauen, aber es ist nicht immer natürlich. Es hilft auch nicht, dass GET einen Körper nicht zulässt, so dass komplexe Filterbedingungen akward werden.
Andrea

PATCH-Ressourcen sind auch ziemlich cool.
Wyatt Barnett

2

Stellen Sie sich eine Sprache vor, in der alle Konstrukte (z. B. Funktionen) Objekte sind. Dann rufen die RESTful-Verben einfach Konventionen und Zuweisungsanweisungen auf. Für JavaScript können Sie eine feste Verbsyntax wie INVOKE zum Aufrufen einer Funktion definieren, DELETE (das gleiche wie delete in js) zum Löschen eines Objekts in einem anderen Objekt, SET zum Zuweisen eines Werts und RETURN zum Zurückgeben eines Werts. Wir könnten die HTTP-Verben verwenden, um die entsprechende POST-Aufruffunktion zu bezeichnen, PUT - Wert zuweisen, GET - einen Wert zurückgeben, - DELETE - ein Objekt löschen. Ich war von der Idee fasziniert, dass die HTTP-Methoden tatsächlich Objektmethoden und tatsächliche Objektschnittstellen beschreiben, und ich konnte nicht erkennen, dass sie tatsächlich Konzepte auf viel niedrigerer Ebene beschreiben können, wie beispielsweise die grundlegenden Sprachkonstrukte, die eindeutig festgelegt und insgesamt endlich sind gesunde Sprachen.

Und natürlich ist es für Routing / Proxy hilfreich, ein festes Vokabular zu haben, über das nachgedacht werden kann.


1
  • Weil ein professioneller Programmierer Hunderte, wenn nicht Tausende von Methodennamen vorwegnimmt. Was im Kleinen sinnlos erscheint, kann mit zunehmender Anwendungsgröße eine große Rolle spielen.

  • Weil Standards für Methodennamen nicht erforderlich sind, wenn sie bereits definiert sind.

  • Denn das Hauptziel von Code ist es, ohne solche zusätzlichen Übersetzungen lesbar zu sein.

  • Weil es die Identifizierung des Zeitpunkts für den Ausbruch einer anderen Klasse fördert und erleichtert.

  • Wenn Sie Code übernehmen, ist es vernünftig und tatsächlich möglich zu verstehen, was und wie es viel schneller geht.

  • Es bietet ein gemeinsames Vokabular und somit eine Abstraktionsebene, sodass Sie sich auf andere Details konzentrieren und Muster sehen können.

  • Dies erleichtert das Auffinden von Fehlern, da gängiger Code und Vorgehensweisen leicht überprüft werden können.

  • Wenn Sie mit mehreren "Ebenen" arbeiten, wie dies bei der Webentwicklung der Fall ist, ist es für das Debuggen sehr praktisch, zu wissen, welche URLs mit welchen Aktionsnamen übereinstimmen.

Insgesamt braucht man es nicht immer, aber wie die meisten Standards ist es sehr sinnvoll zu versuchen, es zu verwenden!


Adressiert in der Reihenfolge 1) Ein Programmierer rechnet also mit Hunderten, wenn nicht mit Tausenden von Ressourcen? In den Bibliotheken, die wir verwenden, nehmen wir bereits Methoden vorweg. 2) Wir brauchen also Standards für Methodennamen, aber nicht für Ressourcennamen? Ich folge dieser Logik nicht. 3) Nicht sicher, was Sie mit Übersetzungen meinen. Wenn Sie mir mitteilen, dass eine Ressource vorhanden ist, muss ich sie verstehen. Wenn ich Ihnen sage, dass es eine Methode gibt, müssen Sie sie verstehen. Das einzige, was mich wirklich interessiert, ist, welche meiner Aktionen Nebenwirkungen haben. 4) Könnten Sie erweitern
Matt Esch

5) Könntest du nochmal erweitern. Ich bin Programmierer. Ich bin es gewohnt, mit gut definierten Objektstrukturen zu arbeiten. Warum sollten wir nicht denselben Mechanismus für die Definition aller unserer APIs verwenden, wenn es wirklich besser ist? 6) Keine Abstraktionsebene ist ohne Begründung erwägenswert. 7) Könnten Sie noch einmal erweitern? Wenn wir auf diese Weise davon profitieren, sollten wir sicherlich alle unsere APIs so codieren. 8) Ich würde erwarten, dass jedes Objekt seine Methoden direkt verfügbar macht. / object / method kann nicht verwechselt werden. Wir definieren die Standards, indem wir sie übernehmen. Mir fehlt momentan die Motivation.
Matt Esch

Matt Sie scheinen ein wenig argumentativ, aber ich werde sagen, dass für 2) Ich habe nicht gesagt, Ressource würde keine Standards benötigen 3) Sie müssen keine Methode wie 'Update' oder 'Neu' oder 'Erstellen' verstehen, weil Sie genau wissen was die nach den normen machen. Aber was ist mit 'MsgToPrimary', was macht das? Erstelle eine Nachricht? Status aktualisieren? Eine E-Mail senden? 7) Ja, die meisten APIs könnten davon profitieren, und viele tun dies. Ich würde versuchen, mich auf den Begriff Standard zu konzentrieren. Standards und Konventionen sind hilfreich, und ich kann sehen, dass Ihre Updates dies zeigen.
Michael Durrant

Ich versuche nur, die Vorteile zu verstehen. Die starken Gegenargumente müssen angesprochen werden, um das Problem zu klären. Ich verstehe immer noch, dass ein fester Satz von Verben eine Art Sprachbeschreibung ist, aber ich stimme nicht wirklich zu, dass es das Verständnis erleichtert. Sie können keine ausdrucksstarken Verben wegnehmen und sagen, hey, wir verstehen jetzt alle Verben, wenn wir nicht alle Ressourcen verstehen. Ressourcen ersetzen Verben. Wir ersetzen das beliebige Verb foo durch eine Ressource namens foo. Unser Verständnis von foo ist nicht klarer als zu der Zeit, als foo ein Verb war.
Matt Esch

1

Die Alternative ist etwas Schreckliches: WSDL (aka Web Service Definition Language), eine (unbeholfene) Art, (etwas) willkürliches APIS programmatisch zu beschreiben.

REST schränkt die Verben stark ein und drückt fast alle anwendungsspezifischen Variationen in die Nutzlast des Dokuments. Dies hat den Vorteil, dass viele Client-Implementierungen mit vielen heterogenen Diensten kommunizieren können. Die Clients und Server sind einander möglicherweise völlig unbekannt, einige sind noch nicht geschrieben.

Es gibt einen Podcast, in dem Stefan Tilkov REST nett erklärt .


1

Ja, eine Rest-API verfügt über eine feste Anzahl von Verben, muss jedoch nicht auf (oder GET, POST, PUT, DELETE) beschränkt sein. Ich würde GET, POST, PUT, DELETE als Standardimplementierung von REST betrachten, die für 80% aller Systeme da draußen funktioniert.

Andere Systeme, die mehr als rohe Operationen implementieren, können (und tun) ihre eigenen Verben für ihre REST-APIs implementieren. Verben wie Veröffentlichen, Konsumieren, Bewerten, Kommentieren, Suchen, Durchsuchen können in einem REST-System hinzugefügt und implementiert werden. Während einige sagen könnten, dass ein größeres Vokabular es komplizierter machen könnte, ist meine Antwort, dass es davon abhängt. Wenn Ihr Zielbenutzer Techniker sind, die verstehen, was ein POST ist, könnte dies komplizierter sein. Wenn die Zielbenutzer Ihrer API jedoch echte Personen sind (dh Personen, die keinen Code haben und nicht wissen, was ein POST ist), sind echte Verben viel einfacher zu verwenden. Tatsächlich hilft ein geeigneter Satz von Verben für Ihre API dabei, die URLs kurz zu halten (was wichtig ist, wenn Sie möchten, dass Benutzer sie in einen Browser eingeben. Wenn Sie ein benutzerdefiniertes Vokabular verwenden, Ich möchte sicherstellen, dass Ihre API und ihre Verben gut dokumentiert sind. Wenn Sie eine benutzerdefinierte REST-API verwenden, möchten Sie sicherstellen, dass Ihre schreibgeschützten Aktionen als HTTP-GET und Schreibaktionen mit POST ausgeführt werden.

Das soziale Teenagernetzwerk Piczo.com (möge es in Frieden ruhen) enthielt eine erweiterte REST-API (einschließlich der oben genannten Verben), die in 7 verschiedenen Sprachen implementiert wurde!


0

Einfach ist gut.

Es gibt Fälle, in denen Sie zusätzliche Verben und Komplexität benötigen, aber die meisten Probleme lassen sich auf einfache CRUD-Aktionen für Ressourcen reduzieren, und genau das versucht REST zu fördern. Wenn Sie an die meisten Webanwendungen denken, lesen sie am Ende Datensätze in einem Datenspeicher, die dieselben sehr einfachen Aktionen verwenden.

object.foo () ist alles gut, aber was macht es? Was kommt zurück? Ändert es den Status des Objekts oder eine seiner Abhängigkeiten? Können Sie es zweimal aufrufen und das gleiche Ergebnis erhalten oder erhalten Sie zwei unterschiedliche Werte? Wenn Sie auch object.bar () haben, müssen diese in einer bestimmten Reihenfolge aufgerufen werden?

Die Verwendung einer Rich-API erfordert viel Wissen, und sie hat normalerweise ihre eigenen Konventionen (dh setFoo mutiert das Objekt, getBar ist wahrscheinlich idempotent, dispose () oder destroy () bedeutet, dass keine anderen Aufrufe für dasselbe Objekt vorhanden sind wird möglich sein, etc ...)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.