Wie kann man eine Architekturverschiebung beschreiben, die absichtlich REST-Standards verletzt?

37

Ich schlage Änderungen an einem sehr schlecht strukturierten Softwareprojekt vor, das unter einer Vielzahl von Problemen leidet. Auf hohem Niveau nutzt das Projekt Angular im Front-End und verwendet verschiedene REST-APIs. Das ist alles großartig (ich sehe keine Notwendigkeit, unsere Technologie oder Werkzeuge zu ändern). Das Problem ist, dass die Codebasis in der Benutzeroberfläche unverhältnismäßig größer ist als die serverseitigen APIs. Ein Großteil der Geschäftslogik befindet sich in der Benutzeroberfläche, wobei die REST-APIs einfache CRUD-Datenbankschnittstellen zur Benutzeroberflächenschicht sind.

Ein POST an den Kunden erstellt beispielsweise einen Kundendatensatz, während ein PUT diesen Kunden ändert. Nicht viel mehr und nicht viel weniger. Unsere Geschäftslogik ist jedoch anspruchsvoller. Der allgemeine Prozess zum Erstellen eines Kunden umfasst weit mehr als das Einfügen eines Datenbankeintrags. Es stellt Daten in anderen erforderlichen Tabellen bereit, führt bestimmte Überprüfungen und Berechnungen durch usw. Ich würde es vorziehen, einen einzelnen POST / PUT-Aufruf durchzuführen, der all dieses Verhalten kapselt und die Last des konsumierenden Clients verringert.

Mein Standpunkt ist also, dass diese übergreifende Orchestrierung auf dem Server (auf dem wir Vollzugriff haben, Protokolle usw.) ausgeführt werden sollte, nicht auf der Benutzeroberfläche. Ein Gegenargument ist jedoch, dass dieser Ansatz nicht mehr REST-konform ist. Daher bin ich mir nicht sicher, wie ich diesen Ansatz am besten beschreiben kann, wenn ich empfehle, den vorhandenen Technologie-Stack beizubehalten, aber grundlegende Änderungen an den Stellen vorzunehmen, an denen Code enthalten ist.

Ben Harrison
quelle
44
Wenn Sie Ihre API auf CRUD beschränken, müssen Sie dafür sorgen, dass sie "RESTful" ist.
Robert Harvey
38
@EsbenSkovPedersen: Bester Freund für immer?
Robert Harvey
5
Anstatt sich Gedanken darüber zu machen, ob Ihr Service REST-konform ist (iirc, fast keiner), würde ich mich mehr um die Konformität mit der HTTP-Spezifikation kümmern . Die meisten APIs, mit denen ich gearbeitet habe, stimmen nicht mit der Spezifikation überein, aber es ist ein erreichbareres und lohnenderes Ziel.
aaaaaa
7
@aaaaaa, der Grund, warum fast keine Dienste REST-konform sind, ist, dass niemand entscheiden kann, was REST ist. Der einzige Übereinstimmungspunkt, den ich gefunden habe, ist, dass "alle anderen es falsch machen".
Mark
16
- "Wie kann man eine architektonische Veränderung beschreiben, die absichtlich gegen REST-Standards verstößt?" - Missachtung . ( Entschuldigung für einen unprofessionellen Kommentar, es war stärker als ich. )
Luk32

Antworten:

49

Ich bin mir nicht sicher, wie ich diesen Ansatz am besten beschreiben kann, wenn ich empfehle, den vorhandenen Technologie-Stack beizubehalten, aber grundlegende Änderungen an den Stellen vorzunehmen, an denen Code gehört.

Service oriented architecture.

Sie möchten Ihr System so umgestalten, dass sich Ihre Geschäftsregeln und Ihre Daten an derselben Stelle befinden. Das ist quasi die Definition eines Dienstes . siehe Udi Dahans Vortrag über das Auffinden von Dienstgrenzen .

Sidebar: Wie von Eric bemerkt, hat dies nichts mit "REST" zu tun. Es gibt absolut keinen Grund, warum Sie eine REST-API (dh eine API, die die Einschränkungen des REST-Architekturstils erfüllt ) nicht vor Ihren Service stellen können. Für Personen, die REST als Zuordnung von Datenbankoperationen zu HTTP-Methoden verstehen, ist dies jedoch möglicherweise nicht offensichtlich.

