Jak połączyć ścisłe TDD i DDD?

15

TDD polega na projektowaniu kodu kierowanego testami.
Zatem typowe warstwy zwykle nie są budowane z góry; powinny nieznacznie pojawić się w ramach operacji refaktoryzacji.

Projektowanie oparte na domenie obejmuje wiele wzorców technicznych, definiujących dobrze ugruntowane warstwy, takie jak warstwa aplikacji, warstwa infrastruktury, warstwa domeny, warstwa trwałości.

Jak zacząć kodowanie projektu DDD od zera, jak się zachować?
Czy powinienem bezwzględnie pozwolić projektowi wyłonić się z testów, co oznacza brak oddzielenia problemów (bez warstw) i refaktora, aby dopasować wzorce techniczne DDD?

Czy też powinienem utworzyć te puste warstwy (aplikacje, podmioty / usługi domenowe, infrastrukturę) i pozwolić TDD zmieścić się w każdej z nich niezależnie (używając próbnych elementów do izolacji między warstwami)?

Mik378
źródło

Odpowiedzi:

12

Zapoznaj się z najnowszymi komentarzami wuja Boba na temat roli projektowania w TDD .

Projektowanie oparte na domenie obejmuje wiele wzorców technicznych, definiujących dobrze ugruntowane warstwy, takie jak warstwa aplikacji, warstwa infrastruktury, warstwa domeny, warstwa trwałości.

Udi Dahan: „Boże, jak nienawidzę nakładania warstw”. Poświęca trochę czasu na omawianie tego w swoim przemówieniu CQRS - ale Innym (nakładanie warstw zaczyna się od 18m30)

Przeliterowałbym twoje zdanie nieco inaczej; „DDD uznaje, że istnieje wiele problemów wspólnych dla większości aplikacji biznesowych i że rozwiązania tych problemów mają różne czasy życia” .

Na przykład obawy związane z domeną z reguły muszą być elastyczne - zwłaszcza, gdy dostosowujesz rozwiązanie do konkretnej firmy. W końcu domena dotyczy tego, w jaki sposób firma prowadzi działalność, to znaczy, w jaki sposób firma zarabia pieniądze, a możliwość szybkiego wprowadzania usprawnień biznesowych to darmowy przychód.

Z drugiej strony prawdopodobnie nie trzeba często zmieniać komponentu trwałości. Rozwiązanie bazy danych, które działało w ostatniej wersji, prawdopodobnie również będzie działać w tej wersji.

Obawy dotyczące aplikacji znajdują się gdzieś pośrodku; wydają się być stabilne, aby użytkownicy nie musieli uczyć się nowej aplikacji z każdym wydaniem.

Ponadto może istnieć wiele implementacji w celu rozwiązania danego problemu. Na przykład aplikacja może wymagać jedynie wykonania migawki bieżącego stanu - wystarczy zapisać plik na dysku. A w pierwszych kilku iteracjach może to być również wszystko, czego potrzebuje domena. Ale w końcu pojawia się historia, która wymaga obsługi zapytań ad hoc, i zdajesz sobie sprawę, że konfiguracja relacyjnej bazy danych będzie o wiele łatwiejsza niż implementacja jednej od zera. I jest jeszcze jedna funkcja, która działałaby lepiej w bazie danych grafów.

Tymczasem CTO chce wersji aplikacji działającej na jego telefonie; CEO właśnie usłyszał od faceta, że ​​publikowanie API jest najważniejsze.

Ponadto zespół sprzedaży korzysta z innego modelu, więc daj nam tę samą aplikację z innym modelem. Och, ale dużo podróżujemy, więc nasza wersja musi działać, gdy jesteśmy offline i synchronizujemy później ...

Innymi słowy, stosujesz wzorce taktyczne z nie poprzez wdrożenie pustych symboli zastępczych i zakładając, że zostaną wypełnione później, ale zamiast tego poprzez rozpoznanie, kiedy przekraczasz strumienie „Hej, to jest kod uporczywości w moim modelu domeny, nie mogę zakończono refaktoryzację ”.

VoiceOfUnreason
źródło
11

Test Driven Development (TDD) nie jest projektem. Jest to wymóg, który wpływa na Twój projekt. Tak jak gdybyś musiał być bezpieczny w wątku, to nie jest projekt. Ponownie, jest to wymóg, który wpływa na twój projekt.

Jeśli z radością zignorujesz wszystkie inne obawy związane z projektowaniem i religijnie będziesz przestrzegać zasad TDD, nie obwiniaj TDD, gdy twój kod zamieni się w bzdury. To będzie bzdura, którą można przetestować, ale to będzie bzdura.

Jedną fajną rzeczą w bzdurach testowalnych jest to, że to badziewka refaktowalna, więc dla niektórych osób jest wystarczająco dobra. Będziemy fantazyjni tylko w razie potrzeby. Inni nienawidzą tego i obwiniają za to TDD. Nie. To twoja robota.

Domain Driven Design (DDD) to coś, co robisz przed cyklem refaktora TDD w kolorze zielonym i zielonym.

