Laden...

Was ist falsch an meiner Schichtentrennung in einem ASP.NET MVC 5 Projekt?

Erstellt von MorphieX vor 5 Jahren Letzter Beitrag vor 5 Jahren 7.282 Views
M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren
Was ist falsch an meiner Schichtentrennung in einem ASP.NET MVC 5 Projekt?

Hallo,

ich fange gerade an meine erste größere Anwendung zu entwickeln und weiß jetzt schon, dass sie über Jahre wachsen und wahrscheinlich von unterschiedlichen Mitarbeitern gepflegt wird.
Daher lege ich großen Wert auf eine möglichst saubere Architektur von Anfang an.

Folgendes ist gegeben:

Infrastructure Assembly

  • Interfaces für DI, z.B. IRepository, IUnitOfWork, IUserResolver,...
  • Entitiy-Klassen und dazugehörige Enums

Data Access Assembly

  • Entity Framework 6.2
  • Auditing (also auch etwas Logik)
  • Zugriff auf Infrastructure Assembly

Business Logic Assembly

  • Implementierung der Repositories, UnitOfWork,...
  • Utilities, z.B. Passwort-Verschlüsselungen
  • Security
  • Zugriff auf Infrastructure Assembly
  • Zugriff auf Data Access Assembly

Presentation Layer

  • Hauptprojekt
  • ASP.NET MVC 5 (ja, kein ASP.NET MVC Core, das ist momentan Absicht, wird aber später sicherlich ausgetauscht
  • In den Controllern werden meist CRUD-Operationen über die Repositories durchgeführt.
  • jede View hat ein eigenes ViewModel, gemappt wird per AutoMapper
  • Abhängigkeiten werden per DI aufgelöst
  • Zugriff auf Business Logic Assembly
  • Zugriff auf Infrastructure Assembly

Meine Projektstruktur sieht also zusammengefasst so aus:

[Presentation Layer] -> [Business Layer] -> [Data Access Layer]
[                      Infrastructure Layer                   ]

Nun zu meinen Fragen:

  1. Gehört die Implementierung des Repositories in den BLL oder in die DAL? Ich habe halt Geschäftslogik in meinen Repositories.

  2. Ich benutze im BLL die Entities, die mir das Entity Framework liefert. Das funktioniert so.
    Ich lese aber in fast allen theoretischen Artikeln, dass da noch Business Objects dazwischen gehören. Also habe ich das mal ausprobiert und auch gleich wieder rückgängig gemacht, da ich gemerkt habe dass das 100% 1:1-Kopien meiner Entities waren. 😉 Irgendwas verstehe ich hier also noch nicht richtig.
    Bisher habe ich auch noch kein Beispiel gefunden, bei dem das so gemacht wurde. Hat jemand einen Link zu einem entsprechenden Beispiel?
    Sind eigene Business Objects bei Verwendung des Entity Frameworks vielleicht gar nicht notwendig?
    Später kommen noch Objekte hinzu, die nicht (sofort) im Entity Framework landen - da kann ich mir das sehr gut vorstellen.

16.806 Beiträge seit 2008
vor 5 Jahren

Repository im Sinne von Daten aus der Datenbank holen, gehören zur Datenschicht.
Diese machen nichts anderes als Entitäten zu schreiben und zu lesen.

In der Business Logik spricht man i.d.R. von Services; die dann aber trotzdem mit dem Repository Pattern umgesetzt werden können.

  1. Ich benutze im BLL die Entities, die mir das Entity Framework liefert. Das funktioniert so.

Funktioniert - ist aber aus Sicht der Software Architektur falsch.
Es ist akzeptabel für kleine Tools das so zu machen; für größere natürlich nicht.

Auch das EF ist nicht in der Lage ordentlich von Entity und Business Object (Domain Object) zu trennen.
Und in der Logik arbeitet man mit Domain Objects.

Ob Du das wirklich in Assemblies aufbauen musst; das ist nen Philosophie-Thema.
Ich mach das nur noch, wenn man muss.
Ansonsten trenne ich "Kern" der Anwendung von UI; sprich 2 Projekte.

Aber zu Deiner Technologieauswahl....

Wenn Du schon sagts, dass die Software Jahre bestehen wird, aber dann auf EF 6.2 und MVC 5 setzt. Das ist alles andere als "mal kurz" zu migrieren.
Vor allem EF würde ich mir nicht mehr ans Bein binden.

M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren

Hallo Abt,

danke für deine Antwort 😃

Und in der Logik arbeitet man mit Domain Objects.

So hatte ich es tatsächlich schon mal umgesetzt. Fühlte sich aber irgendwie nicht richtig an, weil viel Aufwand für (bislang) keinen zusätzlichen Nutzen. Aber ich werde es dann doch noch mal so versuchen.
Frage: Wenn es wirklich eine 1:1-Kopie ist, erbst du dann von der Entität?

Ob Du das wirklich in Assemblies aufbauen musst; das ist nen Philosophie-Thema.

Im Moment hilft mir das, die Schichten nicht versehentlich zu durchbrechen. Ich denke wenn man da ein bisschen mehr Übung drin hat, kann man es sicher auch wagen die Schichten in einer gemeinsamen Assembly zu halten.

Aber zu Deiner Technologieauswahl....

Hehe, mir war klar dass das sofort kommt 😉 Du hast ja auch absolut recht.
Im Moment "spiele" ich auch noch mit der Architektur und auch mit den Technologien. Genau diese beiden Schichten wollte ich aber absichtlich als nächsten "Meilenstein" austauschen.
Ich möchte ein Gefühl dafür bekommen, einzelne Programmteile in einer sauberen Architektur austauschen zu können. - wenn das ohne große Anpassungen in den anderen Programmteilen funktioniert, dürfte die Schichtentrennung doch erfolgreich gewesen sein.
Und wenn ich sage, dass das Projekt über mehrere Jahre gepflegt wird, dann gehe ich davon aus, dass irgendwann ein weiterer Technologiewechsel erfolgen wird.

16.806 Beiträge seit 2008
vor 5 Jahren

Fühlte sich aber irgendwie nicht richtig an

Es ist aber richtig.

, weil viel Aufwand für (bislang) keinen zusätzlichen Nutzen.

Entitäten sind i.d.R. flacher geschnitten als Domain Objects.
Dann hattest Du womöglich einfach noch keine große Anwendung im Sinne einer großen Anwendung.

Bei kleinen Anwendungen ist es tatsächlich so, dass man es selten spürt.
Gefühlt hast Du jetzt auch alles andere als eine große Anwendung 😉

Wenn es wirklich eine 1:1-Kopie ist, erbst du dann von der Entität?

Niemals.

Ich hab mir dafür einfach nen eigenen, sehr simplen, sehr schnellen Mapper (https://github.com/SchwabenCode/FlexMapper) geschrieben.
Ich halte von Auto Mapper nicht viel, weil er es sehr komplex macht, sobald man mit Lazy-Informationen arbeiten (zB einem Datenbankkontext).
Zudem ist der AutoMapper halt (in Relation) langsam.

Im Moment hilft mir das, die Schichten nicht versehentlich zu durchbrechen.

Genau. Dafür hilft es tatsächlich. Damit kann man die Faulheit von Entwicklern brechen 😉

Genau diese beiden Schichten wollte ich aber absichtlich als nächsten "Meilenstein" austauschen.

Das ist halt mehr als nur austauschen.
Ich will dafür sensibilisieren, dass das kein Versionupdate ist, sondern als ob Du eine komplette Technologie ersetzt.

Du musst auch von dem Gedanken etwas Abstand nehmen, dass Du was bauen wirst, in dem man alles einfach austauschen kann wie man lustig ist.
Das ist ein Wunschgedanken, der nie existieren wird.

Du wirst bei einem Technologiewechsel immer auch eine Migration durchlaufen - und das macht bei einem Grüne-Wiese-Projekt ehrlich gesagt wenig Sinn.
Und besonders beim EF zeigt die Historie, dass das alles andere als einfach ist - vor allem wenn man auch noch Migrations verwendet.

Das kostet richtig Zeit und Geld.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Hi MarphieX,

zu. 1.) Die Repositories sollten eigentlich keine Geschäftslogik enthalten und gehören so mit eigentlich in den DAL.

zu. 2.) Nun man kann auch ohne Bussiness Objekte auskommen wenn man EF verwendet. Wenn die SQL DB in der 3. Normal Form ist. Ist da aber für ein Objekt keine schöne Struktur mehr. Und wenn du dann aus Performance gründen hin gehst und sie denormalisirst musst du dann auch deine ganz BL anfassen was man eigentlich nicht möchte.

