it-swarm.com.de

Fördern RESTful-APIs tendenziell anämische Domänenmodelle?

Ich arbeite an einem Projekt, in dem wir versuchen, sowohl domänengesteuertes Design als auch REST auf eine serviceorientierte Architektur anzuwenden. Wir machen uns keine Sorgen um 100% REST Compliance; es wäre wahrscheinlich besser zu sagen, dass wir versuchen, ressourcenorientierte HTTP-APIs (~ Level 2 von Richardsons REST Reifegradmodell) zu erstellen. Trotzdem versuchen wir, uns von der Verwendung von HTTP-Anforderungen im RPC-Stil fernzuhalten, dh wir versuchen, unsere HTTP-Verben gemäß RFC2616 zu implementieren, anstatt POST zu verwenden, um IsPostalAddressValid(...), beispielsweise.

Eine Betonung darauf scheint jedoch auf Kosten unseres Versuchs zu gehen, domänengesteuertes Design anzuwenden. Mit nur GET, POST, PUT, DELETE und einigen anderen selten verwendeten Methoden neigen wir dazu, CRUDdy-Dienste zu erstellen, und CRUDdy-Dienste haben dies tendenziell anämische Domänenmodelle.

POST: Empfängt die Daten, validiert sie und speichert sie in der Datenbank. GET: Daten abrufen, zurückgeben. Keine wirkliche Geschäftslogik da. Wir verwenden auch Nachrichten (Ereignisse) zwischen den Diensten, und es scheint mir, dass der größte Teil der Geschäftslogik darauf aufbaut.

Sind REST und DDD auf einer bestimmten Ebene unter Spannung? (Oder verstehe ich hier etwas falsch? Tun wir vielleicht etwas anderes falsch?) Ist es möglich, ein starkes Domain-Modell in einem serviceorientierten Modell aufzubauen? Architektur unter Vermeidung von HTTP-Aufrufen im RPC-Stil?

34
Kazark

Martin Fowlers erstes Gesetz über verteilte Systeme: "Verteilen Sie Ihre Objekte nicht!" Remote-Schnittstellen sollten grobkörnig und interne Schnittstellen feinkörnig sein. Oft gilt das Rich-Domain-Modell nur innerhalb eines begrenzten Kontexts .

Die REST-API trennt zwei verschiedene Kontexte, die beide ihre eigenen internen Modelle haben. Die Kontexte kommunizieren über eine grobkörnige Schnittstelle (REST-API) unter Verwendung von "anämischen" Objekten (DTO).

In Ihrem Fall klingt es so, als würden Sie versuchen, einen Kontext über eine Grenze zu verteilen, die REST API) ist. Dies kann zu einer feinkörnigen Remote-Schnittstelle oder einem anämischen Modell führen. Abhängig von Ihrem Projekt kann es sein oder kann kein Problem sein.

39
simoraman

POST wurde absichtlich so konzipiert, dass es "absichtlich vage;" das Ergebnis eines POST ist implementierungsspezifisch. Was Sie daran hindert, das zu tun, was Twitter und andere API-Designer tun tun und definieren Sie jede POST Methode im Nicht-CRUD-Teil Ihrer API gemäß Ihren eigenen spezifischen Anforderungen? POST ist das catchall-Verb. Verwenden Sie es, wenn Keines der anderen Verben passt gut zu der Operation, die Sie ausführen möchten.

Anders ausgedrückt, Ihre Frage könnte gleichermaßen gestellt werden als "Fördern 'intelligente' Objekte das Design im RPC-Stil?" Sogar Martin Fowler (der den Begriff "Anemic Domain Model" geprägt hat) räumt ein Diese nackten DTOs haben einige Vorteile:

Das Einfügen von Verhalten in Domänenobjekte sollte nicht dem soliden Ansatz widersprechen, mithilfe von Layering die Domänenlogik von Dingen wie Persistenz und Präsentationsverantwortung zu trennen. Die Logik, die in einem Domänenobjekt enthalten sein sollte, lautet Domänenlogik - Validierungen, Berechnungen, Geschäftsregeln - wie auch immer Sie es nennen möchten.

