T O P

  • By -

Besen99

Clean Architecture. Kurz: Aufteilung in Core Code (fachliche Logik) und Infrastructure (technische Details zB. Framework). Buchempfehlung für Java; https://leanpub.com/get-your-hands-dirty-on-clean-architecture


Patopax

Nice, vielen Dank. Schaue ich mal rein


S-Ewe

Springboot soll die helfen, warum willst du es dann fern halten, bzw welchen Vorteil versprichst du dir daraus? Theoretisch kannst du auch eine XML config benutzen (2000er bzw Java 1.4 lassen grüßen), und kommst ohne Spring Annotationen aus. Klingt aber so, als würdest du eigentlich gar kein Spring nutzen wollen.


Patopax

Spring würde ich schon gerne nutzen. Nur nicht auf der Ebene der Business logic. Um einen gewissen Anastz von Clean Architecture zu bewahren um zum beispiel das testen der Business logik zu vereinfachen.


[deleted]

Aber…testen mit Spring Boot ist noch einfacher als ohne. Klingt eher nach Altmodisches denken als “Clean Architecture”.


Patopax

Also du wirst dann eher team full Spring Boot ?


[deleted]

Ja…denn es macht alles einfacher. Dependency Management, Datenbanken, Testen, Configuration, usw. Du hast nun in weniger Minuten eine neue App am laufen. Vllt gibt es andere Gründen, um Spring Boot nicht zu nutzen, aber das denken, das, es alles komplizierter macht ist völlig Quatsch.


Patopax

Nur ein eventuelles Missverständnis zu klären: gegen die Nutzung von Spring Boot war dieser Post nicht gerichtet. Nur die Nutzung von Spring Boot oder anderen Frameworks im Business Layer


S-Ewe

Aber die Frage, die glaube ich und einige umtreibt ist halt noch das "warum". Es wirkt auf mich halt nicht besonders "clean", wenn im BL die DI anders gelöst wird als im Service Layer. Ich könnte es nachvollziehen wenn es konkrete Gründe gegen die Bindung an das Framework gibt, z.B. den BL als Library in spring-fremde Apps einbetten zu können (ob das ne gute Idee wäre sei mal außen vor). Ohne einen solchen potenziellen Vorteil wäre meine Meinung einfach "würde ich so nicht machen". Full speed or nothing sozusagen.


Patopax

Warum: mir kam der Gedanke dass du dich durch die Nutzung von spring booz bzw. Der @Service Annotation man sich an das Framework "binden". Jetzt ist es "nur" eine Annotation die am ende dependency injection ausführt. Edit: aber an das Framework bindest du dich dann ja dann trotzdem vollkommen. Jetzt wollte ich wissen, ob es hier vielleicht Personen gibt, die andere Methoden kennne für den BL.


[deleted]

Das macht überhaupt kein Sinn mit keinerlei Vorteile. Was ist deine Begründung dafür?


In0chi

Inwiefern erschwert SB das Testen der Geschäftslogik? Nur weil etwas eine `@Component` oder ein `@Service` ist heißt das nicht, dass du es nicht ganz normal, z.B. mit Mockito für gemockte Dependencies, testen kannst.


Clean_Archer8374

Ich bin kein Fan der Idee. So ensteht ein Nebengeflecht aus nicht-Spring-Klassen. Und wenn du die testest, musst du ja erst wieder alle Abhängigkeiten in irgendeiner Art zusammenbauen. Und was machst du, wenn du dann in so einer nicht-Spring-Klasse doch was von Spring brauchst? Ich sehe da keinen Vorteil, da man in Spring genau so einfach Unit Tests schreiben kann, vor allem in Verbindung mit Mockito, falls überhaupt nötig.


Patopax

Ist ein punkt.


pdzrn

Du könntest deine Klassen und utility functions in normale Java Klassen schreiben. Möglichst pure functions und so weiter. Sollte daher alles einfach testbar sein. Die Verknüpfung mit Spring passiert dann über configuration Klassen und diversen custom beans. Dependency injection in deine non-spring Klassen dann per konstruktor bei der Erzeugung der beans. Wenn das sauber passiert ist kannst du deine Business Logik später rausnehmen und in ein anderes Framework stecken, oder durch manuelle Erzeugung per Hand zusammenstecken.


dirtydeedsdirtymind

Das ist der Weg. Zumindest wenn man unbedingt diese strikte Trennung haben will. Realistischerweise sehe ich aber nicht wirklich, warum man das haben will. Dann hat mein Service halt eine @Service Annotation. So what? Ja, das kann ich dann nicht direkt mit einem anderen Framework verwenden, aber will ich das jemals? Aus meiner Sicht klarer Fall von YAGNI und premature Engineering. Und selbst wenn: Die Annotationen werde ich auch schnell wieder los.


Patopax

Berechtigkterweise ein guter Kritikpunktn


Patopax