Das zu den Fragen.
Deine Infrastruktur Assembly (bzw. es müssen nicht unbedingt Assembly sein Namespaces reichen aush) würde ich auf Teil (DAL -> IDAL, BL -> IBL usw.). Was du noch gebrachen kannst sind Cross Cutting Conceps. Da kannst du z.B. den Logger rein Packen.

Dann gibt es grundlegend noch eine harte und eine "weiche" Trennung bei der 3-Schichten Architektur.
Bei der "weichen" darf der PL auf den DAL zugreifen. Bei der harten Trennung laufen alle zugriffe über den BL. Wenn du hauptsächlich CRUD funktionen hast, ist der BL eigentlich unnötiger Ballast. Eine Trennung ist aber mit einer Generischen Basis Klasse recht einfach gemacht und falls später doch noch Logic hinzu kommt weist man wo man sie hin packen soll. Außer dem ist es später einfacher zu sagen, ich verzichte jetzt auf den BL und greife direkt auf den PL zu. Als den umgekehrten Schritt zu machen und nachher alle DAL zugriffe aus dem PL zu schmeißen.

Den Zugriff auf die Datenbank solltest du vielleicht noch über eine WebApi kapseln.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

zu. 2.) Nun man kann auch ohne Bussiness Objekte auskommen wenn man EF verwendet.

Sowas existiert nur in den Unicorn-Beispielen von Microsoft.
Das funktioniert in realen Anwendungen so gut wie nie, da Entitäten einfach vom Grundgedanke anders geschnitten werden als Business-Objekte / Domain Objects.

Hat auch nichts mit der Normalform einer DB zutun.
Die Logik kennt schließlich die DB überhaupt nicht.

M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren

Danke 😄

Ich glaube ihr habt mir jetzt ein wenig die Augen geöffnet.

Könnt ihr mir vielleicht ein Praxis-Beispiel nennen, bei dem sich das Business-Objekt von der Entität unterscheidet? Theoretisch muss ein Business-Objekt doch auch über eine eindeutige ID und den Merkmalen der Entität verfügen.

Ich finde diese minimal-Beispiele von MS (und zig anderen) mittlerweile echt kontra-produktiv...

@Abt, bzgl. der Technologie-Auswahl werde ich damit loslegen, sobald ich das mit der Schichtentrennung sauber habe. Danke noch mal für den Hinweis. Ich habe das vielleicht doch als zu einfach empfunden.

P
1.090 Beiträge seit 2011
vor 5 Jahren

zu. 2.) Nun man kann auch ohne Bussiness Objekte auskommen wenn man EF verwendet.

Sowas existiert nur in den Unicorn-Beispielen von Microsoft.
Das funktioniert in realen Anwendungen so gut wie nie, da Entitäten einfach vom Grundgedanke anders geschnitten werden als Business-Objekte / Domain Objects.

Hat auch nichts mit der Normalform einer DB zutun.
Die Logik kennt schließlich die DB überhaupt nicht.

Eine Entity ist die Objekt Darstellung einer relationalen Datenbank. (OR Mapper). Das heißt indirekt sind dort auch Informationen über die Datenbank Struktur enthalten. Wenn ich die Entity jetzt im BL verwende kennt die BL indirekt die DB Struktur. Wenn ich die DB Struktur ändere, muss ich meist auch die Entity anpassen. Und damit dann den BL.
Mit der 3. Normal Form und wenn man diese bei einen OR Mapper verwendet, denke ist recht anschaulich dargestellt, das die Objekt Darstellung die entsteht, sich nicht wirklich für Bussines Objekte eignet.

Könnt ihr mir vielleicht ein Praxis-Beispiel nennen, bei dem sich das Business-Objekt von der Entität unterscheidet? Theoretisch muss ein Business-Objekt doch auch über eine eindeutige ID und den Merkmalen der Entität verfügen.

Ist jetzt nicht unbedingt ein ein Business-Objekt, aber beim Anlegen von Daten hast man oft eine Auswahl liste (z.B. Anreder Herr/Frau usw). Die Liste ist nicht in der Entity enthalten, bei ihr gibt es eine eindeutige Zuordnung (von der Auswahl).