Es kann sich lohnen, in das Verständnis Ihres Publikums für REST zu investieren, oder auch nicht.

VoiceOfUnreason
quelle
32
Es kann sich auch nicht lohnen, in REST zu investieren. Wenn Sie die Dissertation von Roy Fielding lesen (oder wie ich meiner Frau REST erklärt habe ), besteht der wahre Zweck von REST darin , eine kanonische Darstellung von Ressourcen im Internet bereitzustellen, damit unterschiedliche Maschinen im Internet eine Standardmethode zum Manipulieren dieser Ressourcen haben . Eine private Anwendung benötigt diese Funktion möglicherweise nicht einmal.
Robert Harvey
29

REST ist nicht CRUD. Dieses "Gegenargument" basiert auf einem grundlegend fehlerhaften Verständnis dessen, was REST ist. Ich habe in Ihrem Beitrag nichts gesehen, was darauf hindeutet, dass Ihre Änderung Ihre API mehr oder weniger RESTful machen würde.

Eric Stein
quelle
6
Nun, nein, es ist keine perfekte Zuordnung zu CRUD, aber es geht und spricht und singt sehr ähnlich wie CRUD, zumindest so, wie die meisten Leute es interpretieren.
Robert Harvey
11
@RobertHarvey Ich denke, es ist das (falsche) Verständnis, das hier das Problem ist.
JimmyJames
4
@ JimmyJames: Es ist ein allgegenwärtiges Missverständnis. Es gibt ein starkes Bestreben, die Dinge "erholsam" zu machen, wenn die meisten Leute nicht einmal verstehen, was die Vorteile sind oder wie diese Vorteile für sie gelten würden.
Robert Harvey
4
@RobertHarvey Ich denke, Sie sagen, dass REST kein Ziel sein sollte, wenn Sie es falsch machen. OK, aber so wie ich das sehe, ist es Bullshit und ich bin ein großer Befürworter, Bullshit für Bullshiter zu nennen. Wörter brauchen eine allgemein verstandene Bedeutung, um nützlich zu sein.
JimmyJames
5
@RobertHarvey Zugegeben, aber das wird nicht passieren, solange es genügend Leute gibt, die bereit sind, diesen Missbrauch des Begriffs zu korrigieren. Ich bin nicht bereit, das Handtuch zu werfen.
JimmyJames
24

Beachten Sie außerdem Folgendes: Wenn Sie Ihre Business Rules-Serverseite nicht validieren, bedeutet dies, dass Sie implizit darauf vertrauen, dass alle eingehenden Daten, beispielsweise eine POST-Anforderung, gültig sind.

Das heißt, während Ihre eckige Anwendung möglicherweise prüft, ob der Kunde eine gültige Altersspanne hat und sicherstellt, dass legitime Benutzer das richtige Feedback erhalten, kann jeder, der die URL zu Ihrer API kennt, eine POST-Anfrage mit einigen nicht legitimen Werten durchführen, die dies tun würden nicht mehr validiert werden.

Mein Vorschlag wäre also, Ihre Geschäftsregeln in die API zu verschieben, die Eingabe validieren zu lassen und entsprechende Fehler (oder einfach nur Codes, die angeben, was schief gelaufen ist) im Hauptteil der Antwort zurückzugeben. Diese Codes können dann von Ihrer Front-End-Anwendung verwendet werden, um anzuzeigen, was schief gelaufen ist.

mrsmn
quelle
5
Dies ist bei weitem die nützlichste Antwort: Die API ist die Angriffsfläche, nicht die Eingabe für den Client. Jede API-Anfrage kann gefälscht werden. Alles, was mit der reinen API getan werden kann, ist das, was ein talentloser, böswilliger Skript-Kiddie tun kann. Die Client-Software kann verwendet werden, um eine bessere Benutzererfahrung zu erzielen, aber es ist der Server, der die Regeln durchsetzen muss.
cmaster
10

Um die anderen guten Antworten hier hinzuzufügen:

Ihre Schnittstelle, REST oder anderweitig, sollte nicht aufgrund von Annahmen in Bezug auf Implementierungsdetails eingeschränkt werden. Dies steht in völligem Widerspruch zum Begriff der Dienste als Abstraktionsschicht.

Einer der Hauptvorteile der Verwendung von Diensten besteht darin, dass Implementierungsdetails geändert werden können, ohne dass die Clients etwas tun müssen. Nach dem, was Sie beschrieben haben, scheint es keine wirkliche Abstraktionsschicht zu geben. Die Details der Implementierung wurden über HTTP veröffentlicht. Nichts über REST sagt aus, dass dies notwendig, hilfreich oder wünschenswert ist. Tatsächlich denke ich, dass ich bestimmte Teile der REST-Definition dahingehend argumentieren könnte, dass dies tatsächlich eine nicht- REST -konforme Implementierung ist.

Was Sie vorschlagen, ist, wie eine richtige Service-Schicht entworfen werden sollte. Wenn dir jemand sagt, dass du es nicht kannst, weil es nicht RESTful ist, ist das unglücklich. Sie können sicher sein, dass jemand, der Ihnen sagt, dass er wenig bis gar nichts über REST weiß.

Aufgrund Ihrer Frage haben Sie eine Ressource namens Kunde. Alles, was zum Erstellen einer gültigen Kundenressource erforderlich ist, kann und sollte in einer POSTzur Kundenbasis gehörenden Ressource verarbeitet werden (oder alternativ / optional in einem PUT zu einer bestimmten Kundenressource, falls diese nicht vorhanden ist). REST sagt nichts darüber aus, wie viele Datenbankeinträge, die Sie bei einem bestimmten Aufruf erstellen müssen. Wie Colin Young bemerkte, muss es überhaupt keine Datenbank geben, es ist völlig irrelevant, wie Services aus einer REST-Perspektive implementiert werden.

JimmyJames
quelle
3
REST sagt nichts über Datenbankdatensätze aus, geschweige denn wie viele. Ich könnte einen REST-Dienst erstellen, der ein Wasserventil steuert und Ressourcen für Wasserventil, Wasserversorgung und Tankfüllstand freigibt. Man könnte argumentieren, dass die physischen Objekte selbst eine "Datenbank" sind, aber die Dinge ein bisschen dehnen.
Colin Young
@ColinYoung Ja, danke, dass Sie zur Klärung beigetragen haben.
JimmyJames
3

Hier gibt es einige gute Antworten, aber ich bin nicht sicher, ob sie Ihnen helfen werden, Ihre Mitarbeiter zu überzeugen. Wie viele darauf hingewiesen haben, ist das, was Sie vorschlagen, keine Abkehr vom REST-konformen Design, und ich denke, dies ist der Schlüssel, um sie mit Ihrem Vorschlag in Einklang zu bringen.

Bei REST geht es nicht darum, sicherzustellen, dass Ihre API nur das Speichern und Abrufen von Daten ermöglicht. Es geht vielmehr darum, Aktionen als Ressourcen zu modellieren . Ihre API sollten Maßnahmen ergriffen werden können (es ist ein Application Programming Interface , nachdem alle). Die Frage ist, wie diese Aktionen modelliert werden können.

Anstatt sich einen Begriff auszudenken, sind Beispiele wahrscheinlich die beste Möglichkeit, dies Ihren Mitarbeitern zu erklären . Auf diese Weise können Sie zeigen, wie sie es jetzt tun, welche Probleme dies verursacht, eine Lösung, die das Problem löst, und wie es immer noch RESTful bleibt.

Schauen wir uns Ihr Kundenobjekt an.

Problem:

Die Benutzeroberfläche sendet einen Kunden, nachfolgende Tabellen wurden jedoch noch nicht aktualisiert. Was passiert, wenn einer der nachfolgenden Aufrufe aufgrund eines Fehlers in Ihrem UI-Code (oder eines fehlerhaften Browser-Plugins usw.) fehlschlägt? Jetzt befinden sich Ihre Daten in einem inkonsistenten Zustand. Es könnte sogar ein Zustand sein, der andere Teile Ihrer API oder Benutzeroberfläche zerstört, ganz zu schweigen davon, dass er einfach ungültig ist. Wie erholst du dich? Sie müssten auf jeden möglichen Zustand testen, um sicherzugehen, dass dies nichts kaputt macht, aber es wäre schwierig zu wissen, was möglich ist.

