2010-11-01 22 views
5

Rozumiem, że nie powinniśmy bezpośrednio zmieniać elementów potomnych agregatu-root, ale zamiast tego powinny być one wykonywane za pomocą metod znajdujących się na głównym katalogu głównym. E.g. order.SetOrderLineQty(product, qty);Uzyskiwanie dostępu do podzbiorów należących do agregatów

Ale co, jeśli dzieci agregatu-root są czymś abstrakcyjnym? Wyobraź sobie, że masz główny agregat samochodów, który zawiera listę IWheel jako część agregatu. Jak dodać/zmienić właściwości koła poprzez jego agregat-root (kto nic nie wie o konkretnym typie koła)?

Bardziej realistyczny przykład: Lekarz może utworzyć MedicalRerport (root-root), który zawiera listę IMedicalNote (jako część agregatu MedicalReport). IMedicalNote to interfejs bazowy/interfejs, który jest podzielony na kilka podklas konkretnych, np. BloodCheckNote, TemperatureNote, MineralConcentrationNote, itp.

Każda podklasa ma różne właściwości i wszystkie są edytowalne. Agregat MedicalReport może zawierać jedną lub więcej dowolnych z tych notatek. (Każda podklasa nut ma określoną kontrolę użytkownika, aby użytkownik mógł wprowadzić/zaktualizować szczegóły, pokazane jako panele/zakładki pod dużym ekranem MedicalReport)

Moje pytanie brzmi: jak mogę dodać/edytować właściwości tych zauważa dokładnie poprzez swój agregat-root (MedicalReport)? Ponieważ nie wolno mi bezpośrednio zmienić te notatki właściwości, jedną z opcji brzydki jest poprzez wystawienie wszystkie możliwe właściwości Uwaga o łącznej root (MedicalReport), tj:

report.SetWhiteBloodCellCount(cellCount); 
report.SetBloodCheckComment(comment); 
report.SetTemperature(bodyPart, temperature); 
report.AddMineral(mineral, concentration); 

Każda z tych metod będzie aktualizować (lub utworzyć nowy) notuj przedmioty w jego wewnętrznym zbiorze dzieci. Są 2 oczywiste problemy z tym związane:

  1. Musimy zdefiniować z góry wszystkie dostępne właściwości wszystkich możliwych podklas IMedicalNote w katalogu głównym agregatu. Jest to niedopuszczalne, ponieważ liczba podklas ma szansę rosnąć, zależy to od rodzaju danych medycznych, które chcemy uchwycić, co jest najważniejszym punktem dziedziczenia na pierwszym miejscu.
  2. Na liście może znajdować się wiele wystąpień tego samego rodzaju notatki. Ten interfejs API zawiedzie, ponieważ nie możemy po prostu powiedzieć: report.SetBloodCheckComment(comment) i oczekujemy, że zaktualizuje on element BloodCheckNote na liście, ponieważ zezwalamy na więcej niż jedną pozycję BloodCheckNote na liście.

ja nadal chce utrzymać wszystkie interakcje na te notatki za pośrednictwem swoich łącznych-root, ponieważ ma kontrolować, czy cały agregat MedicalReport jest ważne, aby być zbawiony, czy łączna nie jest modyfikowalne, gruboziarnisty optimistic- kontrola współbieżności itp. Ale jak mogę to zrobić?

Odpowiedz

4

Zastanawiam się, czy źle interpretujesz wskazówki dotyczące zagregowanych źródeł (a może ja to zrobiłem ...).

Nigdy nie przeczytałem wskazówek mówiących: "agregat musi zapewniać metody zastępcze dla każdej możliwej własności wszystkich jej zagregowanych obiektów". Raczej myślę, że mówi: "agregat kontroluje cykl życia, tożsamość i relacje z jego zagregowanych obiektów".

Jest więc całkowicie uzasadnione, aby klient poprosił agregat o (przejściowe) odniesienie do jednego z jego obiektów i zrobił coś z nim.Ja nie mam kopię DDD tutaj, aby potwierdzić treść, ale to wydaje się zgodne z DDD summary ebook (p53), który mówi:

Możliwe jest korzeniem przekazać przemijające referencje do obiektów wewnętrznych zewnętrzne, pod warunkiem, że zewnętrzne obiekty nie zawierają odniesienia po zakończeniu operacji.

Tak więc, w przypadku klientów byłoby zapytać MedicalReport na przykład (y) IMedicalNote, wracaj podtypy, działają na nich odpowiednio i przejść z powrotem do korzeni, jeśli dotyczy.

Jak już wspomniałem: nie mogę powiedzieć na pewno, że jest to zgodne z DDD, ale zdrowy rozsądek mówi, że jest to rozwiązanie bardziej skalowalne i elastyczne niż próba odzwierciedlenia każdej właściwości/metody każdego podtypu w zagregowanym źródle głównym.

hth.

+0

Rozumiem, że można odzyskać obiekt wewnętrzny (IMedicalNote), ale tylko w celu tylko do odczytu. Nie powinieneś dokonywać żadnych modyfikacji. Wszystkie modyfikacje muszą być dokonywane poprzez root, aby mógł kontrolować integralność. Co masz na myśli, przekazując je z powrotem do katalogu głównego? Kiedy zmienimy własność dziecka zewnętrznie, to to jest, zmieniło się (przez odniesienie), omijając root, czyż nie? Co dokładnie oznacza "przejście z powrotem do korzenia"? – Sheepy

+0

Przepraszam, odpowiedz nieco niejednoznacznie. Root przekazuje kopie obiektów, które klient następnie aktualizuje i przekazuje z powrotem do katalogu głównego. Root następnie odpowiedzialny za sprawdzanie niezmienników i tworzenie relacji. Zapewnia rozsądny podział odpowiedzialności: root wie o relacjach i ograniczeniach między zagregowanymi obiektami, ale nie musi znać szczegółów wszystkich podtypów. Klienci mogą operować na określonych podtypach zgodnie z wymaganiami. Uwaga: Root może potrzebować znać pewne szczegóły podtypu (np. Jeśli musi zawierać dokładnie jeden "BloodCheckNote", ale może mieć wiele "TemperatureNote"). – sfinnie

+0

Masz na myśli stworzenie mechanizmu klonowania tak, aby root zawsze przekazywał klon każdego znaku-potomka, gdy uzyskuje się dostęp za pomocą publicznego getera root'a? A następnie sposób na skopiowanie tych wartości z powrotem do rzeczywistego obiektu, gdy klient zwróci te dzieci z powrotem do katalogu głównego. Chciałem tylko wyjaśnić, czy to właśnie miałeś na myśli, ponieważ brzmi to jak trochę pracy. Pozdrawiam – Sheepy

Powiązane problemy