Czy obiekty domeny w projekcie opartym na domenie mają być tylko do zapisu?


13

Czytam o projektowaniu opartym na domenach od prawie dwóch lat i ostrożnie wprowadzam pewne koncepcje do mojej codziennej pracy lub przynajmniej planuję, jak rzeczy, które robię regularnie, mogą być wykonane w ramach projektu opartego na domenach.

Jeden wniosek, do którego zacząłem dochodzić, szczególnie w odpowiedzi na więcej informacji o pozyskiwaniu zdarzeń i segregacji odpowiedzialności za zapytania (CQRS), że być może obiekty domeny są przeznaczone wyłącznie do zapisu. Mówiąc dokładniej, wydaje się, że to, co ludzie subtelnie sugerują w dużej części dokumentacji, przeczytałem, że obiekty domeny są odpowiedzialne za wykonywanie operacji / obliczeń ukierunkowanych na domenę, sprawdzanie poprawności, a następnie są tam głównie po to, aby zapewnić drogę do trwałości poprzez infrastruktura zapewniona w ramach implementacji repozytorium. Chociaż podoba mi się fakt, że może to znacznie uprościć model domeny, ponieważ eliminuje odpowiedzialność za ujawnianie stanu.

Jeśli rzeczywiście jest prawdą, że obiekty domeny mają być głównie używane jako obiekty tylko do zapisu, to rodzi się dla mnie kilka pytań, na które mam nadzieję, że ktoś mógłby odpowiedzieć.

  1. W jaki sposób wykonuje się testy jednostkowe na obiekcie, który ma obiekty ustawiające lub metody, które modyfikują stan obiektu, ale nie zapewniają zewnętrznego publicznego interfejsu do odczytu stanu z takich obiektów, jak obiekty pobierające właściwości w języku C #? Czy można udostępniać stan wyłącznie w celu umożliwienia testowania tego obiektu?
  2. W jaki sposób pokazuje się użytkownikowi wyniki obliczeń lub operacji wykonanych w domenie bez konieczności ich utrwalania, a następnie wyciąga wyniki ze sklepu trwałego poza kontekstem domeny? Czy można wystawiać stan wyłącznie w celu pokazania wyników?

Czy jest ogólna zasada, że ​​jedynymi obiektami pobierającymi właściwości (uzyskującymi akcesoria) powinny być takie, które można również zapisywać w domenie? Lub inaczej mówiąc, czy własności tylko do odczytu powinny być jedyną rzeczą, której należy unikać, ponieważ są one tylko do celów odczytu, a zatem nie odgrywają niezbędnej roli w rzeczywistym modelu domeny?

Powiązany materiał:

  1. TDD, DDD i enkapsulacja

Odpowiedzi:


9

Nie jestem pewien, czy istnieje „jedna prawdziwa droga” dla podejścia projektowego, które, mówiąc uczciwie, wciąż ewoluuje. Po pierwsze, DDD i CQRS to nie to samo, chociaż wydaje się, że ludzie z CQRS wywodzą się z punktu początkowego, na który wpływa DDD.

W sposobie myślenia DDD wiele się dzieje i wiele z nich ma związek z właściwie zdefiniowanymi granicami problemów, komunikacją między interesariuszami i interakcją między systemami, niekoniecznie konkretną implementacją w kodzie, więc nie sądzę, aby być zbyt trudnym- rdzeń jest cnotą.

Być może widzisz część debaty na temat tego, czy i jak obiekty domeny powinny być zmienne oraz jaką funkcję obiekt domeny pełni w systemie jako całości. CQRS dzieli system na ścieżki odczytu i zapisu, więc rozsądne jest stwierdzenie, że tak naprawdę nie potrzebujesz dostępu do odczytu, gdy jesteś na ścieżce zapisu. Czytanie staje się wtedy czymś, co robisz na tle zdarzeń wywoływanych przez niektóre obiekty domeny i konsumowanych (obsługiwanych) przez inne. Jeśli cofniesz się nieco w historii CQRS, znajdziesz argumenty, że obiekty domeny nie powinny mieć ustawiających, tylko pobierających i pojedynczej metody „obsługi”. Logika jest taka, że ​​tylko zdarzenia konsumujące powinny powodować zmianę stanu, a zmiana ta jest całkowicie obsługiwana wewnętrznie przez obiekt domeny.

Pokazujesz wyniki zmiany, traktując je jako osobne artefakty zmiany, umieszczając je w osobnej, płaskiej trwałej strukturze (np. Tabeli) i czytając je tak, jakbyś tylko czytał raport o bieżącym i historycznym stanie systemu . Na przykład możesz wykorzystać zdarzenie, wyodrębniając dane, które musisz odczytać, i zapisując je w tabeli bazy danych, która jest ściśle odwzorowana na pojedynczy widok (np. Ekran) twojego systemu.

