Cześć, z tego co rozumiem, to Agregaty są jednostkami pracy hermentyzującymi reguły biznesowe. Czyli mówiąc po chłopsku zawiera on wszystkie pola, które potrzebujemy aby wykonać w środku całą ifologię i obliczyć wymagany wynik - nie więcej. Dzięki temu też zyskujemy wysoką kohezję klasy, czyli w idealnym przypadku wszystkie metody korzystają ze wszystkich pól tej klasy (wiadomo, że ciężko osiągnąć 100% tego, ale wiadomo o co chodzi).
Do ładowania sobie agregatów (najczęściej za pomocą jakiś ID) służą natomiast Repozytoria.
Mamy sobie standardowe wymaganie biznesowe aby dodać produkt do zamówienia. Sobótka zrobił to tu https://bottega.com.pl/pdf/materialy/ddd/ddd1.pdf (mówię o str. 45) w ten sposób, że ładuje encje
produktu z ProductRepository
, ładuje agregat
zamówienia czyli Order
z OrderRepository
i do Orderu
dodaje ten załadowany product
pod spodem wykorzystując jakieś mapowanie JPA, czyli @ManyToOne. Nie pasuje mi tu bardzo to, że z tego co wyczytałem to repozytoria służą do ładowania i zapisywania agregatów, a nie encji. Jeśli mamy sobie fasadę jako wejście do modułu to nie powinno ono zawierać tylko jednego repozytorium związanego z agregatem? Bo ten jego kod z kilkoma repozytoriami zaczyna wyglądać jak kandydat na 8tysięcznik, gdzie serwis ma 10 repozytoriów.
Czy to nie powinno wyglądać tak, że agregat Order
wygląda raczej w tym stylu jak ponizej? (kod będzie w Javce)
public class OrderLine {
private String productId;
private int quantity;
}
public class Order {
private final Set<OrderLine> orderLines;
public void addProduct(int quantity, String productId) {
// logika sprawdzenia ilości i ewentualnego dodania nowego id do listy
}
}
W agregacie mamy już załadowane dane o produktach, które potrzebujemy do ifologii w środku i zapisujemy po prostu czystą informację biznesową czyli productId wraz z ilością. Czy to nie tak powinno wyglądać? Agregat Product
zawiera wyłącznie to co potrzebuje i potem pod spodem sqlka z updatem też będzie mniejsza.
Druga sprawa o którą chciałem dopytać to granice agregatów. Załóżmy, że użytkownik może dodawać i updatować jakiś Item do sklepu internetowego. Mamy sobie taki agregat:
public class Item {
private ItemId id;
private Title title;
private Description description;
private ItemStatus status;
private Price price;
private LocalDateTime soldDate;
public Item(ItemId id, ItemUpdateForm form) {
this.id = id;
this.title = form.getTitle();
this.description = form.getDescription();
this.status = ItemStatus.NEW;
this.price = form.getPrice();
this.soldDate = null;
}
public void update(ItemUpdateForm form) {
this.title = form.getTitle();
this.description = form.getDescription();
this.price = form.getPrice();
}
}
No i pewnie większosć powie, że to nie jest agregat, bo generalnie nie ma żadnych reguł biznesowych.
Ale zaraz dodamy jakąś metodę biznesową z logiką, coś np jak:
public void markAsSold(TimeService timeService) {
if (status != ItemStatus.SOLD && status != ItemStatus.BLOCKED) {
status = ItemStatus.SOLD;
soldDate = timeService.now();
}
}
I co, to już się nagle robi agregat, bo jest w tym logika biznesowa?
Chyba, że Item
powinienem zostawić jako jakiś prosty obiekt i nie myśleć o nim w kategoriach agregatu, a do zarządzania stanami wydzielić jakiś osobny obiekt, który już będzie agregatem? No bo faktycznie metoda markAsSold
i inne typu markAsBlocked
nie będą prawdopodobnie potrzebowały w ogóle takich pól jak title czy description.
Jak to wtedy jest?
Bambo