Ein Business-Objekt muss auch nicht zwangsläufig eine ID haben. Es gibt oft eine "natürliche" Identität. Z.B. wird aktuell meist oft die E-Mail Adresse verwendet. Die solltest du aber nicht in deiner DB als ID verwenden. Weil sie sich ändern kann.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Wenn ich die DB Struktur ändere, muss ich meist auch die Entity anpassen. Und damit dann den BL.

Und das ist eine Verletzung und zeigt ein Fehldesign der Software Architektur auf.

Der BL muss nie angefasst werden, wenn das Mapping von Entität zu Business Object sauber abläuft.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Der BL muss nie angefasst werden, wenn das Mapping von Entität zu Business Object sauber abläuft.

Das ist auch genau der Grund wie so man keine Entitäten im BL verwenden sollte.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren

Wo wird denn gemappt?
Wenn ich den BL wirklich als eigene Assembly führe, werden die Entities doch im BL in Business Objects gemappt. Und wenn ich nun eine Änderung an meine Entities vornehme, muss ich das Mapping ggf. anpassen, somit also den BL, oder?
Ich muss ja schließlich auch meine Business Objects anpassen, da die Änderung an den Entities (z.B. neues Datenbankfeld) auch im Business Object ankommen soll.

Oder findet das Mapping im DAL statt?

Beispiel:
Ich habe eine Entität "PersonEntity"

  • ID
  • Nachname
  • Vorname

Ich habe dazu das BusinessObject "Person"

  • ID
  • Nachname
  • Vorname
  • VollstaendigerName

Nun erweitere ich meine Entity:

  • ID
  • Nachname
  • Vorname
  • Anrede

also muss ich auch das BusinessObject anpassen:

  • ID
  • Nachname
  • Vorname
  • Anrede <- neu
  • VollstaendigerName <- das Mapping muss ebenfalls angepasst werden

Gut, man könnte jetzt sagen dass das Mapping nicht im BL stattfindet, weil es woanders konfiguriert wird (z.B. AutoMapper-Config) und dass die BusinessObjects nicht unbedingt im BusinessLayer definiert sein müssen, sondern z.B. in der Infrastructure, aber das eigentlich gehört das für mich zum BL

16.806 Beiträge seit 2008
vor 5 Jahren

Wo wird denn gemappt?

Das ergibt sich ja allein anhand der Schichten.
Da der DAL nicht die BL kennen darf, muss der Mapper Teil des BL-Projekts sein.

Bevor also Daten den Service erreichen, muss gemappt werden.

zB.

ArticleEntity e = _articleRepository.Get();
Article a = ArticleMapper.FromEntity(ArticleEntity);

Damit bleibt der Business Layer völlig frei vom Inhalt einer Entität (sondern hat nur die Referenz auf die Abfrage).
Die Entität kann sich damit so viel ändern wie sie will; das Business Objekt bleibt unberührt und nur der Mapper muss angepasst werden.

Und natürlich nicht: Business Objekte gehören in den Business Layer und nicht in Infrastructure.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Die Frage ist ob du da nicht eher DTO bzw. Models hast.

Wir haben bei uns eine eigene Assambly für die Models. Das kennt sowohl PL, BL und DAL (nicht alle Models werden von den Einzelnen Layern Verwendet).

Wir Mappen bei uns im DAL. Das hat bei uns den Grund, das Maschinen und ein altes VB6 unterstützt werden müssen. Die Teils noch auf Ini Files und Access Datenbanken zugreifen. Und beim Ini File habe ich keine Entities. Da sollte der BL sie auch nicht kennen.

Wir haben bis ca. vor einem Jahr noch ASP MVC verwendet. Da haben wir die Models auch direkt in der View verwendet. Dann sind wir nach Aurelia umgestiegen. Aus dem Models konnten, dann Type Script Klassen generieren und die Controller brauchten wir dann nur so abzuändern, das sie nur das Model und nicht mehr die View zurückgegeben haben. Hat ganz gut geklappt.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Wir Mappen bei uns im DAL.

Das heisst der DAL hat eine Referenz auf den BL und der BL auf den DAL?
Das wäre ne Circular Dependency.

Wir haben bis ca. vor einem Jahr noch ASP MVC verwendet. Da haben wir die Models auch direkt in der View verwendet.

Klassische Schichtenverletzung.

Wenn Du ein User hast mit einem Passwort-Property, würdest Du dieses damit exposen.
Sicherlich nicht Sinn der Sache.

Hat ganz gut geklappt.

Auch die Microsoft Beispiele klappen immer gut, weil Unicorn.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Wir Mappen bei uns im DAL.

Das heisst der DAL hat eine Referenz auf den BL und der BL auf den DAL?
Das wäre ne Circular Dependency.

Wir haben bei uns eine eigene Assambly für die Models. Das kennt sowohl PL, BL und DAL (nicht alle Models werden von den Einzelnen Layern Verwendet).

PL, BL und DAL kennen also das Modell. Das Model selber kennt niemanden.

Wir haben bis ca. vor einem Jahr noch ASP MVC verwendet. Da haben wir die Models auch direkt in der View verwendet.

Klassische Schichtenverletzung.

Also soweit ich weiß steht das M in MVC für Modell. Und im MVC Pattern kann die View das Modell kennen. Er kläre hier mir bitte mal Fachlich, wo eine Schichtverletzung vorliegt.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

PL, BL und DAL kennen also das Modell. Das Model selber kennt niemanden.

Und das sollte man ja eigentlich nicht so machen, denn jede Präsentationsschicht hat i.d.R. seine eigenen Modelle.
Daran ändert auch das M in den Pattern-Bezeichnungen nichts.

Du kannst kein Modell in ASP.NET HTML, ASP.NET API, WinForms und einer App teilen - bzw. funktioniert das bei nur sehr sehr sehr einfachen Modellen - und/oder wenn man die Funktionalitäten der einzelnen UI-Technologien vollkommen ignoriert.

Das Modell, das eine API zurück gibt (eine API ist im Prinzip auch nichts anderes als die UI aus Sicht der API-Anwendung) gibt ganz andere Inhalte und Strukturen (Stichwort Hypermedia) aus als zB. WPF (Stichwort Observables).
Dabei kann/wird aber die Business Logik in beiden Fällen vollkommen identisch sein. Würde mich jetzt ehrlich gesagt wundern, wenn ihr hier was neues erfunden habt, das dieses Technologie-Grundproblem lösen würde.

