OO-Sprachen können anstelle von einfachen Sprachen verwendet werden, um eine direkte Verbindung mit einer Maschine herzustellen. C ++ Sicher, aber auch für C # gibt es Adapter und dergleichen. Das Schreiben von Code zur Steuerung mechanischer Teile und die minutiöse Steuerung des Speichers sollten jedoch so niedrig wie möglich gehalten werden. Aber wenn diese Frage mit aktueller objektorientierter Software wie Line Of Business, Webanwendungen, IOT, Webdiensten und den meisten Massenanwendungen zusammenhängt, dann ...
Antworten Sie gegebenenfalls
Leser können versuchen, mit einer serviceorientierten Architektur (SOA) zu arbeiten. Das heißt, DDD, N-Layered, N-Tiered, Hexagonal, was auch immer. Ich habe noch keine Large Business-Anwendung gesehen, die "traditionelle" OO (Active-Record oder Rich-Models) effizient einsetzt, wie es in den 70er und 80er Jahren im letzten Jahrzehnt beschrieben wurde. (Siehe Anmerkung 1)
Der Fehler liegt nicht am OP, aber es gibt ein paar Probleme mit der Frage.
Das Beispiel, das Sie zur Verfügung stellen, soll lediglich den Polymorphismus demonstrieren, es handelt sich nicht um Produktionscode. Manchmal werden genau solche Beispiele wörtlich genommen.
In FP und SOA werden Daten von Business Logic getrennt. Das heißt, Daten und Logik gehören nicht zusammen. Die Logik bezieht sich auf Dienste, und Daten (Domänenmodelle) weisen kein polymorphes Verhalten auf (siehe Hinweis 2).
Dienste und Funktionen können polymorph sein. In FP übergeben Sie häufig Funktionen als Parameter anstelle von Werten an andere Funktionen. Sie können dasselbe in OO Languages mit Typen wie Callable oder Func tun, aber es wird nicht zügellos ausgeführt (siehe Hinweis 3). In FP und SOA sind Ihre Modelle nicht polymorph, sondern nur Ihre Dienste / Funktionen. (Siehe Anmerkung 4)
In diesem Beispiel gibt es einen schlechten Fall der Hardcodierung. Ich spreche nicht nur von der roten Schnur "Hundebellen". Ich spreche auch über das CatModel und DogModel selbst. Was passiert, wenn Sie ein Schaf hinzufügen möchten? Sie müssen in Ihren Code gehen und neuen Code erstellen? Warum? Im Produktionscode würde ich eher nur ein AnimalModel mit seinen Eigenschaften sehen. Im schlimmsten Fall ein AmphibienModell und ein GeflügelModell, wenn ihre Eigenschaften und Handhabung so unterschiedlich sind.
Dies ist, was ich in einer aktuellen "OO" -Sprache erwarten würde:
public class Animal
{
public int AnimalID { get; set; }
public int LegCount { get; set; }
public string Name { get; set; }
public string WhatISay { get; set; }
}
public class AnimalService : IManageAnimals
{
private IPersistAnimals _animalRepo;
public AnimalService(IPersistAnimals animalRepo) { _animalRepo = animalRepo; }
public List<Animal> GetAnimals() => _animalRepo.GetAnimals();
public string WhatDoISay(Animal animal)
{
if (!string.IsNullOrWhiteSpace(animal.WhatISay))
return animal.WhatISay;
return _animalRepo.GetAnimalNoise(animal.AnimalID);
}
}
Wie wechselt man von Klassen in OO zu funktionaler Programmierung? Wie andere gesagt haben; Sie können, aber Sie nicht wirklich. Der Sinn des Obenstehenden ist zu demonstrieren, dass Sie nicht einmal Klassen (im herkömmlichen Sinne der Welt) verwenden sollten, wenn Sie Java und C # ausführen. Sobald Sie Code in einer serviceorientierten Architektur (DDD, Layered, Tiered, Hexagonal, was auch immer) schreiben, sind Sie funktional einen Schritt näher, da Sie Ihre Daten (Domänenmodelle) von Ihren logischen Funktionen (Services) trennen.
OO Language ist FP einen Schritt näher gekommen
Sie können sogar noch etwas weiter gehen und Ihre SOA-Services in zwei Typen aufteilen.
Optionale Klasse Typ 1 : Common Interface-Implementing Services für Einstiegspunkte. Dies wären "unreine" Einstiegspunkte, die andere Funktionen "rein" oder "unrein" aufrufen können. Dies können Ihre Einstiegspunkte aus einer RESTful-API sein.
Optionale Klasse Typ 2 : Pure Business Logic Services. Dies sind statische Klassen mit "reiner" Funktionalität. In FP bedeutet "Pure", dass es keine Nebenwirkungen gibt. Es wird nirgendwo explizit der Status oder die Persistenz festgelegt. (Siehe Anmerkung 5)
Wenn Sie also an Klassen in objektorientierten Sprachen denken, die in einer serviceorientierten Architektur verwendet werden, kommt dies nicht nur Ihrem OO-Code zugute, sondern lässt die funktionale Programmierung auch leicht verständlich erscheinen.
Anmerkungen
Hinweis 1 : Das ursprüngliche objektorientierte Design "Rich" oder "Active-Record" ist noch vorhanden. Früher, als die Leute es vor einem Jahrzehnt oder länger "richtig machten", gab es eine Menge Legacy-Code wie diesen. Das letzte Mal, als ich sah, dass diese Art von Code (richtig gemacht) aus einem Videospiel stammt, Codebase in C ++, in dem sie den Speicher präzise kontrollierten und nur über sehr begrenzten Speicherplatz verfügten. Ganz zu schweigen von FP und serviceorientierten Architekturen, die keine Hardware in Betracht ziehen sollten. Sie legen jedoch Wert auf die Fähigkeit, sich ständig zu ändern, gewartet zu werden, variable Datengrößen zu haben und andere Aspekte. In Videospielen und Computer-KI steuern Sie die Signale und Daten sehr genau.
Hinweis 2 : Domänenmodelle weisen weder ein polymorphes Verhalten noch externe Abhängigkeiten auf. Sie sind "isoliert". Das bedeutet nicht, dass sie zu 100% anämisch sein müssen. Sie können eine Menge Logik in Bezug auf ihre Konstruktion und veränderbare Eigenschaftsänderung haben, wenn dies zutrifft. Siehe DDD "Value Objects" und Entities von Eric Evans und Mark Seemann.
Anmerkung 3 : Linq und Lambda sind sehr verbreitet. Wenn ein Benutzer eine neue Funktion erstellt, verwendet er selten Func oder Callable als Parameter, während es in FP seltsam wäre, eine App ohne Funktionen zu sehen, die diesem Muster folgen.
Anmerkung 4 : Polymorphismus nicht mit Vererbung verwechseln. Ein CatModel erbt möglicherweise AnimalBase, um zu bestimmen, welche Eigenschaften ein Tier normalerweise hat. Aber wie ich zeige, sind Modelle wie dieses ein Code-Geruch . Wenn Sie dieses Muster sehen, können Sie es aufschlüsseln und in Daten umwandeln.
Anmerkung 5 : Reine Funktionen können Funktionen als Parameter akzeptieren. Die eingehende Funktion ist möglicherweise unrein, aber möglicherweise rein. Zu Testzwecken wäre es immer rein. Aber in der Produktion kann es, obwohl es als rein behandelt wird, Nebenwirkungen enthalten. Das ändert nichts an der Tatsache, dass die reine Funktion rein ist. Die Parameterfunktion kann jedoch unrein sein. Nicht verwirrend! : D