Anämisches Domänenmodell: Vor- / Nachteile


Antworten:


39

Die Profis:

  • Sie können behaupten, es sei ein Domain-Modell, und Ihren Entwicklerfreunden damit prahlen und es in Ihren Lebenslauf aufnehmen.
  • Es ist einfach, automatisch aus Datenbanktabellen zu generieren.
  • Es lässt sich überraschend gut auf Datenübertragungsobjekte abbilden.

Die Nachteile:

  • Ihre Domänenlogik existiert an einer anderen Stelle, wahrscheinlich in einer Klasse voller (statischer) Klassenmethoden. Oder Ihren GUI-Code. Oder an mehreren Stellen, alle mit widersprüchlicher Logik.
  • Es ist ein Anti-Pattern, daher werden andere Entwickler fragen, ob Sie die Konzepte des objektorientierten Designs verstehen.

7
+1 Der Punkt zum Generieren des Codes aus Datenbanktabellen ist für einige Leute sehr wichtig. Wenn Sie sich in einem Rapid-Prototyping-Entwicklungsmodus befinden, ist die automatische Codegenerierung äußerst hilfreich. Wir tun nicht so, als wäre dies das richtige OO-Design, und wenn die Dinge schlampig zusammengesetzt werden, entstehen "technische Schulden". In vielen Projekten hat die Markteinführung jedoch eine höhere Priorität.
Bill Karwin

62
Nein. Ob ein anämisches Modell ein Anti-Muster ist, ist Ansichtssache. Fowler (dessen Arbeit ich respektiere und der ich normalerweise folge) sagt, dass es so ist. Ich bin anderer Meinung (nicht, dass mein Wort irgendein Gewicht hat), und viele in den OO-Gräben sind ebenfalls anderer Meinung. Die reine OO-Modellierung ist nicht in jedem Fall allgemein anwendbar, den die gesamte Branche aus Erfahrung kennt. Darüber hinaus kann ein anämisches Modell weiterhin die OO-Modellierungsrichtlinien einhalten. Wenn Sie also bestimmte Fälle sehen, in denen Sie sich bewerben, wird das Verständnis des OO-Designs nicht in Frage gestellt.
Luis.espinal

12
Ob ein Muster ein Anti-Muster ist, ist Ansichtssache. Ein robustes Domänenmodell ist ein gutes OO-Design und ein anämisches Domänenmodell ist ein schlechtes OO-Design. Daher ist es im Kontext von OO ein Anti-Muster. Das bedeutet nicht, dass es nicht verwendet wird oder in allen Fällen unangemessen ist, aber aus persönlicher Erfahrung halte ich es für schlimmer als Singleton-Sucht.
Terry Wilcox

7
Ich glaube, es gibt einen Trend zur funktionalen Programmierung, und das Domänenmodell hat tendenziell viele Nebenwirkungen. Ich habe das Gefühl, dass das anämische Domänenmodell ein Comeback feiert, da es einen funktionaleren Programmierstil ermöglicht, bei dem Ihre Geschäftslogik Daten erwartet und verarbeitete Daten zurückgibt. Ihre Service-Schicht überwacht den Ablauf des Ganzen, indem sie weiß, welche Daten mit welcher Geschäftslogikmethode verarbeitet werden müssen.
Didier A.

2
@ TerryWilcox Nun, ich bin kein Funktionsexperte, aber die funktionale Programmierung hat auch Datenstrukturen. Ein anämisches Domänenmodell verwendet Objekte nur als Datencontainer, sie ähneln eher Strukturen. Mein Punkt ist, dass Sie mit ADM zu einem funktionaleren Weg übergehen können, bei dem Sie unveränderliche Daten haben, die im Laufe der Zeit in immer neuere Zustände umgewandelt werden. Ich kann dies zum Beispiel in Scala sehen, wenn ich versuche, ein bisschen OOP zu nutzen und etwas FP darauf anzuwenden. Ein bisschen wie sie es hier erklären: slidehare.net/debasishg/qconny-12
Didier A.

131

Warum gibt es so viele Systeme, die dies implementieren, da "Anemic Domain Model" ein Anti-Pattern ist?

Ich denke, es gibt mehrere Gründe

1. Komplexität des Systems

In einem einfachen System (das fast alle Beispiele und Beispielcodes enthält, die Sie im Internet finden) möchte ich Folgendes implementieren:

Produkt zur Bestellung hinzufügen

Ich habe diese Funktion in die Bestellung aufgenommen

public void Order.AddOrderLine(Product product)
{
    OrderLines.Add(new OrderLine(product));
}

Schön und super objektorientiert.

Angenommen, ich muss sicherstellen, dass das Produkt im Inventar vorhanden ist, und eine Ausnahme auslösen, wenn dies nicht der Fall ist.

Ich kann es nicht mehr wirklich bestellen, da ich nicht möchte, dass meine Bestellung vom Inventar abhängig ist. Jetzt muss sie in Betrieb genommen werden

