Objektorientierung ist besonders deshalb von großem Wert, weil solche Szenarien auftreten und Sie Werkzeuge zum vernünftigen Entwerfen von Abstraktionen erhalten, mit denen Sie die Komplexität zusammenfassen können.
Die eigentliche Frage ist hier, wo Sie diese Komplexität zusammenfassen.
Lassen Sie mich einen Moment zurücktreten und über die Komplexität sprechen, auf die ich mich hier beziehe. Ihr Problem (so wie ich es verstehe; korrigieren Sie mich, wenn ich falsch liege) ist ein Persistenzmodell, das für die Aufgaben, die Sie mit den Daten ausführen müssen, nicht effektiv verwendbar ist. Es kann für andere Aufgaben effektiv und verwendbar sein, aber nicht für Ihre Aufgaben.
Was machen wir also, wenn wir Daten haben, die kein gutes Modell für unsere Mittel darstellen?
Übersetzen. Du bist das Einzige tun kannst . Diese Übersetzung ist die 'Komplexität', auf die ich mich oben beziehe. Da wir nun akzeptieren, dass wir das Modell übersetzen, müssen wir uns für einige Faktoren entscheiden.
Müssen wir beide Richtungen übersetzen? Werden beide Richtungen gleich übersetzt, wie in:
(Tbl A, Tbl B) -> Obj X (lesen)
Obj X -> (Tbl A, Tbl B) (schreiben)
oder stellen Einfüge- / Aktualisierungs- / Löschaktivitäten einen anderen Objekttyp dar, sodass Sie Daten als Obj X lesen, aber Daten aus Obj Y eingefügt / aktualisiert werden? Welche dieser beiden Möglichkeiten Sie nutzen möchten oder ob keine Aktualisierung / Einfügung / Löschung möglich ist, ist ein wichtiger Faktor für den Ort, an dem Sie die Übersetzung einfügen möchten.
Wo übersetzen Sie?
Zurück zu der ersten Aussage, die ich in dieser Antwort gemacht habe; OO ermöglicht es Ihnen , zu verkapseln Komplexität und was ich hier beziehen , ist die Tatsache , dass nicht nur sollten Sie, aber Sie müssen diese Komplexität kapseln , wenn Sie möchten, um sicherzustellen , nicht durchsickern und sickern in den gesamten Code. Gleichzeitig ist es wichtig zu erkennen, dass Sie keine haben können perfekte Abstraktion haben können. Sorgen Sie sich also weniger darum als darum, eine sehr effektive und verwendbare zu haben.
Wieder jetzt; Ihr Problem ist: Wo setzen Sie diese Komplexität ein? Nun, Sie haben die Wahl.
Sie können dies mit gespeicherten Prozeduren in der Datenbank tun . Dies hat den Nachteil, dass es mit ORMs oft nicht sehr gut funktioniert, aber das stimmt nicht immer. Gespeicherte Prozeduren bieten einige Vorteile, darunter häufig die Leistung. Gespeicherte Prozeduren können jedoch eine Menge Wartung erfordern, aber es liegt an Ihnen, Ihr spezielles Szenario zu analysieren und zu sagen, ob die Wartung mehr oder weniger als andere Entscheidungen sein wird. Ich persönlich kenne mich mit gespeicherten Prozeduren sehr gut aus, und als solche reduziert diese Tatsache des verfügbaren Talents den Overhead. nie unterschätzen den Wert von Entscheidungen basierend auf was Sie tun wissen. Manchmal ist die suboptimale Lösung optimaler als die richtige, weil Sie oder Ihr Team wissen, wie man sie besser erstellt und verwaltet als die optimale Lösung.
Eine weitere Option in der Datenbank sind Ansichten. Abhängig von Ihrem Datenbankserver können diese sehr optimal oder suboptimal oder gar nicht effektiv sein. Einer der Nachteile kann die Abfragezeit sein, je nachdem, welche Indizierungsoptionen in Ihrer Datenbank verfügbar sind. Ansichten werden zu einer noch besseren Wahl, wenn Sie keine Datenänderungen vornehmen müssen (Einfügen / Aktualisieren / Löschen).
Wenn Sie über die Datenbank hinausgehen, haben Sie die alte Bereitschaft, das Repository-Muster zu verwenden. Dies ist ein bewährter Ansatz, der sehr effektiv sein kann. Zu den Nachteilen gehört in der Regel die Kesselplatte, aber gut faktorisierte Repositorys können eine gewisse Menge davon vermeiden. Selbst wenn dies zu unglücklichen Mengen an Kesselplatte führt, handelt es sich bei den Repositorys in der Regel um einfachen Code, der einfach zu verstehen und zu warten ist sowie eine gute API darstellt /Abstraktion. Repositorys können auch für ihre Unit-Testbarkeit gut sein, die Sie durch datenbankinterne Optionen verlieren.
Es gibt Tools wie Auto-Mapper , die die Verwendung eines ORM plausibel machen, um die Übersetzung zwischen Datenbankmodellen von Orm in verwendbare Modelle zu ermöglichen. Einige dieser Tools können jedoch schwierig sein, magisches Verhalten beizubehalten / zu verstehen. Sie erstellen jedoch ein Minimum an Overhead-Code, was zu weniger Wartungsaufwand führt, wenn sie gut verstanden werden.
Als nächstes entfernen Sie sich immer weiter von der Datenbank , was bedeutet, dass es größere Mengen an Code geben wird, die sich mit dem nicht übersetzten Persistenzmodell befassen werden, was wirklich unangenehm sein wird. In diesen Szenarien geht es darum, die Übersetzungsebene in Ihre Benutzeroberfläche einzufügen, wie es sich anhört, als ob Sie dies jetzt tun. Dies ist im Allgemeinen eine sehr schlechte Idee und verfällt mit der Zeit schrecklich.
Jetzt fangen wir an, verrückt zu reden .
Das Object
ist nicht die einzige Abstraktion, die existiert. Im Laufe der vielen Jahre, in denen Informatik studiert wurde, und noch vor dieser Zeit nach dem Studium der Mathematik, hat sich eine Fülle von Abstraktionen entwickelt. Wenn wir kreativ werden wollen, lassen Sie uns über bekannte verfügbare Abstraktionen sprechen, die untersucht wurden.
Da ist das Schauspielermodell.Dies ist ein interessanter Ansatz, da Sie lediglich Nachrichten an anderen Code senden müssen, um die gesamte Arbeit effektiv an diesen anderen Code zu delegieren. Dadurch wird die Komplexität sehr effektiv von Ihrem gesamten Code getrennt. Dies könnte insofern funktionieren, als Sie eine Nachricht an einen Schauspieler mit der Aufschrift "Ich muss Obj X an Y senden" senden und an Position Y ein Behälter auf eine Antwort wartet, der dann Obj X verarbeitet. Sie können sogar eine Nachricht senden, die anweist "Ich muss Obj X und Berechnung Y, Z erledigen" und dann müssen Sie nicht einmal warten; Die Übersetzung erfolgt auf der anderen Seite des Nachrichtendurchlaufs und Sie können einfach weitermachen, wenn Sie das Ergebnis nicht lesen müssen. Dies kann ein geringfügiger Missbrauch des Darstellermodells für Ihre Zwecke sein, aber alles hängt davon ab.
Eine weitere Einkapselungsgrenze sind Prozessgrenzen. Diese können zur effektiven Trennung der Komplexität verwendet werden. Sie können den Übersetzungscode als Webdienst mit einfacher HTTP-Kommunikation mithilfe von SOAP, REST oder wenn Sie wirklich ein eigenes Protokoll möchten (nicht empfohlen) erstellen. STOMP ist insgesamt kein schlechtes neueres Protokoll. Oder verwenden Sie einen normalen Daemon-Dienst mit einer systemlokalen öffentlich zugänglichen Speicher-Pipe, um mit einem beliebigen Protokoll sehr schnell wieder zu kommunizieren. Dies hat tatsächlich einige ziemlich gute Vorteile:
- Es können mehrere Prozesse ausgeführt werden, die die Übersetzung für ältere und neuere Versionen gleichzeitig ausführen. Auf diese Weise können Sie den Übersetzungsdienst aktualisieren, um ein Objektmodell V2 zu veröffentlichen, und den verbrauchenden Code zu einem späteren Zeitpunkt separat aktualisieren, um mit dem neuen Objekt zu arbeiten Modell.
- Sie können interessante Dinge tun, z. B. das Fixieren des Prozesses auf einen Kern für die Leistung. Sie erhalten bei diesem Ansatz auch ein gewisses Maß an Sicherheit, indem Sie diesen Prozess zum einzigen Prozess machen, der mit den Sicherheitsberechtigungen zum Berühren dieser Daten ausgeführt wird.
- Sie werden eine sehr starke Grenze erhalten, wenn Sie über Prozessgrenzen sprechen, die fest bleiben und für eine lange Zeit ein Minimum an Abstraktionslecks gewährleisten, da das Schreiben von Code im Übersetzungsraum nicht außerhalb des Übersetzungsraums aufgerufen werden kann, da diese nicht vorhanden sind Der Prozessumfang wird nicht gemeinsam genutzt, wodurch vertraglich festgelegte Nutzungsszenarien sichergestellt werden.
- Die Möglichkeit für asynchrone / nicht blockierende Updates ist einfacher.
Die Nachteile sind offensichtlich mehr Wartung als gewöhnlich erforderlich, und der Kommunikationsaufwand beeinträchtigt die Leistung und die Wartung.
Es gibt eine Vielzahl von Möglichkeiten, die Komplexität zusammenzufassen, damit diese Komplexität an immer seltsameren und merkwürdigeren Stellen in Ihrem System abgelegt werden kann. Mit Formen von Funktionen höherer Ordnung (oft mit Hilfe von Strategiemustern oder verschiedenen anderen ungeraden Formen von Objektmustern gefälscht) können Sie einige sehr interessante Dinge tun.
Das ist richtig, lassen Sie uns über eine Monade sprechen.Sie könnten diese Übersetzungsschicht in einer sehr unabhängigen Weise aus kleinen spezifischen Funktionen erstellen, die die erforderlichen unabhängigen Übersetzungen ausführen, aber alle nicht sichtbaren Übersetzungsfunktionen ausblenden, damit sie für externen Code kaum zugänglich sind. Dies hat den Vorteil, dass die Abhängigkeit von ihnen verringert wird und sie sich leicht ändern können, ohne großen Einfluss auf externen Code zu haben. Anschließend erstellen Sie eine Klasse, die Funktionen höherer Ordnung (anonyme Funktionen, Lambda-Funktionen, Strategieobjekte, die Sie jedoch strukturieren müssen) akzeptiert, die auf allen Objekten vom Typ OO-Modell funktionieren. Sie lassen dann den zugrunde liegenden Code, der diese Funktionen akzeptiert, die wörtliche Ausführung mit den entsprechenden Übersetzungsmethoden durchführen.
Dadurch wird eine Grenze erstellt, an der die gesamte Übersetzung nicht nur auf der anderen Seite der Grenze vorhanden ist, sondern nicht in Ihrem gesamten Code. Es wird nur auf dieser Seite verwendet, sodass der Rest Ihres Codes nur weiß, wo sich der Einstiegspunkt für diese Grenze befindet.
Ok, ja, das ist wirklich verrückt, aber wer weiß? Sie könnten einfach so verrückt sein (im Ernst, unternehmen Sie keine Monaden mit einer Verrücktheitsrate von unter 88%, es besteht die reale Gefahr von Körperverletzungen).