DDD to próba utworzenia i zachowania przestrzeni w kodzie, w której ekspert w dziedzinie, który jest w dużej mierze nieświadomy szczegółów systemu, może zrozumieć, jak kontrolować system. Odbywa się to poprzez abstrakcję i modelowanie problematycznej dziedziny w znany sposób.

System DDD może mieć architekturę, która wygląda następująco:

wprowadź opis zdjęcia tutaj

Ta architektura DDD ma wiele nazw: czyste , cebulowe , sześciokątne itp

Oto rozłączenie, które widzę wielu ludzi, kiedy patrzą na ten projekt. To nie jest konkretne. Mogę podążać za tym projektem i nigdy nie napisałem niczego, co widzisz na schemacie. Widzę, że inni twierdzą, że musi istnieć obiekt przypadku użycia lub klasa encji. To zestaw reguł, które mówią ci, z kim możesz rozmawiać i jak.

Otóż ​​to. Postępuj zgodnie z zasadami tego projektu, a TDD możesz wyciszyć z serca. TDD nie obchodzi, z kim rozmawiasz. Dba o to, aby wszystko, co coś robi, mogło zostać sprawdzone za pomocą jednego kliknięcia. Nie, coś gdzieś jest zepsute. Mówi dokładnie, co jest zepsute.

Wciąż niejasne? Spójrz na diagram Controler- Use Case Interactor- Presenterw prawym dolnym rogu. Oto trzy konkretne rzeczy komunikujące się ze sobą. Jasne, że to DDD, ale jak tu dodać TDD? Po prostu kpij z konkretnych rzeczy. Prezenter musi otrzymywać informacje. PresenterMockKlasa byłby to dobry sposób, aby sprawdzić, że robi się to, czego oczekuje się dostać. Hand i napęd jak gdybyś był i masz dobry sposób na badanej jednostki ponieważ mock powie, czy to ma to, czego oczekuje się dostać.Use Case InteractorPresenterMockUse Case InteractorControllerUse Case Interactor

Spójrz na to. Zadowolony z TDD i nie musieliśmy wybiegać z naszym projektem DDD. Jak to się stało? Zaczęliśmy od dobrze oddzielonego projektu.

Jeśli używasz TDD do projektowania (nie tylko rozwoju ), otrzymujesz projekt, który odzwierciedla wysiłek włożony w to. Jeśli tego właśnie chcesz. Ale nigdy nie po to było przeznaczone TDD. To czego ostatecznie brakuje, z pewnością nie jest winą TDD.

TDD nie dotyczy projektowania. Jeśli musisz wprowadzić zmiany w projekcie, aby używać TDD, masz większe problemy niż testowanie.

candied_orange
źródło
Nigdy nie mówiłem, że TDD to projekt, ale chodzi o design.
Mik378
1
Wujek Bob kazał ci zaprojektować. Nie powiedział ci: „hej, jeśli pracujesz, kto dba o resztę”.
candied_orange
1
Jak już powiedziałem, po prostu przestrzegaj zasad, z którymi możesz rozmawiać. Czysta architektura nie jest czymś do dyskusji. Po prostu określ, w której jesteś części, i zastanów się, z kim i jak się komunikować. Jest bardziej zwinny niż myślisz. Następnie zapytaj, czy jest to testowalne przez TDD. Jeśli nie, zrobiłeś coś złego. Jeśli tak, mam nadzieję, że zwracałeś uwagę, ponieważ dobry projekt to coś więcej niż tylko testowanie.
candied_orange
6
Ugh ... Naprawdę nie mogę znieść błędnej nazwy „Test Driven Design”. Nadal musisz trochę zaprojektować, zanim zaczniesz błogo uderzać w klawiaturę, niezależnie od tego, czy piszesz testy.
RubberDuck
1
Aby zacytować wujka Boba na ten temat: „Musisz zaprojektować okres” . Kliknij tutaj, a jeśli jesteś zbyt niecierpliwy, aby przeczytać całość, wyszukaj te słowa. Przekonasz się, że Martin jest dość nieugięty, że TDD nie jest magiczną kulą i że musisz zaprojektować nie tylko swój kod, ale także testy, jeśli nie chcesz żyć w bardzo kruchej bazie kodu.
candied_orange
4

TDD zapewnia, że ​​Twój kod ma wszystkie niezbędne przypadki testowe napisane równolegle z programowaniem. Nie powinno to wpływać na projektowanie na wysokim poziomie. Pomyśl o tym więcej w pracy w okopach.

W DDD chodzi o projekty wysokiego poziomu, język między ekspertami i inżynierami domeny, mapowanie kontekstu itp. To powinno być motorem projektowania aplikacji na wysokim poziomie.

Oba są płytkimi wyjaśnieniami dwóch potężnych metodologii programowania. Ale pod koniec dnia naprawdę osiągają dwie bardzo różne rzeczy.

Zacznij od mapowania języka i kontekstu DDD, a potem, kiedy będziesz pisać kod, rozpocznij praktykę TDD. Ale praktyka TDD nie powinna wpływać na projektowanie na wysokim poziomie, ale powinna zapewnić możliwość przetestowania. Jest tu trochę zastrzeżenia.