In Bezug auf das Richardson Maturity Model können Sie Level 3 erreichen, ohne sich jemals Gedanken über "Anemic Domain Models" zu machen. Denken Sie daran, dass Sie niemals Verhalten auf den Browser übertragen werden (es sei denn, Sie planen, Javascript über Ihre Modelle einzufügen).

Bei REST geht es hauptsächlich um Maschinenunabhängigkeit. Implementieren Sie das Modell REST) in dem Maße, in dem Ihre Endpunkte Ressourcen darstellen sollen, und damit die Benutzer Ihrer API problemlos auf diese Ressourcen zugreifen und diese auf standardmäßige Weise verwalten können. Wenn dies anämisch erscheint , Dann ist es halt so.

Siehe auch
Ich brauche mehr Verben

10
Robert Harvey

Die REST-API ist nur eine Art von Präsentationsschicht. Es hat nichts mit dem Domain-Modell zu tun.

Die Frage, die Sie gestellt haben, kommt von Ihrer Verwirrung, dass Sie sich irgendwie aneinander anpassen müssen. Das tust du nicht.

Sie ordnen Ihr Domain-Modell Ihrer REST API) zu, genauso wie Sie Ihr Domain-Modell über ein ORM einem RDBMS zuordnen - es muss diese Mapping-Schicht geben.

Domain ← ORM → RDBMS
Domain ← REST Mapping → REST API

4

This Artikel ist ziemlich verwandt mit dem Thema und ich glaube, beantwortet Ihre Frage.

Ein Kernkonzept, von dem ich denke, dass es Ihre Frage sehr gut beantwortet, wird im folgenden Absatz des genannten Artikels zusammengefasst:

"Es ist sehr wichtig, zwischen Ressourcen in der API REST und Domänenentitäten in einem domänengesteuerten Design zu unterscheiden. Das domänengesteuerte Design gilt für die Implementierungsseite (einschließlich der API-Implementierung), während Ressourcen in RESTverwendet werden ] _ API-Laufwerk für API-Design und -Vertrag. Die Auswahl der API-Ressourcen sollte nicht von den zugrunde liegenden Details der Domänenimplementierung abhängen. "

3
Majix

IMHO Ich glaube nicht, dass sie dazu neigen, anämische Domänenmodelle (ADMs) zu fördern, aber sie erfordern, dass Sie sich etwas Zeit nehmen und die Dinge durchdenken.

Zunächst denke ich, dass das Hauptmerkmal von ADMs darin besteht, dass sie wenig bis gar kein Verhalten aufweisen. Das heißt nicht, dass das System kein Verhalten hat, sondern nur, dass es sich normalerweise um eine Serviceklasse handelt (siehe http://vimeo.com/4359819 ).

Und wenn das Verhalten im ADM nicht vorhanden ist, was dann? Die Antwort sind natürlich die Daten. Wie ordnet sich diese REST API?) Zu? Vermutlich werden die Daten dem Inhalt der Ressource und das Verhalten den HTTP-Verben zugeordnet.

Sie haben also alles, was Sie zum Erstellen eines umfangreichen Domänenmodells benötigen. Sie müssen lediglich sehen können, wie die HTTP-Verben den Domänenoperationen für die Daten zugeordnet sind, und diese Operationen dann in dieselben Klassen einordnen, die Ihre Daten kapseln.