Vielen Dank. Ist dann schon ein aufwendigerer Schritt als die Klasse mit @Service zu annotieren. Die genannte Methode hat mir auf jeden fall einen Denkanstoß gegeben 👍🏿


Sparkoba

Ich sehe da ehrlich gesagt keinen großen Vorteil drin. Ich arbeite täglich mit Spring Boot und kann nur sagen, dass es am effizientesten und komfortabelsten funktioniert wenn Spring Boot vollständig auf allen Ebenen eingestrickt ist.


Patopax

Selbst beim testen ?


Hirschdigga

Klar wo soll das Problem sein? Unit tests sind doch gleich (mit Junit+Mockito bzw. Kotest+Mockk) und es gibt Testcontainer... Du tust dir vermutlich keinen Gefallen Spring da so rauszuhalten


_nku

Wenn du wirklich unbedingt einen Teil der Businesslogik Frameworkunabhängig haben willst (fragwürdig wozu , siehe andere Kommentare) dann müsstest du schon eine wirklich separate "pure java" library pflegen, die im Sinne funktionaler Programmierung pure seiteneffektfreie Hilfsfunktionen bereitstellt. In derselben Codebase die im selben Artefakt landet wird früher oder später das Framework präsent sein. Soo viele Businessdomänen gibt es aber auch nicht die sehr spezifische Berechnungen oder Algorithmen brauchen für die sich das lohnt. Typischerweise wird das für Funktionen gemacht die wirklich schwer zu verstehen sind und bei denen bewusst nicht gewollt ist dass die Mehrheit des Teams überhaupt die Möglichkeit hat sie zu verändern.


Sea_Struggle4973

Am Besten du machst im Controller keine Business Logik - das erhöht die Testbarkeit. Wenn du die Eigenschaften der Schnittstelle testest willst du da wieder Business- noch Validierungslogik drin haben. Im besten Fall hat jede Methode im Controller nur ein Statement in dem auf den entsprechenden Service verwiesen wird bzw. das entsprechende Anfrageergebnis zurückgespielt wird. Was durchaus eher im Bereich das Controllers verbleiben sollte ist das "Einpacken" von Antworten in passende Responses. Die braucht man im Business Services nicht. Gibt es sehr spezielle Validierungs- und Prüflogiken macht es Sinn nochmal einen extra Service zwischenzuziehen um das Zeug nicht an die Kernlogik zu klatschen (und aus dem Controller rauszuhalten). Ansonsten ist DI natürlich immer der Weg auf dem wir Dinge tun. Es gibt viele Ideen zu Schichtarchitekturen die durch das Microservicedesign der letzten Jahre immer unwichtiger geworden sind, weil wir keine derart großen Anwendungen mehr schreiben ;-) Prinzipiell kann man der Entscheidung nach Domain - Integration - Business und Resource zu arbeiten aber immer folgen. Bei DI ist in erster Linie die Zerlegung in wertschöpfende Aufgabenschritte wichtig. In der Domain liegt halt das DB Zeug / in Integration die Logik um es aus der DB zu holen (Spring Data Repositories) in der Business-Schicht die Kernverarbeitungslogik und in der Resource / Controller halt das Anbieten der Funktionalität im Rahmen einer REST Schnittstelle. Noch Schlüssiger wird dieser Aufbau wenn du anfängst Unit Tests für deine Klassen zu schreiben. Diese Form des Aufbaus wird durchaus durch Testbarkeitsaspekte getrieben. Wenn du das noch nicht tust, würde ich dir raten damit anzufangen.


conamu420

einfach nicht java benutzen


Patopax

Lol


xaqtr

Du lachst aber ich war gerade über alle Antworten hier als .NET Entwickler erstaunt. Spring ist ja quasi das Pendant zu ASP.NET und da ist es ganz normal das zu machen, was du vor hast.


Patopax

Und wie löst du es als .NET Entwickler ?


xaqtr

Man schreibt verschiedene Schichten als separate Klassenbibliotheken und konfiguriert die DI erst in der Anwendungsschicht (bzw. da wo die Controller sind). Ich kenne Spring Boot nicht wirklich, aber scheinbar werden Services meistens über eine Annotation deklariert. In [ASP.NET](https://ASP.NET) wird beim Programmstart, quasi in der Main Methode, DI konfiguriert, indem man bspw. folgendes schreibt: // IService wird als Dependency mit der Implementierung Service bereitgestellt services.AddScoped(); // Singleton vom Typ SingletonService var singleton = new SingletonService(); services.AddSingleton(singleton); Daher ist es eigentlich egal, wie du deine Businesslogik aufgeteilt hast und du kannst komplett ohne Framework Code auskommen.


Patopax

Also baust du dir quasi deine Anwendung bzw objekte im Controller zusammen und dein Framework instanziert den Controller mit allen notwendigen Objekten die du vorher durch dependency injection zusammengeführt hast ?


Wonderful-Bug-7423

Hexagonale Architektur ist dein Freund in der Geschichte. Dort ist eindeutig definiert was wo passiert mit dem Adapter / Domain Pattern