public void OrderService.AddOrderLine(Order order, Product product)
{
    if (!InventoryService.Has(product)
       throw new AddProductException

    order.AddOrderLine(product);
}

Ich könnte IInventoryService auch an Order.AddOrderLine übergeben, was eine weitere Option ist, die Order jedoch weiterhin von InventoryService abhängig macht.

In Order.AddOrderLine gibt es noch einige Funktionen, die jedoch normalerweise auf den Bestellbereich beschränkt sind, während meiner Erfahrung nach viel mehr Geschäftslogik außerhalb des Bestellbereichs vorhanden ist.

Wenn das System mehr als nur eine einfache CRUD ist, haben Sie den größten Teil Ihrer Logik in OrderService und nur sehr wenig in Order.

2. Sicht des Entwicklers auf OOP

Im Internet gibt es viele hitzige Diskussionen darüber, welche Logik auf Entitäten angewendet werden soll.

Etwas wie

Order.Save

Sollte Order wissen, wie sie sich selbst retten kann oder nicht? Nehmen wir an, wir haben Repositories dafür.

Kann Order jetzt Bestellpositionen hinzufügen? Wenn ich versuche, es mit einfachem Englisch zu verstehen, macht es auch keinen Sinn. Der Benutzer fügt der Bestellung ein Produkt hinzu. Sollten wir also User.AddOrderLineToOrder () ausführen? Das scheint übertrieben.

Wie wäre es mit OrderService.AddOrderLine (). Jetzt macht es irgendwie Sinn!

Mein Verständnis von OOP ist, dass Sie zur Kapselung Funktionen in Klassen einfügen, in denen die Funktion auf den internen Status der Klasse zugreifen muss. Wenn ich auf die Order.OrderLines-Auflistung zugreifen muss, setze ich Order.AddOrderLine () auf Order. Auf diese Weise wird der interne Status der Klasse nicht angezeigt.

3. IoC-Container

Systeme, die IoC-Container verwenden, sind normalerweise vollständig anämisch.

Dies liegt daran, dass Sie Ihre Dienste / Repositorys mit Schnittstellen testen können, Domänenobjekte jedoch nicht (einfach) testen können, es sei denn, Sie fügen allen Schnittstellen hinzu.

Da "IoC" derzeit als Lösung für alle Ihre Programmierprobleme gelobt wird, folgen viele Leute ihm blind und auf diese Weise erhalten Sie anämische Domänenmodelle.

4. OOP ist schwierig, das Verfahren ist einfach

Ich habe ein bisschen einen " Fluch des Wissens " in diesem Fall, aber ich habe festgestellt, dass es für neuere Entwickler viel einfacher ist, DTOs und Services zu haben als Rich Domain.

Möglicherweise liegt es daran, dass es mit Rich Domain schwieriger ist zu wissen, auf welche Klassen die Logik gesetzt werden soll. Wann werden neue Klassen erstellt? Welche Muster sollen verwendet werden? etc..

Bei zustandslosen Diensten geben Sie es einfach in den Dienst mit dem nächstgelegenen Namen ein.


Ich denke, es würde davon abhängen, wie komplex es werden würde. 1. Wenn es so einfach ist wie in 1-2 Abhängigkeiten - ich würde es in der Order-Klasse behalten. 2. Bei mäßiger Komplexität würde ich die OrderLines-Klasse erstellen und Order.OrderLines verwenden, um die Order <-> OrderLines-Kommunikation sowie die zugehörigen Abhängigkeiten zu verarbeiten. 3. Aber im Falle einer hohen Komplexität würde ich den Anwendungsdienst OrderService verwenden, um die meisten externen Abhängigkeiten zu berücksichtigen, während die Logik des Auftragsmoduls in der Reihenfolge bleibt.
Eric P

13
Tolle Zusammenfassung - all diese Gründe sind der Grund, warum es kein Anti-Muster ist. Die slawische Hingabe an OO ist ein Antimuster. Fügen Sie jetzt Parallelität ohne Projektion hinzu und beobachten Sie, wie Sie sich mit Fowler-Stil OO in Knoten binden. Sehen Sie sich Unternehmen an, die in großem Maßstab Parallelität betreiben (z. B. Google), und sehen Sie, wie viel OO sie tun.
DanH

Schön gesagt. Bei Verwendung von Grails bin ich mir nicht sicher, ob 3 ° zu Anämie führt. Was 1 ° betrifft, beenden Sie tatsächlich das Verschieben der Logik in der Serviceschicht in jeder nicht trivialen Anwendung. Aber ich habe immer noch einen domänenzentrierten Ansatz mit Grails. Das macht es eigentlich nicht so gut, da Ihre Domain Ihr bevorzugter Ort für Logik ist, Sie aber bei Bedarf Bits um eine Ebene nach oben verschieben.
Youri

4
Ich sehe keine Korrelation zwischen IoC und Anämie. Es scheint ein völlig unabhängiges Thema zu sein. Ob Ihre Services / Repositorys oder Domänenobjekte Schnittstellen implementieren, hat nichts mit dem Testen zu tun. Sie testen vielmehr Services / Repositorys / Domänenobjekte und entkoppeln sie von ihren Abhängigkeiten, die selbst Schnittstellen implementieren. Und ob Sie dies richtig machen oder nicht, hat keine Korrelation zu IoC, die ich sehen kann.

2
Die Sache mit DDD, die ich mit Grok zu kämpfen habe, ist Ihr erster Punkt: "Wenn das System mehr als nur ein einfaches CRUD ist, werden Sie den größten Teil Ihrer Logik in OrderService und sehr wenig in Order haben." Das macht für mich Sinn, aber ist der Zweck von DDD nicht für komplexere Systeme zu verwenden?
Dan Ling

20

Danach habe ich schon sehr lange einen Gedanken in meinem Kopf. Ich glaube, dass der Begriff "OOP" eine Bedeutung angenommen hat, die nicht wirklich dafür bestimmt ist. Das Anagramm bedeutet "objektorientierte Programmierung", wie wir alle wissen. Der Fokus liegt natürlich auf dem Wort "orientiert". Es ist nicht "OMP", was "objektprogrammierte Programmierung" bedeutet. Sowohl ADM als auch RDM sind Beispiele für OOP. Sie verwenden Objekte, Eigenschaften, Methodenschnittstellen usw. Es gibt jedoch einen Unterschied zwischen ADM und RDM in der Art und Weise, wie wir Dinge kapseln. Das sind zwei verschiedene Dinge. Zu sagen, dass ADM schlecht ist OOP ist keine genaue Aussage. Vielleicht brauchen wir stattdessen andere Begriffe für verschiedene Kapselungsstufen. Außerdem hat mir der Begriff Anti-Pattern nie gefallen. Es wird normalerweise von Mitgliedern einer gegnerischen Gruppe etwas zugewiesen. Sowohl ADM als auch RDM sind gültige Muster, sie verfolgen einfach unterschiedliche Ziele und sollen unterschiedliche Geschäftsanforderungen lösen. Diejenigen von uns, die DDD praktizieren, sollten dies zumindest zu schätzen wissen und nicht auf das Niveau anderer fallen, indem sie diejenigen verprügeln, die sich für die Implementierung von ADM entscheiden. Nur meine Gedanken.


16

"Es ist ein Anti-Pattern, daher werden andere Entwickler fragen, ob Sie die Konzepte des objektorientierten Designs verstehen."

"Ein anämisches Domänenmodell ist ein Anti-Muster. Anti-Muster haben keine Vorteile."

Ob das anämische Domänenmodell ein Anti-Muster ist, ist Ansichtssache. Martin Fowler sagt, dass dies der Fall ist. Eine Reihe von Entwicklern, die OO genau kennen, sagen, dass dies nicht der Fall ist. Die Angabe der Meinung als Tatsache ist selten hilfreich.

Und selbst wenn es allgemein als Anti-Muster akzeptiert würde, besteht die Möglichkeit, dass es immer noch einen (wenn auch relativ geringen) Vorteil hat.


2
... welche sind? Ich versuche nicht, dich oder irgendjemanden auszutricksen, aber ich bin wirklich neugierig auf die Profis. Die Nachteile wurden tausendmal erwähnt, aber ich suche immer noch nach belastbaren Vorteilen des ADM (abgesehen von Polemikphrasen).
struppi

6
... das scheint, als würde jemand versuchen, das Adovcate des Teufels mit wenig Show dafür zu spielen. the chances are it would still have some (though relatively little) upside.Dann nennen Sie bitte einige! Mindestens eine, anstatt eine Hypothese aufzustellen!
Schlitten

2
Es ist einfacher zu wissen, wo eine Logik für etwas hingehört, das nicht mit einer Klasse zusammenhängt (ein echtes Geschäft). Wie an anderen Stellen gesagt, hat das "Rich-Domain-Modell" Logik an mehreren Stellen (Serviceschicht, mehrere Klassen, die an Objektgraphen beteiligt sind, ...). Mit RDM haben Sie außerdem keinen einfachen Überblick über die gesamte Geschäftslogik, können Zyklen nicht einfach vermeiden usw. Dumme Datenstrukturen ohne Logik haben ihren Platz in einer OO-Anwendung.
Ymajoros

1
Ich finde, dieser Artikel gibt ein gutes Argument, um zu sagen, ADM ist kein Antipattern blog.inf.ed.ac.uk/sapm/2014/02/04/…
Syclee

1
Antipatterns verursachen immer Probleme und wir haben erfolgreich mehrere ziemlich große Anwendungen (2 oder 3 Jahre Entwicklung von 10 Entwicklern arbeiten> 300KLOC) mit hochwertigen Lösungen ausgeliefert, die das Muster verwenden und ohne das Gefühl zu haben, dass etwas damit nicht stimmt. Es kann also nicht so schlimm sein, wenn es so ist ermöglicht es Ihnen, guten Code zu erstellen, während Sie ihn verwenden.
Ignacio Soler Garcia

13

Es scheint mir, dass Fowlers größter Einwand darin besteht, dass ADMs im folgenden Sinne keine OO sind. Wenn man ein System "von Grund auf neu" um passive Datenstrukturen herum entwirft, die von anderen Codeteilen manipuliert werden, riecht dies sicherlich eher nach prozeduralem Design als nach objektorientiertem Design.

Ich schlage vor, dass es mindestens zwei Kräfte gibt, die diese Art von Design erzeugen können:

  1. Designer / Programmierer, die immer noch der Meinung sind, dass prozedural erforderlich ist, um in einer objektorientierten Umgebung zu arbeiten (oder davon auszugehen, dass sie ...), um ein neues System zu erstellen , und

  2. Entwickler, die daran arbeiten, einem Legacy- System, das nicht OO-fähig ist (unabhängig von der Sprache), ein serviceähnliches "Gesicht" zu verleihen.

Wenn Sie beispielsweise eine Reihe von Diensten erstellen, um die Funktionalität einer vorhandenen COBOL-Mainframe-Anwendung verfügbar zu machen, können Sie Dienste und Schnittstellen anhand eines konzeptionellen Modells definieren, das die internen COBOL-Datenstrukturen nicht widerspiegelt. Wenn der Dienst das neue Modell jedoch den alten Daten zuordnet, um die vorhandene, aber versteckte Implementierung zu verwenden, ist das neue Modell möglicherweise im Sinne von Fowlers Artikel "anämisch" - z. B. eine Reihe von Definitionen im TransferObject-Stil und Beziehungen ohne wirkliches Verhalten.

Diese Art von Kompromiss kann durchaus für die Grenzen üblich sein, an denen idealistisch reine OO-Systeme mit einer vorhandenen Nicht-OO-Umgebung interagieren müssen.


8

Das anämische Domänenmodell (ADM) ist möglicherweise eine gute Wahl, wenn Ihr Team nicht in der Lage oder nicht bereit ist, ein Rich-Domain-Modell (RDM) zu erstellen und es im Laufe der Zeit zu warten. Das Gewinnen mit einem RDM erfordert eine sorgfältige Beachtung der im System verwendeten dominanten Abstraktionen. Stellen Sie sich vor, dass in jeder Entwicklergruppe nicht mehr als die Hälfte und vielleicht nur ein Zehntel ihrer Mitglieder mit Abstraktionen kompetent sind. Wenn dieser Kader (möglicherweise nur ein einziger Entwickler) nicht in der Lage ist, Einfluss auf die Aktivitäten der gesamten Gruppe zu nehmen, wird das RDM der Entropie erliegen.

Und das entropische RDM tut besonders weh. Die Entwickler werden harte Lektionen lernen. Zunächst werden sie in der Lage sein, die Erwartungen ihrer Stakeholder zu erfüllen, da sie keine Geschichte haben, der sie gerecht werden können. Aber wenn ihr System komplizierter (nicht komplexer) wird , wird es spröde; Die Entwickler werden versuchen, Code wiederzuverwenden, neigen jedoch dazu, neue Fehler oder Rückverfolgungen in der Entwicklung hervorzurufen (und damit ihre Schätzungen zu überschreiten).

Im Gegensatz dazu werden die ADM-Entwickler geringere Erwartungen an sich selbst stellen, da sie nicht erwarten, so viel Code für neue Funktionen wiederzuverwenden. Mit der Zeit werden sie ein System mit vielen Inkonsistenzen haben, aber es wird wahrscheinlich nicht unerwartet kaputt gehen. Ihre Markteinführungszeit wird länger sein als bei einem erfolgreichen RDM, aber es ist unwahrscheinlich, dass ihre Stakeholder diese Möglichkeit wahrnehmen.


5

"Entwickler, die daran arbeiten, einem Legacy-System, das nicht von OO (unabhängig von der Sprache) entwickelt wurde, ein serviceähnliches" Gesicht "zu verleihen."

Wenn Sie an viele LOB-Anwendungen denken, verwenden diese Legacy-Systeme häufig nicht dasselbe Domänenmodell wie Sie. Das anämische Domänenmodell löst dieses Problem mithilfe der Geschäftslogik in Serviceklassen. Sie könnten all diesen Schnittstellencode in Ihr Modell einfügen (im herkömmlichen OO-Sinne) - aber normalerweise verlieren Sie die Modularität.


1
Bingo. Hier scheinen viele Leute das Boot zu vermissen. ADMs haben einen Zweck. Ihr Missbrauch ist ein Anti-Muster, aber sie selbst sind es nicht.
Luis.espinal

4

Als ich zum ersten Mal auf den Artikel über das Anemic Domain Model stieß, dachte ich: "Holy S ***, das ist was ich tue. Horror!" Ich beharrte und folgte den Verweisen auf Eric Evans Buch, das als gutes Beispiel angesehen wurde, und lud die Quelle herunter. Es stellt sich heraus, dass "kein anämisches Domänenmodell verwenden" nicht bedeutet, "keine Serviceklassen zu verwenden, keine Mediatoren zu verwenden, keine Strategien zu verwenden" oder sogar "der manipulierten Klasse Logik zu verleihen".

Die DDD-Beispiele enthalten Serviceklassen, XyzUpdaters, Singletons und IoC.

Ich bin immer noch verwirrt darüber, was genau ein anämisches Domänenmodell ist. Ich erwarte "Ich werde es wissen, wenn ich es sehe". Im Moment bin ich zufrieden mit einem positiven Beispiel für gutes Design.


1
Ich habe später Eric Evans Buch gekauft und kann es nur empfehlen. Es bietet solide Beispiele für das Gegenteil von anämischen Domänenmodellen.
Jamie

4

Nachdem ich mit einem "ausgereiften" System mit einem ADM gearbeitet habe und das Gefühl habe, dass ich zumindest ein anekdotisches Feedback zu dieser Frage geben kann.

1) Fehlende Verkapselung

