Laden...

Verständnisfrage Drei-Schicht-Architektur und Dependency-Inversion

Letzter Beitrag vor 11 Monaten 7 Posts 678 Views
Verständnisfrage Drei-Schicht-Architektur und Dependency-Inversion

Hallo,

ich lese gerade ein Buch über Dependency Injection und ausgehend davon wird auch Dependency-Inversion und Drei-Schicht-Architektur erwähnt. Ich möchte das ganze nun auch in meinem Projekt anwenden und habe eine grundsätzliche Frage.

Im Buch wird erwähnt, dass die Datenzugriffsschicht von der Logikschickt abhängen soll und nicht andersherum bzw. auch, dass jede Schicht die Interfaces, die sie verlangt, selbst definieren soll.

Frage: Wie mache ich dass, wenn die Datenschicht in einer eigenen Bibliothek vorliegt? Aus dem Bauch heraus würde ich sagen, man braucht eine zusätzliche Vermittlungsschicht, die dann von der Logik- und der Datenschicht abhängt und das dann vermittelt, Stichwort Glue-Code. Wie gesagt, das wäre meine erster Gedanke. Wie ist der "offizielle" Weg?

Grüße, Alex

Final no hay nada más

Im Buch wird erwähnt, dass die Datenzugriffsschicht von der Logikschickt abhängen soll und nicht andersherum bzw. auch, dass jede Schicht die Interfaces, die sie verlangt, selbst definieren soll.

Welches Buch ist das?

Frage: Wie mache ich dass, wenn die Datenschicht in einer eigenen Bibliothek vorliegt?

Getrennte Bibliotheken sind nur ein organisatorisches Mittel in einer Solution, hat aber keine Auswirkung auf die Softwarearchitektur an für sich.

Die Logik kennt die Datenschicht

public class UserService(IUserRepository userRepository)

Ob das IUserRepository nun durch eine zusätzlich Lib-Referenz kommt oder nicht, ist hier unerheblich.

Eigentlich braucht man hier keinerlei Glue-Code.


https://github.com/BenjaminAbt/AspNetCoreEnterprisePlatform ist mein ASP.NET Core Schulungscode von 2022.

Beispiel: das "Tenants" ist die Domäne (nach Domain Driven Design), wobei Features.Tenants das eigentliche Domänen-Projekt ist.
Darin enthalten ist sowohl die Logik, wie auch die Datenverantwortung der Domäne. Es würde aber keine Rolle spielen, wenn die Daten in einem extra Organisationprojekt zB "Features.Tenants.Database" liegen würden. Das würde organisatorisch gewisse Dinge erleichtern wie Multi-Database, aber nicht die Software Architektur.

Mein Beispiel hat auch (relativ) viele Projekte; sind aber alles organisatorische Mittel einer Plattform (das Schulungsziel). In den meisten Fällen, vor allem bei kleineren Anwedungen, hat man sehr viel weniger Projekte.

Hallo Abt,

danke für deine Antwort. Das Buch heißt "Dependency Injection Principles, practices and patterns" von Mark Seemann.

Dein kurzes Beispiel habe ich in dem Buch genau anders verstanden, nämlich so, dass IUserRepository in der Logikschicht definiert sein muss, damit diese nicht von der Datenschicht abhängt. Sonst müsste ich ja immer die Logikschicht anpassen müssen, wenn sich die Datenschicht andert. Die Datenschicht implementiert dann das Interface. Wenn aber die Datenschicht aus einer anderen Bibliothek stammt, müsste ich da ja noch eine Eben einfügen, die das "anpasst", weil ja das konkrete UserRepository aus der Bibliothek nichts vom Interface meiner Logikschicht weiß. Es gibt ja hier im Forum auch einen Thread zum Thema Schichtarchitektur. Da erwähnt jemand, dass man unter Umständen viel Gluecode schreiben muss, wenn man das konsequent durchzieht. Ist das damit gemeint?

Grüße, Alex

Final no hay nada más

Das kann aber so nicht funktionieren, denn IUserRepository muß ja in beiden Schichten bekannt sein (denn in der Datenschicht muß es ja eine konkrete Klasse geben, welche dieses Interface implementiert), also darf es nicht in der Logikschicht definiert sein, sondern zwingend im DAL.

Das Interface sollte ja relativ stabil (über die Zeit) sein, aber wenn sich etwas ändert (z.B. neue Methoden oder Parameter ändern sich), dann müssen beide Schichten angepaßt und neu kompiliert werden.

Sicherlich kann man noch ein extra Projekt nur für die Schnittstellen machen, dies lohnt sich aber erst bei größerem Projekten (vor allem wenn man mit Fremdbibliotheken bzw. eigenen Teams arbeitet, die eine komplette Schicht umsetzen bzw. es alternative Implementierungen gibt, welche in verschiedenen Anwendungen genutzt werden z.B. für Kunden mit verschiedenen Datenbanksystemen).

Zitat von ill_son

Das Buch heißt "Dependency Injection Principles, practices and patterns" von Mark Seemann.

Ich kenn das Buch, das steht da nicht drin. Das hast falsch rum verstanden.
Wie Th69 schreibt geht das auch gar nicht.

Hallo,

ich wollte mich nochmal zur Thematik melden und zur Diskusion betragen. Ich hab nochmal ins Buch geschaut und die Stelle gefunden. Ich hab das Buch in der 2019er Ausgabe. Da ich mir nicht sicher war, ob ich das einfach ablichten und ins Forum stellen darf, hab ich es fix nachgezeichnet. Das Bild hab ich dem Post angehängt, im Buch auf Seite 68, Bild 3.11.

Auf Seite 63 steht auch nochmal:

"Because our goal is to inverse the dependency between the domain layer and the data layer, IProductRepository is defined in the domain layer."

Meine Problematik ist, das ich absehbar vor der Aufgabe stehe, in meiner Anwendung die erzeugten Daten abhängig davon, wer mit der Anwendung arbeitet, zu verarbeiten. Beispielsweise Anwender aus Gruppe A legt beim Betätigen des "Speicher-Buttons" Daten nur lokal ab, Anwender aus Gruppe in der Datenbank. Wenn jetzt Implemetierung A und B in unterschiedlichen Bibliotheken oder Projekten sind, ginge das ja nur so wie oben beschrieben. Wo liegt mein Denkfehler?

Grüße, Alex

Final no hay nada más

Der Domain Layer ist aber nicht die Logik, sondern eben die Domäne. Das gleiche wie ich oben beschrieben hab.

Dein Bild ist im Endeffekt die kleinste Ausbaustufe für die Basis einer 3-Tier-Architektur. Ein "großen Produktservice" würde man in modernen Architekturen jedoch eher nicht mehr machen. Wird zu oft zu einer großen, unwartbaren monolithischen Klasse. Sofern der UserContext das Ding von EF ist - gehört auch das zum DAL.

Und ja: Deine Logik kennt die Datenschicht - nicht umgekehrt.