Daher gehört das entsprechende View-Modell auch nicht in die BL.
Zudem findet das Mapping auf UI-Seite statt.

Wenn Du ein User hast mit einem Passwort-Property, würdest Du dieses damit exposen.
Sicherlich nicht Sinn der Sache.

Nette Unterstellung. Kann ich auch. Das ist nur wirklich ein Problem wenn man wie du die Passwörter im Klartext in der DB speichert.
Aber selbst die "Hash Werte" Reiche ich nicht bis zur UI durch.

Es ist sehr schade, wie Du (leider wieder) ein einfaches, sachliches Fallbeispiel (das ich in dieser Form in diesem Forum schon zig Male verwendet habe, weil es alltäglich ist) als persönlichen Angriff wertest und daraus (leider wieder) einen persönlichen Angriff startest.
Was willst Du damit erreichen?

M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren

Was haltet ihr davon, wenn wir (die Community) ein Beispielprojekt erarbeiten, auf welches man dann im [Artikel] Drei-Schichten-Architektur bzw. unter die regelmäßig gestellten Fragen zu diesem Thema verlinken könnte?

So simpel wie möglich und so komplex wie nötig.

Eventuell auch in unterschiedlichen Variationen, z.B. ohne Tools wie AutoMapper oder EF (damit man wirklich sieht was da eigentlich passiert) und mit Tools, damit man sieht was man an Arbeit spart 😉

Ich habe zumindest überall nur Beispiele gefunden, die entweder falsch; viel zu komplex oder viel zu simpel gehalten sind.

Das wäre aus meiner Sicht ein echter Mehrwert.

16.806 Beiträge seit 2008
vor 5 Jahren

Das wären aber 10< Beispiele, die natürlich auch gepflegt gehören - und trotzdem nicht alles abdecken werde.
Entwickler ist man ja auch, weil man entwickelt und nachdenken sollte. Für alles kann es keine Templates zum Kopieren geben.

P
1.090 Beiträge seit 2011
vor 5 Jahren

@Abt
Es gibt doch einige Anwendungen, da geht es Zentral darum das der Benutzer Daten eingibt und Speichert. Die Verwenden Zentral die CRUD Funktionen. Da geht es Zentral darum die Daten von der View in die Datenbank zu bekommen. Was dazu fuhrt das mein Model Gleich dem Bussines Object ist. Und das ist ähnlich dem Entety Model. Wenn ich jetzt eine Änderung im Entety Model mach. Muss ich auch, das Model und das Bussiness Objekt ändern. Und die UI Anpassen, soll ja auch angezeigt werden. Und ich brauche noch 2 Mapper, die ich gegebenen Falls auch anfassen muss. Dann brauch der PL noch einen Verweis, auf die Bussiness Objekte des BL (also einen Verweis auf die Implementierung BL)under BL auf die Entitäten (also einen Verweis auf die Implementierung DAL). Und um dann die Entitäten Richtig Mappen zu können muss der BL auch deren Abhängigkeiten kennen.
Dazu kommt dann noch das nicht alle Daten Zugriffs Technologien Entitäten unterstützen.

Wenn ich den DAL die Daten auf ein Objekt Mappen lasse, die (Objekte) kann ich in ein eigens Assembly packen. Braucht der BL nur ein die Interface des DALs zu kennen. Welches ich auch in ein eigenes Assembly Packen kann. Und mein BL kann jedes Assembly verwenden, welche die Schnittstellen des DAL implementiert. Bei Änderungen muss ich dann die Klasse mit dem Objekten ändern. Den DAL und da das Mapping anpassen. Und wenn ich die Daten bis in die UI so verwenden kann, brauche ich nur die UI Anpassen. Und falls ich doch ein Komplizierteres Bussines Model Brauche, kann ich es mir immer noch erstellen und Mappen.

@MorphieX
Bei der Disskusion zu Drei Schichten Architektur ist ein wirklich einfaches Beispiel zu finden.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Das hört sich ehrlich gesagt nicht so an, als ob es für mehrere Oberflächen/Technologien ausgelegt ist - Du hast hier ja laut Beschreibung eine (unnötige?) Bindung und schränkst Dich damit ein.
Das würde (offensichtlich?) knallen, wenn zB. ASP.NET auf WPF trifft.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Die Abhängigkeit zu den Entitäten, habe im Prinzip gegen die zur "Modell" Klasse getauscht. Dafür kann (muss aber nicht) ich auf eine Klasse (die Redundant ist) und einen Mapper verzichten (PL<->BL).

Wenn wir uns mal das ASP MVC Modell aus dem Beispiel anschauen. Das kann ich bei MVC Verwenden. Das Objekt lässt sich aber auch Problem Los als Json Serialisieren. So das ich per WebApi bereitstellen kann. Eine Type Skript Klasse kann ich auch daraus erstellen lassen. Das Model kann ich auch als Model bei WPF im MVVM Pattern benutzen. Falls ich das PropertyChange Brauche kann ich es als nicht serilisierbar kennzeichnen (Ob es jetzt mit TypeScript funktioniert weiß ich nicht aber ich denke da gibt es eine Möglichkeit). Und bei Windoes Forms kann ich es auch nutzen. Bei Bedarf kann ich es immer noch auf eine Andere Struktur Mappen.

Das ist natürlich jetzt ein Einfaches Beispiel, es geht auch Komplexer. Nur sicher nicht Beliebig Komplex.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Ich nenne es mal Zufall, dass es bei Dir funktioniert.
Meine Erfahrung sagt, dass es eigentlich kein realen Fall gibt, der nicht ohne Workaround damit auskommt.

Daher finde ich die Beispiele dazu auch von Microsoft einfach nicht gut und realitätsnah.
Teilweise sogar eklatant falsch (zB. EF Beispiel mit Http Client)

P
1.090 Beiträge seit 2011
vor 5 Jahren

Da fällt mir die Signatur von jemanden hier im Forum ein.
(Frei zitiert)
„Alles „wussten“, das es nicht Funktioniert. Da kam jemand der wusste das nicht und tat es einfach.“