Myślę, że może być ważne, aby pamiętać: powinieneś ćwiczyć DDD tylko wtedy, gdy aplikacja jest wystarczająco złożona.

Matt Oaxaca
źródło
1
Nie zgadzam się, TDD nie polega na testowaniu, ale na projektowaniu.
Mik378
Opieram wszystko na 3 zasadach TDD opisanych przez wujka Boba.
Matt Oaxaca
Steve Freeman, autor książki GOOS stwierdził: nie należy określać żadnych warstw ani infrastruktury przed rozpoczęciem cykli TDD.
Mik378
Nie znam tej książki, ale musiałbym się nie zgodzić. Nie chcę, aby TDD kształtował mój wykres DI i klas.
Matt Oaxaca
3
@ Mik378: TDD nie polega na testowaniu, ale przede wszystkim na projektowaniu - jedynym projektem indukowanym przez TDD jest projekt testowania jednostkowego. Każda inna część projektu musi pochodzić z innego miejsca. Widzę TDD bardziej jako technikę implementacji.
Doc Brown
3

DDD dotyczy projektowania oprogramowania.
TDD dotyczy projektowania kodu.

W DDD „model” reprezentuje de abstrakcję domeny, całą wiedzę eksperta w dziedzinie.

Możemy użyć TDD do początkowego modelu projektowania kodu. Domena ma reguły biznesowe i modele domen, które napisane w teście (pierwsze) powinny być zielone.

W efekcie możemy kodować testy po zaprojektowaniu modelu opartego na domenie.
Ta książka „Rosnące oprogramowanie zorientowane obiektowo, kierowane przez testy” link do zakupu
Podejdź do tego z chodzącym szkieletem , sześciokątną architekturą i TDD.

Źródło: szybko DDD - InfoQ

JonyLoscal
źródło
1
dla mnie oprogramowanie i kod to to samo
Konrad
1
To może być również to samo. Próbowałem powiedzieć: oprogramowanie jako „rozwiązanie”, „system”, „wysoki poziom” i kod jako „implementacja”, „niski poziom”, „szczegóły”.
JonyLoscal
Myślę, że ważne jest to, że „najpierw testujemy, ale potrzebujemy minimalnego szkieletu, w którym zaczynamy testowanie”. Czy ty?
JonyLoscal
1

Czy powinienem ściśle pozwolić projektowi wyłonić się z testów

Nie. (Domain Driven) Projektowanie z definicji powinno wynikać z wymagań domeny. To zły pomysł, aby pozwolić cokolwiek kierować projektem, czy to pakiet testów, schemat bazy danych, czy ... (ciąg dalszy)

Czy powinienem utworzyć te puste warstwy (aplikacje, podmioty / usługi domenowe, infrastruktura) i pozwolić TDD zmieścić się w każdej z nich niezależnie

(ciąg dalszy) ... lub niektóre kanoniczne warstwy klas / hierarchii klas w twoim ulubionym wybranym języku OO, nawet jeśli jest to bardzo dojrzały i popularny (w końcu „miliony much nie mogą się mylić”, prawda?) .

Jeśli chodzi o DDD, OOP nie spełnia wymagań dotyczących wyrażania w formie czytelnej dla człowieka, tj. Coś, co byłoby mniej lub bardziej jasne dla osób nieprogramujących. Języki FP ściśle wpisywane lepiej sobie radzą. Polecam przeczytać książkę o DDD przy użyciu programowania funkcjonalnego „Domain Modeling Made Functional” autorstwa Scotta Wlaschina

https://pragprog.com/book/swdddf/domain-modeling-made-functional

Nie musisz używać języka FP, aby pożyczać niektóre pomysły stamtąd (nie wszystkie niestety), ale jeśli faktycznie je przeczytasz, prawdopodobnie będziesz chciał użyć języka funkcjonalnego.

Odpowiada również na twoje pytanie o to, jak TDD pasuje do obrazu DDD. W skrócie, kiedy wymagania są kodowane w stylu funkcjonalnym, eliminuje to potrzebę ogromnej liczby testów jednostkowych, ponieważ sprawia, że ​​większość nieprawidłowych stanów i scenariuszy jest niereprezentatywna / niemożliwa do skompilowania. Oczywiście nadal jest miejsce na zautomatyzowane testowanie w projekcie FP, ale w żadnym wypadku testy nie będą prowadzić do żadnych poważniejszych decyzji projektowych.

Aby zrobić pełne koło, wróćmy do pytania tytułowego, tj. „Jak połączyć ścisłe TDD i DDD?”. Odpowiedź jest prosta: nie ma nic do połączenia / konfliktu interesów. Projektuj zgodnie z wymaganiami, rozwijaj zgodnie z projektem (pisząc najpierw testy, jeśli naprawdę chcesz wykonać TDD)

KolA
źródło
+1 za książkę FP DDD i ogólne wyjaśnienie.
Roman Susi