Jeśli eksperymentujesz z tym stylem, pamiętaj, że inni programiści prawdopodobnie nie będą zaznajomieni z tym podejściem i że istnieje stosunkowo niewiele (ale interesujących) scenariuszy, w których jest to uzasadnione jako podejście projektowe.

W przypadku testów jednostkowych możesz zastosować kilka metod. Pierwszym i najbardziej naturalnym jest sprawdzenie, czy zdarzenia, które spodziewasz się wywołać przez obiekty domeny, są prawidłowe. Obiekt domeny może wywoływać zmienione ogólne zdarzenie przechowujące informacje o zmianie. Możesz to zweryfikować. Możesz zweryfikować fakt, że zdarzenie zostało w ogóle podniesione, a inne zdarzenia nie zostały podniesione.

Innym podejściem jest użycie szpiegów testowych, które ujawniają czytelne atrybuty na obiekcie domeny, aby można było zweryfikować zmiany stanu. Na przykład możesz odziedziczyć po obiekcie domeny, dodać niektóre akcesoria, aby przeczytać stan, który w innym przypadku byłby zamknięty, i sprawdzić, czy jest poprawny.

Znowu jesteś zdezorientowany, ponieważ te podejścia są mylące. Jeśli chcesz wprowadzić dobre pomysły do ​​swojego programowania, najpierw weź soczyste kawałki. Granice DDD i wyraźne role są zmianami w sposobie myślenia o komunikacji z kodem. CQRS co najmniej sugeruje, że odczytywanie danych i zapisywanie danych to operacje segregowalne. Ten wgląd prowadzi cię do bardzo jasnego myślenia o roli danych, które musisz przedstawić, ile naprawdę potrzebujesz, kto je spożywa, jak świeże musi być, itd. ... Nie potrzebujesz pełna implementacja Event Sourcing w celu lepszego kodowania w enkapsulacji. Możesz zacząć od skupienia się na operacjach atomowych w swoim obiekcie, „podejmij, nie pytaj” podejście do projektowania interfejsu obiektu,


1
+1 za rozpoczęcie od jucy bitów. Dodatkowo: odgrywanie tylko CQS (na razie pomijanie części „wydarzenia”) może być dobrym miejscem do rozpoczęcia.
cottsak

1

Czy obiekty domeny w projekcie opartym na domenie mają być tylko do zapisu?

Nie. CQRS może być używany obok DDD.


Ale czy kwerenda w CQRS dotyczy kwerendy o dane, które są używane przez model domeny do zapisywania zmian w modelu, czy może służyć do kwerendy o dane dla warstwy aplikacji, która mogłaby powiedzieć, że pokazuje wartości użytkownikowi? Słyszę od niektórych, że w DDD chodzi o koordynowanie zmian i nie należy go używać do czytania w żadnym innym celu niż do koordynowania zmian w innym obiekcie w modelu domeny. Taka czy inna decyzja oznaczałaby radykalnie inny projekt modelu, biorąc pod uwagę, że ujawnione dane na obiektach domeny będą się różnić w ograniczonym zakresie, jeśli zostaną wykorzystane tylko w domenie.
jpierson

0

Testy jednostkowe modelu domeny powinny sprawdzać, czy dla każdego wykonanego polecenia zgłaszane są prawidłowe zdarzenia domeny. Polecenia domeny i przechwycone zdarzenia można przesłuchać pod kątem stanu.

Możesz również zastąpić ToString()polecenia i zdarzenia w domenie, aby zapewnić automatyczne, czytelne dla człowieka raportowanie stanu.

Aby odpowiedzieć na drugie pytanie, aby wyświetlić wyniki poleceń, należy zaplanować, aby zdarzenia domeny były „publikowane” w modelu odczytu.


Czy mógłbyś nieco wyjaśnić, czy nadal ma to zastosowanie, gdy nie korzystasz z pozyskiwania zdarzeń?
jpierson

1
Być może bez pozyskiwania zdarzeń moja sugestia nie zadziała; Nie znam sposobów twojego kodu. W przypadku obiektu domeny, który idealnie nie ujawnia żadnych właściwości, być może możesz jawnie zaimplementować interfejs testowy, który udostępnia właściwości, które chcesz przetestować. Tylko Twój kod testowy będzie „wiedział”, aby rzutować takie obiekty domeny na interfejs testowy.
Ed James

Dziękuję za tę sugestię. Nie podoba mi się pomysł zmodyfikowania moich klas domen specjalnie pod kątem testowalności, ale przypuszczam, że może to być jeden z tych szarych obszarów w dalszym ciągu w projektowaniu opartym na domenach, jeśli chcesz, aby był testowany. Inna myśl jest taka, że ​​jeśli ktoś ujawnia stabilność i testowalność poprzez ten sam interfejs, to przynajmniej wprowadza się tylko jedną zależność od infrastruktury zamiast dwóch. Co sądzą o tym inni?
jpierson
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.