In einem Live-System mit einem ADM besteht die Möglichkeit, zB 'obj.x = 100; obj.save ', auch wenn dies gegen die Geschäftslogik verstößt. Dies führt zu einer Reihe von Fehlern, die nicht auftreten würden, wenn die Invarianten dem Objekt nachempfunden wären. Es ist die Schwere und Verbreitung dieser Fehler, die meiner Meinung nach das schwerwiegendste Negativ für ein ADM sind.

Ich halte es für wichtig, hier darauf hinzuweisen, dass sich hier eine funktionale Lösung und die prozeduralen Lösungen eines ADM erheblich unterscheiden und dass alle Ähnlichkeiten, die andere möglicherweise mit den Oberflächenähnlichkeiten zwischen einem ADM und einer funktionalen Lösung gezogen haben, zufällig sind.

2) Code aufblähen

Ich schätze, dass die in einem ADM erzeugte Codemenge das 5- bis 10-fache der Menge beträgt, die eine OOP / RDM-Lösung erzeugen würde. Dies ist darauf zurückzuführen, dass möglicherweise 50% Code-Wiederholungen, 30% Kesselplatten-Codes und 20% Probleme oder Probleme lösen, die sich aus dem Fehlen eines RDM ergeben.

3) Schlechtes Verständnis der Domänenprobleme

