it-swarm.com.de

Warum wird ein anämisches Domänenmodell in C # / OOP als schlecht angesehen, in F # / FP jedoch als sehr wichtig?

In einem Blog-Beitrag auf F # für Spaß und Gewinn heißt es:

In einem funktionalen Design ist es sehr wichtig, Verhalten von Daten zu trennen. Die Datentypen sind einfach und "dumm". Und dann haben Sie separat eine Reihe von Funktionen, die auf diese Datentypen wirken.

Dies ist das genaue Gegenteil eines objektorientierten Entwurfs, bei dem Verhalten und Daten kombiniert werden sollen. Denn genau das ist eine Klasse. In einem wirklich objektorientierten Design sollten Sie eigentlich nur Verhalten haben - die Daten sind privat und können nur über Methoden abgerufen werden.

Tatsächlich wird in OOD ein unzureichendes Verhalten in Bezug auf einen Datentyp als schlechte Sache angesehen und hat sogar einen Namen: " anämisches Domänenmodell ".

Angesichts der Tatsache, dass wir in C # weiterhin Kredite von F # aufnehmen und versuchen, mehr Code im funktionalen Stil zu schreiben; Wie kommt es, dass wir uns nicht die Idee leihen, Daten/Verhalten zu trennen, und es sogar für schlecht halten? Ist es einfach so, dass die Definition mit OOP nicht übereinstimmt, oder gibt es einen konkreten Grund dafür, dass es in C # schlecht ist, der aus irgendeinem Grund in F # nicht gilt (und tatsächlich umgekehrt ist)?

(Hinweis: Ich bin speziell an den Unterschieden in C #/F # interessiert, die die Meinung über das Gute/Schlechte ändern könnten, und nicht an Personen, die mit beiden Meinungen im Blog-Beitrag nicht einverstanden sind.).

49
Danny Tuppeny

Der Hauptgrund FP zielt darauf ab und C # OOP nicht) ist, dass in FP der Fokus auf referenzieller Transparenz liegt; Das heißt, Daten gehen in eine Funktion und Daten kommen heraus, aber die Originaldaten werden nicht geändert.

In C # OOP gibt es ein Konzept der Delegation von Verantwortung, bei dem Sie die Verwaltung eines Objekts an dieses delegieren und daher möchten, dass es seine eigenen Interna ändert.

In FP) möchten Sie niemals die Werte in einem Objekt ändern, daher ist es nicht sinnvoll, Ihre Funktionen in Ihr Objekt einzubetten.

Weiter in FP Sie haben einen höherwertigen Polymorphismus, wodurch Ihre Funktionen weitaus allgemeiner sind als C # OOP erlaubt. Auf diese Weise können Sie eine Funktion schreiben, für die funktioniert Jedes a, und daher ist es nicht sinnvoll, es in einen Datenblock einzubetten. Dies würde die Methode eng koppeln, sodass sie nur mit dieser bestimmten Art funktioniert von a. Ein solches Verhalten ist in C # OOP] gut und üblich, da Sie ohnehin nicht in der Lage sind, Funktionen so allgemein zu abstrahieren. aber in FP ist es ein Kompromiss.

Das größte Problem, das ich in anämischen Domänenmodellen in C # OOP) gesehen habe, ist, dass Sie doppelten Code erhalten, weil Sie DTO x haben, und 4 verschiedene Funktionen, die Aktivität f an DTO x übertragen, weil 4 Verschiedene Personen haben die andere Implementierung nicht gesehen. Wenn Sie die Methode direkt auf DTO x setzen, sehen diese 4 Personen alle die Implementierung von f und verwenden sie erneut.

Anämische Datenmodelle in C # OOP behindern die Wiederverwendung von Code, dies ist jedoch in FP nicht der Fall), da eine einzelne Funktion auf so viele verschiedene Typen verallgemeinert ist, dass Sie Holen Sie sich eine größere Wiederverwendung von Code, da diese Funktion in so viel mehr Szenarien verwendet werden kann als eine Funktion, die Sie für ein einzelnes DTO in C # schreiben würden.


