Was sind die Vorteile? Gibt es Nachteile?
Ein ValueObject ist allein durch seine Attribute definiert und nicht durch eine ID. Ein ValueObject ist immer immutable. Andere Werte = anderes Objekt.
Der Code wird lesbarer
Map<Long, String>
lässt nicht erkennen, um was für eine Map es sich handelt.
Map<PersonId, PhoneNumber>
macht deutlich, um welche Objekte es sich in der Map handelt.
Verhindert falsche Verwendung
Dies würde kompilieren und keinen Fehler werfen
Police(String vsnr, String pid) {}
new Police("pid", "vsnr");
Um eine Verwechslung zu vermeiden sollte man ValueObjects verwenden. Dann würde es einen Compile Fehler geben.
Police(VSNR vsnr, PoliceId pid) {}
new Police(pid, vsnr);
Weniger Anpassung bei Änderung der internen Repräsentation
Wenn sich die interne Repräsentation ändert, ist der äußere Code davon nicht betroffen. Wenn z.B. bei einer Versicherungsnummer (VSNR) bisher ein Long verwendet wurde und daraus jetzt ein String wird, weil sich der Aufbau der ID verändert hat, muss das ValueObject selbst angepasst werden. An den Stellen, wo das Objekt übergeben wird, muss es nicht angepasst werden.
Kapselung der Validierung
Die Prüfung, ob es sich um ein valides Objekt handelt, erfolgt im ValueObject selbst. Es muss / kann nicht mehr mehrere Stellen geben, an denen diese Validierung stattfindet bzw. stattfinden kann. Der Entwickler findet sie an der gesuchten Stelle und kann sie ggf. anpassen, wenn sich daran etwas ändert.
Bei der Erstellung des ValueObjects wird vorher geprüft, ob es gültig ist. Nur dann wird ein Objekt zurückgegeben. Ein ValueObject ist immer gültig.
Zusammenfassung
Vorteile:
- Typsicherheit
- hiding implementation
- Logik an einer Stelle
Nachteil:
- Es entstehen mehr Klassen, die aber meist recht übersichtlich sind