Ein ADM und ein schlechtes Verständnis der Domänenprobleme gehen etwas Hand in Hand. Es entstehen naive Lösungen, Anforderungen werden aufgrund der Schwierigkeit, sie mit dem vorhandenen DM zu unterstützen, nur unzureichend berücksichtigt, und das ADM wird aufgrund der längeren Entwicklungszeiten und der mangelnden Flexibilität zu einem erheblichen Hindernis für Unternehmensinnovationen.

4) Wartungsschwierigkeiten

Ein gewisses Maß an Genauigkeit ist erforderlich, um sicherzustellen, dass ein Domänenkonzept an allen Stellen geändert wird, an denen es zum Ausdruck gebracht wird, da das Konzept möglicherweise nicht nur eine Neuimplementierung durch Kopieren und Einfügen ist. Dies führt häufig dazu, dass dieselben Fehler mehrfach untersucht und behoben werden.

5) Erhöhte Schwierigkeit beim Einsteigen

Ich denke, einer der Vorteile eines RDM ist der Zusammenhalt von Konzepten, die ein schnelleres Verständnis der Domäne ermöglichen. Mit einem ADM können Konzepte fragmentiert und unklar sein, was für neue Entwickler schwieriger zu erwerben ist.

Ich war auch versucht, die Betriebsunterstützungskosten für ein ADM höher einzubeziehen als für ein RDM, aber dies würde von einer Reihe von Faktoren abhängen.