Kann natürlich sein, das es bei mir Zufall ist. Und Erfahrung ist natürlich gut. Aber wissen ist da besser.

p.s.
Bevor mich da jemand Falls Versteht wir konnten unser „Daten“ Model Problemlos übernehmen, bei der Umstellung von MVC nach Aurelia. Bei Komplexeren Sachen, die manchmal echt schwer waren mit MVC umzusetzen. Wurde schon einiges (im Controller) geändert, was dann mir Aurelia deutlich leichter war.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Und Erfahrung ist natürlich gut. Aber wissen ist da besser.

🤔

M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren

@MorphieX
Bei der Disskusion zu Drei Schichten Architektur ist ein wirklich einfaches Beispiel zu finden.

Meinst du "ProductCatalogue"? Ich weiß ja nicht...
Im Prinzip ist in dem Beispiel alles vom DataSet abhängig, und damit meine ich nicht unbedingt die Daten, sondern die Technologie. Für mich (und das ist meine persönliche Meinung) liegt die Schwierigkeit der Schichtentrennung in den Schnittstellen zwischen den einzelnen Schichten, und genau das wird in dem Beispiel meiner Meinung nach falsch dargestellt, aber das ist ein allgemeines Problem bei WinForms, bzw. Binding an DataSources.

Aber ich habe gerade ein -auf den ersten Blick- sehr vielversprechendes Projekt gefunden:
https://github.com/JonPSmith/SampleMvcWebApp

Das werde ich mir mal genauer anschauen

P
1.090 Beiträge seit 2011
vor 5 Jahren

Also das Beispiel ist daraus entstanden, das es für bei kleineren Anwendungsfallen zu Aufwändig wäre eine 3-Schichten Architektur zu verwenden. Ich denke es zeigt das eine 3-Schichten Architektur recht einfach erstellt werden kann. Es bedeutet ja erst mal nur das PL,BL und DAL trenne und das ich von höheren Schichten nur auf niedrige zugreife und niedrige Schichten höhere nicht kennen.

Wie die Schichten jetzt mit einander Kommunizieren und was am sinnvollsten wo macht, ist ein ganz anderes Thema. Und hängt einfach von zu vielen Faktoren ab um da eine pauschale Aussage geben zu können.

Um ein paar Beispiele zu nennen.
Technologie
Wenn ich in WPF eine lang laufende Berechnung im BL hab, ist es am einfachsten wenn er mich über ein Event über den Fortschritt informiert.
Hab ich ein ASP MVC Seite funktioniert es nicht wenn die auf dem Server läuft. Da kann ich dann z.B. SignalR nehmen.

Aufgabe (was macht die Anwendung)
Wenn man BL einfach 2 Zahlen zusammen Rechnet, brauche ich kein Event. Da übergebe ich, die Zahlen an eine Methode und die liefert mir ein Ergebnis zurück.

Rahmen Bedingungen
Wir haben bei uns noch Teils ini Dateien, die Verwendet werden müssen. Die Datei wollte ich auf keinen falle in den BL geben und da dann auf ein Objekt Mappen. Also hab ich sie im DAL auf das Objekt gemappt und der DAL hat mir dann das Objekt zurückgeben. Damit war meine Schnittstelle für den DAL definiert und da ich die gleiche Schnittstelle auch beim SQL Server verwenden will. Bleibt mir einstündlich anderes Übrige als das Objekt da zu Mappen.

Eine Lösung die immer Richtig ist gibt es da nicht.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Es bedeutet ja erst mal nur das PL,BL und DAL trenne und das ich von höheren Schichten nur auf niedrige zugreife und niedrige Schichten höhere nicht kennen.

Streng genommen greifst Du aber laut Deiner Beschreibung von Unten nach Oben (DAL auf BL).

Wie die Schichten jetzt mit einander Kommunizieren und was am sinnvollsten wo macht, ist ein ganz anderes Thema.

Eigentlich ist das klar.

Wenn ich in WPF eine lang laufende Berechnung im BL hab, ist es am einfachsten wenn er mich über ein Event über den Fortschritt informiert.

Hab ich ein ASP MVC Seite funktioniert es nicht wenn die auf dem Server läuft. Da kann ich dann z.B. SignalR nehmen.

Das macht kein Unterschied in der BL. Die BL kann in beiden Fällen ein Event anbieten.
In der WPF UI wird eben der Event abonniert. Über ASP.NET eben ein WebSocket-Message angetriggert.
Das ist damit nur ein Customizing der UI, nicht der BL.
Völlig Schichtkonform.

Wenn man BL einfach 2 Zahlen zusammen Rechnet, brauche ich kein Event. Da übergebe ich, die Zahlen an eine Methode und die liefert mir ein Ergebnis zurück.

Willst Du auf asynchon vs. synchron hinaus?
Auch das ist völlig getrennt von der UI.

Wir haben bei uns noch Teils ini Dateien, die Verwendet werden müssen. Die Datei wollte ich auf keinen falle in den BL geben und da dann auf ein Objekt Mappen.

Ich kenn den Inhalt nicht genau. Aber das ist bei Dir kein Einzelfall - ich hab auch noch tagtäglich aufgrund meiner Nähe zum Maschinenbau damit zutun.

Beispiel:
Wir haben eben ein IUserRepository.
Wenn der User aus der Datenbank kommen soll, dann haben wir eine UserMssqlRepository Implementierung. Wenn der User aus der Ini kommen soll eine UserIniRepository Implementierung.

Ich sehe nicht, wieso Dein Fall so einzigartig ist, weshalb er das Konstrukt "verletzen" müsste.
Ist für mich eher ein OOP Thema als ein Architektur-Thema.

Aber ich habe gerade ein -auf den ersten Blick- sehr vielversprechendes Projekt gefunden:
https://github.com/JonPSmith/SampleMvcWebApp

Ich mag das Beispiel aus einem Grund (pauschal) nicht: es wird angenommen, dass Entität und Business Model den gleichen Inhalt hat.
Das ist wieder ein unreales Beispiel für größere, komplexe Anwendungen.

Aus aktuellem Anlass: ich finde den Artikel Softwarearchitektur ohne Grundsätze sehr gut.
Es steckt sehr viel Wahrheit drin.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Es bedeutet ja erst mal nur das PL,BL und DAL trenne und das ich von höheren Schichten nur auf niedrige zugreife und niedrige Schichten höhere nicht kennen.
Streng genommen greifst Du aber laut Deiner Beschreibung von Unten nach Oben (DAL auf BL).