Lösung:

Erstellen Sie einen API-Endpunkt, um Kunden zu erstellen. Sie wissen, dass Sie keinen "/ customer / create" - oder sogar "/ create-customer" -Endpunkt haben möchten, da "create" ein Verb ist und gegen REST verstoßen würde. Also kündige es an. "/ customer-creation" könnte funktionieren. Wenn Sie jetzt Ihr CustomerCreation-Objekt POSTEN, werden alle erforderlichen Felder gesendet, damit ein Kunde vollständig erstellt werden kann. Der Endpunkt stellt sicher, dass die Daten vollständig und gültig sind (z. B. 400 zurückgeben, wenn die Validierung fehlschlägt) und möglicherweise alle innerhalb einer einzelnen DB-Transaktion bestehen bleiben.

Wenn Sie auch einen Endpunkt für GET / customer-Objekte benötigen, ist dies in Ordnung. Sie können beides haben. Der Trick besteht darin, Endpunkte zu erstellen, die den Bedürfnissen der Verbraucher entsprechen.

Vorteile:

  1. Sie garantieren, dass Sie nicht in einen schlechten Zustand geraten
  2. Es ist für die Benutzeroberflächenentwickler tatsächlich einfacher, wenn sie die Reihenfolge von Anforderungen, Validierungsproblemen usw. Nicht "kennen" müssen
  3. Es ist nicht so gesprächig wie eine API und reduziert die Latenz von Netzwerkanforderungen
  4. Es ist einfacher, Szenarien zu testen und zu konzipieren (fehlende / fehlerhafte Daten von der Benutzeroberfläche sind nicht auf mehrere Anforderungen verteilt, von denen einige möglicherweise fehlschlagen).
  5. Es ermöglicht eine bessere Kapselung der Geschäftslogik
  6. Erleichtert im Allgemeinen die Sicherheit (da die Geschäfts- und Orchestrierungslogik in der Benutzeroberfläche von den Benutzern geändert werden kann)
  7. Vermindert wahrscheinlich die Duplizierung der Logik (mehr als 2 Benutzer einer API als mehr als 2 APIs, die Zugriff auf dieselben Daten gewähren)
  8. Immer noch 100% RUHIG

Nachteile:

  1. Es ist möglicherweise mehr Arbeit für den Back-End-Entwickler (aber möglicherweise nicht auf lange Sicht)

Es kann für die Menschen schwierig sein, dieses Paradigma zu verstehen und was daran gut ist, wenn sie es nicht ausprobiert haben. Hoffentlich können Sie ihnen helfen, indem Sie ein Beispiel aus Ihrem eigenen Code verwenden.

Meine eigene Erfahrung ist, dass die Entwickler in meinem Team, als sie mit der Umsetzung dieser Strategie begannen, die Vorteile fast sofort erkannten.

Weitere Studie:

Dieser Artikel von thoughtworks hat mir wirklich geholfen, anhand praktischer Beispiele die Idee zu bekommen, Aktionen als Objekte zu modellieren: https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling

Ich würde auch vorschlagen, sich über CQRS und Event Sourcing zu informieren, da sie genau mit dieser Art von Dingen zu tun haben (dh Ihre API von der eigentlichen Persistenzlogik zu trennen). Ich weiß nicht, wie bereit Ihre Mitarbeiter wären, solche Dinge zu lesen, aber es könnte Ihnen mehr Klarheit verschaffen und Ihnen helfen, sie ihnen zu erklären.

Planky
quelle
" weil create ein Verb ist und gegen REST verstoßen würde " - Absolut richtig. Mit anderen Worten wäre es dann der 47.258.346. Ansatz, " RPC über REST " auszuführen . Das ist etwas, das ich zumindest als "unnatürlich" bezeichnen würde, weil es REST-konforme Ansätze missbraucht und falsch darstellt (sie haben ihre Anwendungsfälle, aber RPC ist keiner von ihnen) und auch dazu neigt, ineffizient zu sein.
JensG