Wie andere bereits betont haben, sollten Sie sich bei DDD (Greg Evans, Vince Vaughn und Scott Millett) nach den Vorteilen eines RDM umsehen.


Ist Greg Evans das geheime Kind von Greg Young und Eric Evans? Ich wusste auch nicht, dass Vince Vaughn DDD-Bücher schreibt, aber vielleicht hat Vaughn Vernon auch angefangen zu schauspielern :)
knittl

2

Es ist der gleiche Profi wie bei den meisten Anti-Patterns: Es ermöglicht Ihnen, viele Leute für eine lange Zeit zu beschäftigen. Da Manager tendenziell mehr bezahlt werden, wenn sie mehr Mitarbeiter verwalten, besteht ein starker Anreiz, sich nicht zu verbessern.


1
Nein, echte Erfahrung
Stephan Eggermont

7
Lassen Sie es mich in diesem Fall umformulieren. ^^^ Rein anekdotische Beweise, die verwendet werden, um auf einen allgemein klingenden Satz zu schließen.
Luis.espinal

Wenn wir genügend anekdotische Beweise finden, können wir möglicherweise ein Muster ableiten. Und dieses Muster ist bekannt und in der Literatur zum Änderungsmanagement hinreichend beschrieben.
Stephan Eggermont

4
"Und dieses Muster ist bekannt und in der Literatur zum Änderungsmanagement hinreichend beschrieben." - Zitate bitte. Genauer gesagt bedeutet Korrelation keine Kausalität . Das heißt, nur weil Sie sehen, wie Menschen aufgrund vorhandener Anti-Muster (speziell Softwaremuster und anämische Domänenmodelle auf den Punkt gebracht) ihre Räder in Bürokratie drehen , bedeutet dies nicht, dass das letztere existiert, um das erstere zu rechtfertigen was du gerade getrompft hast. Rhetorische Parolen sind schlechte Karikaturen zur Erklärung komplexer Themen. Korrelation bedeutet
Luis.espinal