Mache ich garantiert nicht. Da ich für die einzelnen Sachen eigene Assemblys habe. Und die sich sonst nicht Kompilieren ließen. (An den Punkt wäre es vielleicht hilfreich, wenn ich mich da miss verständlich ausgedrückt habe. Mir zu erklären welche Punkte du nicht verstehst.).
DAL und BL greifen auf eine Modell Klasse (Assembly) zu. Die Modell Klasse kennt weder DAL noch BL. Man könnte sich also als 4. Layer bezeichnen.

Das macht kein Unterschied in der BL. Die BL kann in beiden Fällen ein Event anbieten.
In der WPF UI wird eben der Event abonniert. Über ASP.NET eben ein WebSocket-Message angetriggert.
Das ist damit nur ein Customizing der UI, nicht der BL.
Völlig Schichtkonform.

Ja da könnten wir jetzt anfangen zu Diskutier. Was noch mit zum BL und was zu UI gehört. Wollen wir uns da drauf einigen. Das das Frontend was im Brauers Läuft. Nicht einfach ein Event Verwenden kann wie es eine WPF Anwendung kann.

Willst Du auf asynchon vs. synchron hinaus?
Auch das ist völlig getrennt von der UI.

Nein ich möchte eigentlich nur (wie Erwähnt) ein paar Beispiele Aufzeigen. Wie so man nicht einfach eine Beispiel Implementierung für ein 3 Schichten Model bereitstellen kann.

Wir haben eben ein IUserRepository.
Wenn der User aus der Datenbank kommen soll, dann haben wir eine UserMssqlRepository Implementierung. Wenn der User aus der Ini kommen soll eine UserIniRepository Implementierung.

Hey das haben wir auch. Und jetzt erkläre mir mal bitte wie der BL die Entitiy aus dem UserMssqlRepository Mappen sollen. Die gar nicht in dem UserIniRepository enthalten sind?

Ich sehe nicht, wieso Dein Fall so einzigartig ist, weshalb er das Konstrukt "verletzen" müsste.
Ist für mich eher ein OOP Thema als ein Architektur-Thema.

Bitte erläutere mir es mal näher. Mir ist aktuell nicht klar was ich verletzen sollte. Grundlagen der Schichten Architektur verletze ich nicht. SOLID, DRY, YAGNI usw. Verletze ich nicht. Was ich sicher Verletze ist, irgend ein Ungeschriebene Prinzip, das ich die Selbe Klasse für die Datenhaltung nicht im DAL,BL und PL verwenden darf. Gut bei einem Logger darf ich das.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Mache ich garantiert nicht.

Na doch, das sagst Du doch hier:

DAL und BL greifen auf eine Modell Klasse (Assembly) zu. Die Modell Klasse kennt weder DAL noch BL. Man könnte sich also als 4. Layer bezeichnen.

Wenn ich ein Business Object in eine eigene DLL auslagere und auf diese von DAL und BL-Service zugreife, dann kompiliert das - wie bei Dir.
"Verletzt" aber die Idee, dass der DAL nicht das BL Model kennt.

Da ich für die einzelnen Sachen eigene Assemblys habe.
Und die sich sonst nicht Kompilieren ließen.

Und genau das ist der Punkt. Nur weil etwas kompiliert und in anderen Assemblies liegt, hat das doch nichts mit den Layern zutun.
Die Anzahl über Projekte respektive DLLs hat null Aussagekraft. Software Schichten sind ein virtuelles und kein physikalisches Konstrukt.

I.d.R. haben meine Microservices (Beispiel) zwei:

  • Identity.Usermanagement
  • Identity.Usermanagement.HttpApi

In ersteren ist DAL und BL.
In zweiterem ASP.NET Core, das in Form von Json Modellen die UI darstellt.

Trotzdem sind die Schichten im Projekt "Identity.Usermanagement" sauber getrennt.

Wollen wir uns da drauf einigen. Das das Frontend was im Brauers Läuft. Nicht einfach ein Event Verwenden kann wie es eine WPF Anwendung kann.

Nein. Der Event wird von der BL angeboten, nicht von der UI.
Ist damit etwas völlig verschiedenes. Dank WebAssembly und Blazor kann ich das exakt gleiche Event in WPF und im Frontend (> Browser) verwenden.
Exakt, 100% exakt das gleiche.

Was Du meinst ist ein Technologie-Bruch durch .NET -> JavaScript.
Das ist wieder Äpfel mit Birnen verglichen.

Und jetzt erkläre mir mal bitte wie der BL die Entitiy aus dem UserMssqlRepository Mappen sollen. Die gar nicht in dem UserIniRepository enthalten sind?

Sorry, die Frage versteh ich nicht.

P
1.090 Beiträge seit 2011
vor 5 Jahren

"Verletzt" aber die Idee, dass der DAL nicht das BL Model kennt.

Ich hab doch gar kein BL Model.

Und jetzt erkläre mir mal bitte wie der BL die Entitiy aus dem UserMssqlRepository Mappen sollen. Die gar nicht in dem UserIniRepository enthalten sind?
Sorry, die Frage versteh ich nicht.

Du hast gesagt, das du die Entities vom DAL im BL Mappst. Entities sind aber die Objekt Darstellungen von Datenbank Tabellen (O/R Mapper). Die hast du aber in einen Ini File nicht. Wie willst du sie also Mappen.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Die hast du aber in einen Ini File nicht. Wie willst du sie also Mappen.

Prinzipiell hat eine Dateiendung nichts damit zutun, wozu die Datei verwendet wird.
In meinem Fall hat der Kunde die Ini-Datei als Datenbank missbraucht.

Ich weiß nicht ganz, wozu ihr die Ini-Dateien verwendet - hoffentlich eher dem Zweck entsprechend.
Aber selbst wenn es eine Konfiguration ist, sehe ich wenig Notwendigkeit.
Da bietet die BL einfach ein entsprechendes Interface an, und die Schicht drunter die Implementierung.

Ich hab doch gar kein BL Model.

🤔 🤔 🤔
Also der Beschreibung nach schon....

P
1.090 Beiträge seit 2011
vor 5 Jahren

Die hast du aber in einen Ini File nicht. Wie willst du sie also Mappen.