Wie in den Kommentaren ausgeführt hat, ist die Typinferenz einer der Vorteile FP ist darauf angewiesen, solch einen signifikanten Polymorphismus zuzulassen, und insbesondere können Sie dies zurückverfolgen auf das Hindley Milner Typsystem mit Algorithmus W Typinferenz, eine solche Typinferenz im C # OOP Typ System wurde vermieden, weil die Kompilierungszeit bei Einschränkung -basierte Inferenz wird hinzugefügt, wird aufgrund der erforderlichen umfassenden Suche extrem lang. Details hier: https://stackoverflow.com/questions/3968834/generics-why-cant-the-compiler-infer-the -Typ-Argumente-in-diesem-Fall

39
Jimmy Hoffa

Warum wird ein anämisches Domänenmodell in C #/OOP als schlecht angesehen, in F #/FP jedoch als sehr wichtig?

Ihre Frage hat ein großes Problem, das den Nutzen der Antworten einschränkt, die Sie erhalten: Sie implizieren/nehmen an, dass F # und FP ähnlich sind. FP ist a Riesige Sprachfamilie, einschließlich symbolischer Umschreibung, dynamisch und statisch. Selbst unter statisch typisierten FP Sprachen) gibt es viele verschiedene Technologien zum Ausdrücken von Domänenmodellen wie Modulen höherer Ordnung in OCaml und SML (das existieren nicht in F #). F # ist eine dieser funktionalen Sprachen, aber es ist besonders bemerkenswert, dass es schlank ist und insbesondere weder Module höherer Ordnung noch Typen höherer Art bietet.

Tatsächlich konnte ich Ihnen nicht sagen, wie Domain-Modelle in FP ausgedrückt werden. Die andere Antwort hier spricht sehr spezifisch darüber, wie es in Haskell gemacht wird und ist überhaupt nicht anwendbar auf LISP (die Mutter aller FP Sprachen), die ML-Sprachfamilie oder andere funktionale Sprachen .

wie kommt es, dass wir uns nicht die Idee leihen, Daten/Verhalten zu trennen, und es sogar für schlecht halten?

Generika können als Mittel zur Trennung von Daten und Verhalten angesehen werden. Generika aus der ML-Familie der funktionalen Programmiersprachen sind nicht Teil von OOP. C # hat natürlich Generika. Man könnte also argumentieren, dass C # sich langsam die Idee leiht, Daten und Verhalten zu trennen.

Ist es einfach so, dass die Definition nicht zu OOP passt?

Ich glaube, OOP basiert auf einer grundlegend anderen Prämisse und bietet Ihnen folglich nicht die Werkzeuge, die Sie zum Trennen von Daten und Verhalten benötigen. Für alle praktischen Zwecke benötigen Sie Produkt- und Summen-Datentypen und den Versand In ML bedeutet dies Vereinigungs- und Datensatztypen sowie Mustervergleich.

Check out das Beispiel, das ich hier gegeben habe .

oder gibt es einen konkreten Grund dafür, dass es in C # schlecht ist, der aus irgendeinem Grund in F # nicht gilt (und tatsächlich umgekehrt ist)?

Seien Sie vorsichtig beim Springen von OOP zu C #. C # ist bei weitem nicht so puritanisch wie OOP wie andere Sprachen. Das .NET Framework ist jetzt voll von generischen, statischen Elementen Methoden und sogar Lambdas.

(Hinweis: Ich bin speziell an den Unterschieden in C #/F # interessiert, die die Meinung über das Gute/Schlechte ändern könnten, und nicht an Personen, die mit beiden Meinungen im Blog-Beitrag nicht einverstanden sind.).

Das Fehlen von Vereinigungstypen und Musterübereinstimmungen in C # macht dies fast unmöglich. Wenn Sie nur einen Hammer haben, sieht alles aus wie ein Nagel ...

6
Jon Harrop