4
Vielleicht möchten Sie Quality Software Management von Gerald M. Weinberg lesen, insbesondere Band 4. Und ich behaupte nur eine mögliche Ursache für den Fortbestand, nicht für sein Auftreten. Das Peter-Prinzip bietet eine angemessene Alternative.
Stephan Eggermont

2

In Übereinstimmung mit der Antwort von Eric P und dem, was einige andere oben geschrieben haben, scheint der Hauptnachteil eines ADM der Verlust von OOD zu sein, insbesondere das Zusammenhalten der Logik und der Daten eines Domänenkonzepts, so dass die Implementierungsdetails währenddessen verborgen bleiben Die API kann reichhaltig sein.

Eric weist darauf hin, dass es häufig Informationen außerhalb einer Domänenklasse gibt, die für die Logik des Handelns auf diese Klasse erforderlich sind, z. B. die Überprüfung eines Inventars vor dem Hinzufügen eines Artikels zu einer Bestellung. Ich frage mich jedoch, ob die Antwort eine Service-Schicht ist, die diese übergreifende Logik enthält, oder ob sie im Rahmen des Objektdesigns besser gehandhabt wird. Jemand muss etwas über das Inventarobjekt, das Produktobjekt und das Bestellobjekt wissen. Vielleicht ist es einfach ein OrderSystem-Objekt, das ein Inventarmitglied, eine Liste von Bestellungen usw. hat. Dies sieht nicht sehr anders aus als ein Service, aber ich denke, es ist konzeptionell kohärenter.

Oder sehen Sie es so: Sie können einen Benutzer mit einem internen Guthaben haben, und jedes Mal, wenn User.addItemToOrder (Artikel) aufgerufen wird, wird der Preis des Artikels abgerufen und das Guthaben überprüft, bevor es hinzugefügt wird usw. Dies scheint eine vernünftige OO zu sein Design. Ich bin mir nicht sicher, was genau verloren geht, wenn ich das durch Service.addItemToUserOrder (Benutzer, Element) ersetze, aber ich bin mir auch nicht sicher, was gewonnen wurde. Ich denke, ein Verlust wäre die zusätzliche Codeebene sowie der klobigere Schreibstil und die erzwungene Unkenntnis des zugrunde liegenden Domänenmodells.


1

Es sollte beachtet werden, dass die Kapselung und Konsolidierung von Schnittstellenpunkten, die durch ein gut gestaltetes Objektmodell für die Nachrichtenübermittlung bereitgestellt wird, mit zunehmender Komplexität und Granularität der Variationen die Sicherheit und das Verwalten von kritischem Code ohne umfassendes Refactoring wesentlich sicherer macht.

Die vom ADM erstellten Serviceschichten sind zwar sicherlich einfacher zu implementieren (da sie relativ wenig Überlegungen erfordern und über viele dezentrale Schnittstellenpunkte verfügen), werden jedoch wahrscheinlich später Probleme verursachen, wenn es an der Zeit ist, ein lebendes und wachsendes System zu ändern.

Ich könnte auch hinzufügen, dass nicht in allen Fällen überhaupt ein Domänenmodell erforderlich ist (geschweige denn das ADM-Modell). Manchmal ist es besser, einen prozeduraleren / funktionaleren Stil der Aufgabe zu verwenden, der datengesteuert ist und nicht von anwendungsweiten Logik- / Geschäftsregeln abhängt.

Wenn Sie versuchen, die Vor- und Nachteile für eine ganze App zu bestimmen, ist es meiner Meinung nach wichtig, zuerst zu entwerfen, wie jede für Ihre bestimmte Anwendung aussehen könnte, bevor Sie überhaupt mit dem Schreiben einer einzelnen Codezeile beginnen. Wenn Sie Ihre Anwendung in beiden Stilen CRC- oder drahtgebunden haben, treten Sie einen Schritt zurück und entscheiden Sie, welche sinnvoller ist und besser zur Anwendung passt.