Prinzipiell hat eine Dateiendung nichts damit zutun, wozu die Datei verwendet wird.
In meinem Fall hat der Kunde die Ini-Datei als Datenbank missbraucht.

Du hast mich da nur halb Zitiert. Über die Datei Endung hab ich nichts gesagt. Es geht um die Entitäten. Die du nicht hast. Ich fände es gut wenn du auf den Punkt (Entitäten) eingehen würdest.

Ich hab doch gar kein BL Model.

👶 👶 👶
Also der Beschreibung nach schon....

Nein hab ich niie gesagt.

Auf MorphieX Frage wo er die Bussines Objete Mappen soll.
Hab ich die Frage in den Raum gestellt.> Die Frage ist ob du da nicht eher DTO bzw. Models hast. Und eine alternative Vorgestellt.

Wenn ich hauptsächlich CRUD Aktionen haben. Ist es meines Erachten nicht nötig (ich kann wenn ich möchte) für jeden Layer ein eigenes Modell zu Verwenden. Grundlegend reicht es dann, da ein Modell für alle Layer zu erstellen. Bei dem dann alle Layer das Modell, kennen und das Model keiner der Layer.
Hab ich aber auch schon geschrieben.

PL, BL und DAL kennen also das Modell. Das Model selber kennt niemanden.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Wir drehen uns im Kreis, und Du widersprichst Dir selbst.

PL, BL und DAL kennen also das Modell. Das Model selber kennt niemanden.

Egal wie Du es formulierst: wenn alle Schichten das Modell kennen (und/oder davon abhängig ist), wozu es auch immer gehört, dann ist das eine Verletzung der Idee von Schichtentrennung.
Nicht mehr - und nicht weniger; völlig egal wie viele Schichten Du hast und wie Du sie nennst, ob Du das Modell jetzt im luftleeren Raum hast oder nicht.

Es bleibt ein Ideebruch und ein technologisches Problemkonstrukt, denn Du bist damit nicht in der Lage schichtspezifische Features (Annotations, Validations, Bindings..) nutzen zu können; und wenn es vereinzelt funktioniert, dann zB nur mit einer sehr starken Bindung.
Es ist auch nicht möglich eine isolierte Änderung oder Modularisierung durchzuführen - ohne den gesamten Stack zu brechen.

Das ist prinzipiell mal bei kleinen Tools nicht schlimm, einfach damit es wirtschaftlich und pragmatisch bleibt.
Aber es sollte definitiv nicht als generelle Empfehlung als Beispiel dienen, weil je größer die Anwendung ist, desto größer werden die Nachteile aufbauend aus diesem Konstrukt.

Ich fände es gut wenn du auf den Punkt (Entitäten) eingehen würdest.

Ich kann Dir echt nicht folgen, was Du meinst.

P
1.090 Beiträge seit 2011
vor 5 Jahren

dann ist das eine Verletzung der Idee von Schichtentrennung.

Nein schau dir da bitte mal die Grundlagen an. Schichtentrennung sagt erst mal nichts anderes aus als das höher Schichten, nur auf niedrige Schichten zugreifen dürfen. (Wenn du alles in eigene Assemblies packst und es sich kompilieren lässt, ist es erfüllt). Was es verletzt wäre eine Strickte Schichten Trennung. Da darf nur auf die jeweils drunter liegende Schicht zugegriffen werden.

Ich fände es gut wenn du auf den Punkt (Entitäten) eingehen würdest.
Ich kann Dir echt nicht folgen, was Du meinst.

(So langsam wird es schwer es einfacher zu erklären).
Ich probiere es noch mal. Also in deinem DAL für den zugriff auf die SQL Datenbank. Hast du Entitäten, die eine Objektorientierte Darstellung der Struktur in der Datenbank sind (Einfachsteform ist eine Entität pro Tabelle.) Dort sind haben Tabellen oft Fremd Schlüsse. Wenn es für ein Feld nur bestimmte werte geben darf. In der DB sollten sie eigentlich in einer Tabelle hinterlegt sein. Bei Ini Dateien, muss meist der Benutzer wissen welche werte er dort eintragen darf. Wenn ich mir aus einer Datenbank Entitäten erstellen lasse, gibt es einen Verweis auf dem Fremdschlüssel, dieser ist in einer Ini Datei nicht enthalten. Wenn du in BL das Mapping machst kannst du nicht Entitäten benutzen, da sie nur im DAL für den SQL zugriff existieren. Aber nicht im DAL für den Ini Zugriff. Erkläre mit bitte wie du, das sinnvoll machen willst.

Bei der Gelegenheit, das ist bei uns einer der Gründe wie so wir ein eigenes Assemby für die "Modelle" eingeführt haben. Weil der BL sonst hätte wissen müssen ob es sich um eine Ini Datei handelt oder um eine SQL Datenbank. Und das wollte ich vermeiden. Also wenn du da wirklich eine gute Lösung für hast. Bin ich offen dafür.

p.s.
Wäre nett wenn du mich wenigsten soweit Zitieren würdest. Das meine Frage nicht aus dem Kontext gerissen wird.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.806 Beiträge seit 2008
vor 5 Jahren

Schichtentrennung sagt erst mal nichts anderes aus als das höher Schichten, nur auf niedrige Schichten zugreifen dürfen.

Naja, Du machst es Dir hier leicht mit Deiner Argumentation.
Was Du machst ist nichts anderes als ein Element (hier das Modell) argumentativ aus einer Schicht zu nehmen und sagen, dass dies in der Luft hängen würde - und dadurch alles konform sei, was es natürlich nicht ist.
So funktioniert Software Architektur nicht.

Zugriffsrichtungen sind nur eine der Punkte einer Software Architektur, wie Du bestimmt in den Grundlagen auch gelesen hast, auf die Du mich aufmerksam machst.
Ein anderer, von mehreren ist die Frage, ob Du eine Schicht bearbeiten/erweitern kannst, ohne die anderen bearbeiten zu müssen.
Und das ist mit einem Modell in allen Schichten schlicht und einfach nicht möglich.

Es ist Pragmatismus, da ist das okay.
Aber zu behaupten, dass sei konform... das ist es halt nicht - egal wie viele Schichten man hat und wie sie heissen. 😉
Ich hoffe jeder der das liest, beachtet dies.