Ich denke, wo Menschen dazu neigen, auf Probleme zu stoßen, ist, dass sie Schwierigkeiten haben zu sehen, wie die HTTP-Verben ihrem Domänenverhalten zugeordnet werden, wenn das Verhalten jenseits der einfachen CRUD liegt, dh wenn es in anderen Teilen der Domäne jenseits der Nebenwirkungen Nebenwirkungen gibt Ressource, die von der HTTP-Anforderung geändert wird. Eine Möglichkeit, dieses Problem zu lösen, sind Domain-Ereignisse ( http://www.udidahan.com/2009/06/14/domain-events-salvation/ ).

3
RibaldEddie

Mehrere einigermaßen erfolgreiche Implementierungen, die ich gesehen/gebaut habe, beantworten die Frage, wie sie die Verb + Nomen-Metapher mit grobkörnigen "geschäftsfreundlichen" Methoden mischen, die auf die Entitäten einwirken.

Stellen Sie also anstelle der (zum Scheitern verurteilten) getName() Methode/des Dienstes getPerson() offen, übergeben Sie Dinge wie Bezeichner-Typ/ID und geben Sie die gesamte Person Entität zurück.

Da das Verhalten der Entität "Person" in einem solchen Kontext nicht angemessen vermittelt werden kann (und möglicherweise auch nicht in einem datenzentrierten Kontext wie diesem), ist es durchaus sinnvoll, ein Datenmodell (gegenüber einem Objektmodell) für die Anforderungs-/Antwortpaare von zu definieren Die Dienste.

Die Dienste und definierten Verben selbst fügen einige domänenzulässige Verhaltensweisen, Steuerelemente und sogar Statusübergangsregeln für die Entitäten hinzu. Zum Beispiel würde es eine domänenspezifische Logik geben, was im transferPerson() - Serviceaufruf passiert, aber die Schnittstelle selbst würde nur die Ein-/Ausgabeentitäten/Daten definieren, ohne IHR internes Verhalten zu definieren.

Ich würde Autoren nicht zustimmen, die beispielsweise sagen würden, dass eine Verbimplementierung transfer in die Person-Klasse gehört oder einem personenzentrierten Service zugeordnet ist. In der Tat würde die Methode von Übertragung für ein Person und Optionen davon (in diesem einfachen Beispiel) besser durch ein Carrier definiert, wobei das Person weiß möglicherweise nicht einmal, welche Übertragungsmethoden verfügbar sind oder wie die Übertragung überhaupt stattfindet (wer weiß, wie Düsentriebwerke überhaupt funktionieren).

Macht dies die Entität Person anämisch? Das glaube ich nicht.

Es kann/sollte Logik über personenspezifische Dinge geben, die für die Person intern sind, wie z. B. ihren Gesundheitszustand, die nicht von einer externen Klasse definiert werden sollten.

Abhängig von den Anwendungsfällen ist es jedoch völlig akzeptabel, dass eine Entitätsklasse in bestimmten Systemen kein wichtiges/relevantes Verhalten aufweist, z. B. in einem Sitzzuweisungsdienst in einem Transportsystem. Ein solches System kann durchaus REST-basierte Dienste implementieren, die sich mit Personeninstanzen und zugehörigen Kennungen befassen, deren internes Verhalten jedoch niemals definieren/implementieren.

1
Darrell Teague

Ist Ihr Problem, dass Sie versuchen, Ihr Modell mit POST so oft wie möglich) in die Grundmenge der Verben zu packen?

Es ist nicht notwendig - ich weiß, dass für die meisten Leute REST bedeutet POST, GET, PUT und DELETE, aber der http rfc sagt:

Die allgemeinen Methoden für HTTP/1.1 sind nachstehend definiert. Obwohl dieser Satz erweitert werden kann, kann nicht davon ausgegangen werden, dass zusätzliche Methoden dieselbe Semantik für separat erweiterte Clients und Server verwenden.

Und Systeme wie SMTP verwenden den gleichen Stil verbbasierter Methoden, jedoch mit einer völlig anderen Menge.

Es gibt also keinen Grund, warum Sie diese verwenden müssen. Sie können jeden Satz von Verben verwenden, den Sie mögen (obwohl Sie wirklich feststellen werden, dass Sie mit ein wenig Nachdenken alles tun können, was Sie in der Basis 4 benötigen). Das, was REST von den anderen Mechanismen unterscheidet, ist die zustandslose und konsistente Art der Implementierung dieser Verben. Sie sollten nicht versuchen, ein Nachrichtenübergabesystem zwischen den Ebenen zu implementieren, da Sie im Grunde nicht = tun REST Dann führen Sie stattdessen einen Mechanismus zum Weiterleiten von Nachrichten, RPC oder Nachrichtenwarteschlangen durch, wodurch Sie zweifellos die Vorteile von REST (dh die Einfachheit von) verlieren) es, dass es über eine http-Verbindung wirklich gut funktioniert).

Wenn Sie ein komplexes Messaging-Protokoll mit allen Funktionen wünschen, erstellen Sie dieses (wenn Sie dies über das Web tun können, gibt es einen Grund, warum REST ist so beliebt), aber versuchen Sie ansonsten, sich daran zu halten das architektonische Design von REST.

0
gbjbaanb