Überlegen Sie auch, welche leichter zu warten ist ...


1

Es gibt eine bessere Vorhersagbarkeit. Manager mögen das, besonders wenn das Projekt Zeit und Material bezahlt. Jede Änderung bedeutet viel Arbeit, so dass schwierige Arbeit hinter viel sich wiederholender Arbeit verborgen sein kann. In einem gut konzipierten DRY-System ist die Vorhersagbarkeit sehr schlecht, da Sie ständig neue Dinge tun.


1

Nachdem ich Eric Evans Buch über domänengesteuertes Design zum ersten Mal gelesen hatte, verstand ich nicht wirklich, dass es sich nicht nur um eine Reihe taktischer Muster für das Entwerfen guter Domänenmodellklassen handelt.

Nachdem ich mehr über das Thema gelernt und auch die strategischen Muster verwendet hatte, begann ich endlich zu verstehen, dass es zunächst darum geht, ein tiefes Verständnis für die Geschäftsprobleme zu erlangen, die Sie zu lösen versuchen.

Und erst danach können Sie entscheiden, welche Teile des Systems für die Anwendung taktischer Muster wie Aggregate, Entitäten , Repositorys usw. zusammen mit sogenannten Rich- Domain-Modellen (im Gegensatz zu anämischen ) geeignet sind . Um von diesen Mustern zu profitieren, muss die Geschäftslogik jedoch ausreichend komplex sein für diesen Teil des Systems sein.

Wenn es darum geht, die Lösung des vorliegenden Problems zu implementieren, sollte zunächst festgestellt werden, ob dieses spezifische Problem besser mit einem CRUD- basierten Ansatz oder einer Investition in ein umfangreiches Domänenmodell zusammen mit den genannten taktischen Mustern angegangen werden kann.

Wenn CRUD sinnvoller ist, z. B. wenn es keine komplexe Geschäftslogik gibt und der größte Teil der Logik sich mit der Transformation, Übertragung und Speicherung von Daten befasst, kann die Implementierung eines Domänenmodells ein unnötiger Overkill sein. Dies bedeutet nicht, dass nicht viel Arbeit zu erledigen ist, sondern nur, dass nicht die Geschäftsregeln den größten Implementierungsaufwand verursachen. Aber in diesem Fall gibt es nicht so etwas wie ein anämisches Domänenmodell , einfach weil es kein Domain - Modell überhaupt ist . Was Sie eher sehen werden, sind solche Dinge wie DTOs (Data Transfer Objects) oder DAOs(Datenzugriffsobjekte) und Serviceklassen, die die Daten verarbeiten. Und die entsprechenden Operationen befassen sich in hohem Maße mit der Transformation von Daten von einer Darstellung in eine andere und dem Verschieben von Daten mit sehr wenig oder fast keiner Geschäftslogik.

Wenn Sie festgestellt haben, dass es eine Menge komplexer Geschäftslogik gibt, die sich auch im Laufe der Zeit ändern wird, als wenn Sie in ein Domain-Modell investieren meiner Erfahrung nach eine gute Idee. Der Grund dafür ist, dass es einfacher ist, die Geschäftsperspektive über Code darzustellen und die entsprechenden Vorgänge zu verstehen, die die Geschäftsdomäne und ihre Regeln widerspiegeln. Dies bedeutet nicht, dass in jedem Anwendungsfall Domänenmodellklassen vorhanden sein müssen. Wenn zum Beispiel kein Zustand vorhanden ist, der mutiert und beibehalten werden soll, können auch nur Domänendienste, die die Domänenlogik enthalten, eher wie reine Funktionen implementiert werden.

Wenn es jedoch auch einen zu mutierenden und fortbestehenden Zustand gibt, der auch im Geschäftsbereich Zweck und Bedeutung hat, sollten der Zustand und das Verhalten, das diesen Zustand ändert, gekapselt werden . Damit kann niemand die Geschäftsregeln so einfach umgehen und dadurch zu ungültigen Zuständen und schwerwiegenden Fehlern führen. Sogenannte anämische Domänenmodelle sind häufig Ursachen für solche Probleme . Dies ist häufig der Fall, wenn Sie Code sehen, in dem verschiedene Komponenten mit derselben "anämischen" Domänenmodellklasse arbeiten und einen Teil ihres Status überprüfen und einen Teil ihres Status ändern, ohne sich um die Gesamtinvarianten dieser Geschäftseinheit zu kümmern oder diese zu kennen. Es ist nicht notwendig, dies als Anti-Muster zu bezeichnen, aber es ist wichtig, das zu verstehenSie verlieren viele Vorteile von Rich Domain-Modellenin einem DDD-basierten Ansatz zusammen mit den genannten Problemen. Wenn Sie ein Domänenmodell verwenden, bei dem das Verhalten und seine Daten in derselben Klasse platziert sind, können auch viele verschiedene "Clients" Operationen dieser Klasse aufrufen. Sie müssen jedoch nicht darauf achten, dass die Geschäftsinvarianten der Geschäftseinheit eingehalten werden Die Domain-Modellklasse kümmert sich immer darum und kann den "Client" auch über ungültige Operationen informieren oder sogar Ausnahmen als Sicherheitsnetz auslösen.

Unter dem Strich halte ich es daher für wichtig, Datenstruktur-ähnliche Klassen (wie DTOs oder DAOs) nicht mit anämischen Domänenmodellklassen zu verwechseln . Bei einem sorgfältig und absichtlich ausgewählten CRUD-basierten Ansatz ist es nicht vorteilhaft, ein Domänenmodell zu verwenden, da die Geschäftslogik zu komplex ist.

Mit dem anämischen Domänenmodell würde ich auf Code verweisen, aus dem hervorgeht, dass es viele komplexe Geschäftslogiken und Geschäftsregeln gibt, die auf verschiedene Komponenten verteilt sind und eher in der Nähe der Daten liegen sollten, die diese Logik ändert.

Es gibt noch eine weitere Lektion, die ich auf diesem Weg gelernt habe: Wenn Sie versuchen, dieselbe Geschäftssprache (auch als Ubiquituous Language bezeichnet ) in Ihrem Code zu verwenden, die die Steakhalter in ihrem täglichen Arbeitsleben verwenden, gewinnen Sie bereits so viele Vorteile hinsichtlich des Verständnisses von die Geschäftsdomäne und die Verbesserung der Lesbarkeit Ihres Codes, die Ihnen so viel hilft, egal ob Sie einen CRUD-basierten oder einen Domänenmodell-basierten Ansatz verwenden.


0

Um Michaels Antwort zu erweitern, hätte ich gedacht, dass es (ziemlich) klar ist, wohin dieser Code gehen soll: in einen dedizierten Mediator, der die Interaktion zwischen der Bestellung und dem Inventar übernimmt.

Aus meiner Sicht ist das Wichtigste an der Domain, dass sie das einfache Testverhalten der isInThisState()Methoden usw. enthalten muss. Nach meiner Erfahrung sind diese in den meisten Unternehmen auch über die Service-Tränen (sic :) verteilt und werden entweder kopiert oder endlos neu geschrieben. All dies verstößt gegen die Standardkonhäsionsregeln.

Meiner Ansicht nach sollte der Ansatz sein Ziel für eine DM , die so viel von dem biz beahaviour hält als praktisch, leg den Rest in eindeutig gekennzeichneten Bereichen (dh nicht in den Diensten)


Die Sache mit einem Mediator ist, dass es sowieso kaum einen Unterschied zwischen dieser und der prozeduralen Programmierung gibt. Sie gruppieren nur einige Funktionen, die zu keinem der beiden Objekte gehören. Die Tatsache, dass Sie sie in einem anderen Objekt gruppieren, macht keinen großen Unterschied.
Rob Grant

0

Mein Team persönlich bevorzugt das ADM. Wir haben eine Reihe von Geschäftsobjekten, die bestimmte Teile unserer Domäne darstellen. Wir verwenden Dienste, um diese Objekte in der Datenbank zu speichern. Unsere Geschäftsobjekte verfügen zwar über Methoden, diese Methoden manipulieren jedoch nur den internen Status.

Der Vorteil für uns bei der Verwendung von ADM gegenüber RDM zeigt sich darin, wie wir die Objekte in db beibehalten. Entwickler, die an unseren Legacy-Codesystemen arbeiten, können unsere Geschäftsobjekte (aus dem neuen System) verwenden und weiterhin ihre aktuelle Datenzugriffsschicht verwenden, um diese Objekte in der Datenbank zu speichern. Die Verwendung des RDM würde Entwickler unseres Legacy-Systems dazu zwingen, Repository-Objekte in unser Geschäftsmodell einzufügen ... was nicht mit ihrer aktuellen Datenzugriffsschicht übereinstimmt.


-15

Ein anämisches Domänenmodell ist ein Anti-Muster. Anti-Patterns haben keine Profis.


10
Ich stimme dir nicht zu. Die meisten Antipatterns haben Eckfälle, in denen sie eine bessere Lösung sind als andere Alternativen.
Bill Karwin

19
Anti-Patterns haben Profis. Deshalb benutzen die Leute sie, obwohl sie normalerweise schlechte Ideen sind.
Kristopher Johnson

6
Zu papageien, dass etwas ein Anti-Muster ist, wenn es nur eine Meinung ist (auch wenn es etwas von Fowlers Kaliber ist), ist keine gültige Form der Antwort.
Luis.espinal

@luis: Genau das, was ich schreiben wollte, bevor ich dich kommentieren sah. Darüber hinaus gibt es Werkzeuge, um einen Zweck zu erfüllen. Wenn Fowler es nicht OO nennen will, ist das in Ordnung. Dies weist jedoch nicht automatisch auf eine schlechte Lösung / Architektur / etc. Hin.
JensG
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.