Ich hab versucht Dich auf den Konzeptfehler hinzuweisen.
Diesen kannst Du jetzt nehmen und Dir einfach mal anschauen, oder resistent bleiben und weiter andere auf Grundlagen verweisen 😃

Aber da wir uns hier im Kreis drehen und der Ton wieder in Richtung der üblichen Herablassung wandert, bin ich mal raus.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Naja, Du machst es Dir hier leicht mit Deiner Argumentation.

Ich mach es mir leicht?
Also ich habe "ausführlich" auf jede deiner Fragen geantwortet. Wobei ich wider holt, Sachen erklärt habe, die ich eigentlich vorher schon Erläutert habe.

Ich hab dich ein paar mal darum gebeten, zu erklären wie dein Konzept funktionieren soll, wenn es im Ini Assembly keine Entitäten gibt. Da hast du dich dumm gestellt Und gesagt das du meine Frage nicht verstehst. Eine Antwort hab ich immer noch nicht bekommen.

Ich kann dir jeder Zeit mein Konzept erklären. Da es Produktive im Einsatz ist. (Auch wenn du dir alle mühe gibst es falsch zu verstehen). Und funktioniert.

Dein Konzept hast du mir einfach nicht im "Detail" vorgestellt. Und weichst jetzt auch wieder aus.

Wenn du es besser weist als ich. Sollte es ja kein Problem sein, für dich, es vorzustellen und zu erklären was ich falsch mache.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren

@Palin
Was sind das denn für Ini-Files?
In der Regel gibt es doch eine feste Definition, wie so ein Ini-File aussehen kann. Also kann man das Ini-File doch genau so im DAL zu Objekten mappen wie das Entity-Framework dies mit den SQL-Daten macht.

So ist es den darüber liegenden Layern total egal, ob die Daten aus einem Ini-File oder einer Datenbank kommen.

Oder missbraucht ihr hier das Ini-File irgendwie als unstrukturierte Datenbank? In dem quasi alles mögliche drin stehen kann?

P
1.090 Beiträge seit 2011
vor 5 Jahren

Ein Ini-File ist eine Einfache Konfigurationsfilesdatei. Die Schlüssel Werte Paare enthält.

Bei den Werten kann es aber sein, das da nicht jeder Beliebige Wert drin stehen kann. Als einfache Beispiel wenn die Software Deutsch und Englisch kann, könnte "de" und "en" erlaubt sein. Hier muss dann der Benutzer einfach wissen, welche Werte er eintragen darf. Bei einer Datenbank kann ich da einfach eine Weitere Tabelle erstellen in der die Werte drinstehen und dann einen Fremdschlüssel verwenden. Wenn ich im BL Mappe muss der BL jetzt wissen ob es die Tabelle gibt oder nicht.

Würde mich jetzt mal interessieren wie Abt das Problem löst.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

M
MorphieX Themenstarter:in
184 Beiträge seit 2012
vor 5 Jahren

Hmm, ich verstehe das Problem auch noch nicht so ganz...

folgender Code gehört für mich dann z.B. in den DAL:

public class ConfigEntity
{
  public String CompanyName { get; set; }

  public String Language { get; set; }
}

public interface IConfigRepository
{
  ConfigEntity GetConfig();

  void SaveConfig(ConfigEntity config);
}

public class IniConfigRepository : IConfigRepository
{
  const String iniFileName = "config.ini";

  public ConfigEntity GetConfig()
  {
    // Ini-Datei hier lesen und in Objekt mappen
    return new ConfigEntity()
    {
      CompanyName = "Ini-Wert",
      Language = "Ini-Wert"
    };
  }

  public void SaveConfig(Config config)
  {
    // Ini-Datei hier speichern
  }
}

Die konsumierenden Layer wissen nun also nicht, dass es sich um eine Ini-Datei handelt. Im BL wird "ConfigEntity" nun wieder in ein Business-Model "Config" gemappt. -> genau so wie die Entities die aus einer Datenbank kommen.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Für den Ini DAL wäre dein Entität korrekt (Obwohl es da eigentlich keine Entitäten gibt). Da Language kein Fremdschlüssel ist. Im SQL DAL sollte es so aussehen.

public class ConfigEntity
{
  public String CompanyName { get; set; }

  public Language Language { get; set; }
}

Da Language ja eine Eigene Tabelle ist.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

R
295 Beiträge seit 2008
vor 5 Jahren

Es gibt kein 'Ini DAL' oder ein 'SQL DAL'. Es gibt genau ein Data Access Layer, welches zwei verschiedene Repositories (oder was auch immer) enthält.

Diese implementieren beide das (beispielsweise) IConfigRepository, welches mit einer ConfigEntity arbeitet.

Sprich;
Im DAL mappen die einzelnen Repositories ihre Daten in die Config Entity.
Im Business Layer wird dann die ConfigEntity in entsprechende Business Model gemappt.

Gruss,
Wurm.

ServiceStack & Angular = =)

709 Beiträge seit 2008
vor 5 Jahren

Da Language ja eine Eigene Tabelle ist.

Solange das Repository die Daten so zurück gibt, wie es das Interface vorsieht, ist das egal.
Dann muss das halt durch das Repository entsprechend aufgelöst werden.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Solange das Repository die Daten so zurück gibt, wie es das Interface vorsieht, ist das egal.
Dann muss das halt durch das Repository entsprechend aufgelöst werden.

Sag ich die ganze Zeit. Die Implementierung "Ini" und "SQL" Repository müssen auf die gleiche Klasse Mappen. Das Repository muss also das Mappen übernehmen.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

709 Beiträge seit 2008
vor 5 Jahren

Wenn ich das richtig verstanden habe, geben beide Repositories geben ein Objekt zurück, das dem Data Access Layer zugehörig ist.
Das Mappen in entsprechende BL-Objekte übernimmt dann die BL-Schicht.

P
1.090 Beiträge seit 2011
vor 5 Jahren

Genau nur das wir für die Implementierung des Zugriff auf Ini, Access und SQL eigen Assemblys haben. Haben die Klassen auch ein eigenes Assembly. Man kann sie wenn man möchte noch den DAL zurechnen oder sagen es ist ein eigener Layer.

Im BL machen wir das Mappen auf BL-Objekte nur wenn wir es brauchen. Wir haben viele einfache CRUD Ansichten. Da ist in den einzelnen Schichten zu Mappen nicht unbedingt nötig.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern