Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
hab eine Verständnisfrage. Irgendwie ergibt sich mir der Sinn eines DTO nicht. Ich könnte auch einen Constructor mit farbe, preis in Auto.java packen statt ein eigenes Objekt/Klasse dafür zu erstellen.
Ich habe 2 services, einen Datenservice welcher Daten aus der DB holt und bereit stellt und einen Shopservice, welcher Die Daten vom "Datenservice" holt, verarbeitet und an eine externe API schickt (zb Autoverkaufsportal oder sonst was)
Nun hab ich an einigen Stellen das Bedürfnis, nicht alle Daten eines Autos zu holen um Zeit und Last zu sparen. Zb fragt der Shopservice beim Datenservice nach einem Auto um dessen Preis und Farbe zu bekommen. Ich brauch an der Stelle nur die 2 Werte vom Auto und möchte nicht das gesamte Auto mit all seinen Relationen holen.
@Repository
public interface Repository..{
@Query("Select new com.domain.dto.AutoUpdateDto(a.farbe,a.preis) from Auto a where a.id = :id")
AutoUpdateDto getAutoUpdateDto(int id);
}
hab eine Verständnisfrage. Irgendwie ergibt sich mir der Sinn eines DTO nicht. Ich könnte auch einen Constructor mit farbe, preis in Auto.java packen statt ein eigenes Objekt/Klasse dafür zu erstellen.
Ich habe 2 services, einen Datenservice welcher Daten aus der DB holt und bereit stellt und einen Shopservice, welcher Die Daten vom "Datenservice" holt, verarbeitet und an eine externe API schickt (zb Autoverkaufsportal oder sonst was)
Nun hab ich an einigen Stellen das Bedürfnis, nicht alle Daten eines Autos zu holen um Zeit und Last zu sparen. Zb fragt der Shopservice beim Datenservice nach einem Auto um dessen Preis und Farbe zu bekommen. Ich brauch an der Stelle nur die 2 Werte vom Auto und möchte nicht das gesamte Auto mit all seinen Relationen holen.
@Repository
public interface Repository..{
@Query("Select new com.domain.dto.AutoUpdateDto(a.farbe,a.preis) from Auto a where a.id = :id")
AutoUpdateDto getAutoUpdateDto(int id);
}
DTOs werden dazu verwendet um die Übertragungsbreite zwischen UI und Service zu reduzieren. Es ist aber zu bedenken, dass die Konvertierung zwischen Domain Object und DTOs ein kostspieliger Prozess sein kann, was Onkel Bob hier erklärte: https://martinfowler.com/bliki/LocalDTO.html
Das ist nicht sicherstellen.
Im Moment wird das sicher funktionieren, aber Design technisch kannst du das nicht sicherstellen. Deswegen wird üblicherweise ein DTO verwendet.
Schlussendlich kannst du das aber machen wie du willst. Vielleicht wirds dir nie Probleme machen.
Eventuell hast du aber plötzlich NullPointer, weil du das unvollständige Objekt verwendest.
Das Problem ist nur - Dein Auto-Objekt hat nun aber zwei Verantwortlichkeiten:
a) Das fachliche Objekt in der Anwendung
b) Datenobjekt für den Service, wo viele Daten nicht gefüllt sind.
Das heißt, jede Methode, die ein Auto als Eingabe erwartet muss nun eigentlich genau prüfen, hat sie Auto a) oder ein Auto b) in der Hand? Du kannst damit generell aus rein architektonischer Sicht nicht davon ausgehen, dass bei einem Auto-Objekt mehr als Preis und Farbe gefüllt ist.
Klar gehst du aufgrund deines Codes aus, dass ein Auto-Objekt vom Typ b) nur in Richtung Service verwendet wird. Daher kann sowas funktionieren. Aber es verletzt halt das Single-Responsibility-Prinzip - deine Klasse ist nun für zwei Aufgaben zuständig
Es ist aber zu bedenken, dass die Konvertierung zwischen Domain Object und DTOs ein kostspieliger Prozess sein kann, was Onkel Bob hier erklärte: https://martinfowler.com/bliki/LocalDTO.html
Nur als Hinweis am Rande: der Text bezieht sich auf „Local DTOs“ und „Kosten“ meinen dort mehr als nur die reine Konvertierung.
Die reinen Konvertierungs-Kosten sind generell schon sehr gering, zusätzlich sind sie grad in diesem Fall, wo es um Rest-Schnittstellen geht, völlig vernachlässigbar, da alles andere um Größenordnungen langsamer ist. Bei rein lokalen DTOs sind die Kosten im Vergleich natürlich größer, in heutigen Systemen aber auch völlig irrelevant.
Die relevanten Kosten sind da eher der zusätzliche Code. Man muss das Model duplizieren (oder uU verdreifachen), man muss konvertieren, man schränkt die Schnittstellen ein, ....
Wenn es aber um Remote-Schnittstellen geht, grad auch wie in diesem Fall, wenn Enitäten nur teilweise benötigt werden, sind die Kosten es wert, bzw sogar geringer als der Verzicht auf DTOs. Den Performance-Nachteil durch die Konvertierung gleicht man dann auch zusätzlich wieder durch weniger zu übertragende Daten aus.
Und als drittes noch (ich verbreche grad mal bewusst gegen "keine Doppelposts", da es doch recht unterschiedliche Dinge sind):
Ich würde ich dieses Anwendungsfall nicht mal unbedingt von DTO sprechen. In diesem Anwendungsfall sieht es schon rein auf Domänen-Ebene nach einem eigenem Event aus, und nicht nach nur einer "Teil-Ansicht" der Entität, mindestens der Name spricht dafür (AutoUpdateDto). Es kann also durchaus Sinn machen, das auch auf Domain-Ebene auch explizit so zu modellieren.
Das hat dann natürlich noch andere Konsequenzen auf Architekturebene zur Folge, die sich aber uU durchaus positiv auswirken. Sowohl für den Service selbst, als auch alle abhängigen Services.
Warum das in dem Fall auch sinnvoll ist, kann man sogar an einem theoretischen Beispiel gut erklären. Angemommen, man würde das allgemeine Auto-Objekt nehmen, aber nur Preis und Farbe füllen und hätte folgenden Code:
Java:
public void sendeAnSchnittstelle(List<Auto> autos) {
autos.forEach(this::sendeEinzelAutoAnSchnittstelle);
}
Dann kommt die Anforderung "Mit Plattform X gibt es einen Exklusivertrag, VWs dürfen daher nicht mehr über diese Schnittstelle gesendet werden". Dies setzt ein Entwickler um, der die Historie nicht kennt:
Java:
public void sendeAnSchnittstelle(List<Auto> autos) {
autos.stream().filter(a->a.getMarke() != Marke.VW).forEach(this::sendeEinzelAutoAnSchnittstelle);
}
Er schreibt auch noch ein paar Unit-Testfälle für diese Methode, wo er mal die Marke VW und mal andere reinsteckt - klappt alles.
Tja, nur dumm das nachher, wenn es richtig läuft das Feld Marke nie gefüllt ist und daher auch VWs gesendet werden.
Hätte ich folgenden Code, wo die Klasse AutoPreisFarbeDto nur die Felder Preis, Farbe und ggf. eine ID um die Verknüpfung zum kompletten Objekt herstellen zu können.
Java:
public void sendeAnSchnittstelle(List<AutoPreisFarbeDto> autosDto) {
autosDto.forEach(this::sendeEinzelAutoAnSchnittstelle);
}
Dann kann der Entwickler an der Stelle keinen Fehler machen, sondern muss entweder die Selektion direkt anpassen oder das DTO erweitern und die Felder füllen.
So vermeidet - vor allem in größeren Projekten, wo die Software über Jahre gewartet und weiterentwickelt wird, Fehler.
Klar könnte man das im JavaDoc dokumentieren, aber dann müsste man das an jeder Methode, die ein Auto bekommt wo nur Preis und Farbe gefüllt sind machen - was den Aufwand erhöht. Und zum anderen gilt im Sinne von Clean Code - wenn ich Dokumentation brauche um meinen Code zu erklären, ist der Code meist nicht sauber. Man sollte nichts über Kommentare dokumentieren, was man auch durch sauberen Code ausdrücken kann.
Also ist das so richtig wie ich das vor habe? Die Fehlerprävention mit dem Filter ist ein gutes Beispiel danke.
BTW auf Ud*my sind grad alle Kurse reduziert, kennt jemand Kurse im Bezug auf Spring (Boot) und die DTO Geschichte, die ich unbedingt kaufen sollte? Ich deck mich gleich mal für das restliche Jahr ein
BTW auf Ud*my sind grad alle Kurse reduziert, kennt jemand Kurse im Bezug auf Spring (Boot) und die DTO Geschichte, die ich unbedingt kaufen sollte? Ich deck mich gleich mal für das restliche Jahr ein
Also ist das so richtig wie ich das vor habe? Die Fehlerprävention mit dem Filter ist ein gutes Beispiel danke.
BTW auf Ud*my sind grad alle Kurse reduziert, kennt jemand Kurse im Bezug auf Spring (Boot) und die DTO Geschichte, die ich unbedingt kaufen sollte? Ich deck mich gleich mal für das restliche Jahr ein
Ich habe mir am Anfang hier auch ein paar Videos zugelegt. Wenn du des englischen mächtig bist, dann kann ich dir für den Anfang von Spring
(persönlicher Favorit) John Thompson: Spring Framework 5: Beginner to Guru
Er erklärt schon viel und gründlich, allerdings muss man definitiv sagen "Guru" ist hier übertrieben, da Spring sehr sehr viele unterschiedliche Module zur Verfügung stellt und er wirklich nur die wichtigsten Module ausführlich erklärt. Was z.B. fehlt ist sind Module wie z.B. Spring Cloud - Diese Module brauchst du als Einsteiger aber auch nicht. Ich würde den Titel eher umbenennen in "Beginner to Advanced"
Weitere nennenswerte Tutoren wären
Chad Darbey: Spring & Hibernate for Beginners
Chad geht auch schon etwas tiefer rein, deshalb find ich "Beginners" ist etwas untertrieben. Aber es kommt halt immer auf die Definition an was sind Beginners, was sind Fortgeschrittene, was sind Experten und was sind Gurus.
und 28minutes (allerdings letzter ist Inder und hat dem entsprechend ein indisch-englisch drauf)
28minutes bin ich schon Stammkunde 😂 John thomsen hab ich mir genau den Kurs gekauft und zusätzlich noch einen mit spring Boot. Hab dummerweise mit Boot begonnen statt mit dem normalen spring Kurs.
Der originäre Sinn besteht darin, die Objekt-Kommunikation (über das Netzwerk) zu minimieren.
In den Anfängen von Java EE (J2EE, wie es damals noch hieß) war es durchaus nicht unüblich, neben local auch remote EJBs zu verwenden, bei denen Methodenaufrufe in einen Netzwerkaufruf mit entsprechendem Overhead übersetzt wurden. Wurden also 5 Getter aufgerufen, führte dies zu 5 Anfragen über das Netzwerk und damit zu 5 x Latenzzeit plus Overhead. Stattdessen wurde ein DTO eingeführt, das mit einer einzigen Antwort des Servers an den Client geschickt wurde.
Dieser ursprüngliche Hauptzweck ist weitestgehend entfallen, weil man vom Paradigma der Remote Procedure Calls abgekommen ist, und man sich an Ressourcen orientiert hat. Da die Darstellung einer Ressource implizit ein DTO ist, braucht es dafür natürlich auch kein Pattern mehr.