2009-07-17 22 views
23

Po kilku latach śledzenia złej praktyki przekazanej przez "architektów" w moim miejscu pracy i myślenia, że ​​musi istnieć lepszy sposób, ostatnio czytałem o TDD i DDD oraz o mnie. uważam, że zasady i praktyki będą doskonale pasować do złożoności oprogramowania, które piszemy.TDD, DDD i enkapsulacja

Jednak wiele próbek TDD, które widziałem, wywołuje metodę na obiekcie domeny, a następnie testuje właściwości obiektu, aby zapewnić prawidłowe zachowanie.

Z drugiej strony, kilka szanowanych osób w branży (Greg Young najbardziej zauważalnie, dzięki swoim rozmowom na temat CQRS) opowiada się za całkowitym zamknięciem każdego obiektu domeny poprzez usunięcie wszystkich "pobierających".

Moje pytanie brzmi: w jaki sposób można przetestować funkcjonalność obiektu domeny, jeśli nie można odzyskać jego stanu?

Uważam, że brakuje mi czegoś fundamentalnego, więc proszę, nazwijcie mnie idiotą i oświećcie mnie - wszelkie wskazówki będą mile widziane.

+1

Hah, chciałem przeczytać nieco więcej o tym dyrektorze "no getters" po przeczytaniu tego posta ... i ten post był pierwszym wynikiem w Google. –

+0

Sądzę, że szukałem nazwy wzoru, który widziałem gdzie indziej. Najpierw obejrzałem film o separacji poleceń, która zalecała domenę tylko do zapisu i alternatywną ścieżkę do wysyłania zapytań do magazynu danych. Potem przeczytałem jeszcze kilka artykułów, które omawiały gettery naruszające hermetyzację itd. Może te terminy przyniosą lepsze wyniki wyszukiwania? – Justin

+0

Z twojego komentarza, myślę, że prawdopodobnie to, co usłyszałeś, było "nie-ustawicielami". Wiele osób uważa, że ​​ustawiacze naruszają hermetyzację.Zgadzam się ogólnie, że są nadużywane, ale w wielu przypadkach są nadal przydatne i konieczne. –

Odpowiedz

17

To, co opisujesz, to: weryfikacja stanu , w której potwierdzasz stan obiektu domeny. Istnieje gałąź TDD o nazwie weryfikująca zachowanie, która wykorzystuje obiekty Mock.

Weryfikacja zachowania pozwala określić, które metody powinny być wywoływane, a jeśli chcesz, które metody nie są wywoływane.

Przeczytaj ten artykuł Martina Fowlera, aby uzyskać więcej informacji: Mocks Aren't Stubs.

+0

Awesome - to dało mi dużo słów kluczowych do wyszukania i więcej materiałów do czytania! Dzięki za szybką i szybką odpowiedź. – Justin

+0

Przeczytaj na temat Martina Fowlera - napisał mnóstwo na ten temat i jest świetnym źródłem informacji. Również znalazłem Test-Driven Development By Example - Napisany przez Kent Becka jako dobry elementarz do TDD –

+0

Rozważałem książkę Kent Beck, ale niektóre recenzje, które widziałem (szczególnie Amazon) nie są aż tak korzystne. Czy to na pewno polecisz? – Justin

2

Kilka rzeczy.

Po pierwsze, kiedy robisz takie rzeczy jak TDD, aby twój kod mógł być przetestowany, skończysz z mniejszą klasą. Jeśli masz klasę z dużą ilością prywatnych właściwości, których nie możesz kontrolować, istnieje duża szansa, że ​​zostanie ona podzielona na wiele klas i stanie się bardziej testowalna.

Po drugie, oldschoolowa architektura OO stara się zapewnić bezpieczeństwo oprogramowania, stosując zabezpieczenia językowe, aby zapobiec dostępowi do danych. Architektura TDD sprawia, że ​​oprogramowanie jest bardziej niezawodne, pisząc testy, które sprawdzają, co faktycznie robi kod, kładąc mniejszy nacisk na używanie konstrukcji językowych, aby zapewnić to, czego program nie robi.

Po trzecie, sprawdzenie właściwości nie jest jedynym sposobem sprawdzenia poprawności kodu, który zrobił to, co powinien. Książka xUnit Design Patterns dokumentuje inne podejścia tutaj: http://xunitpatterns.com/Result%20Verification%20Patterns.html

+0

Dzięki za szybką reakcję - link jest niesamowity i zaczynam robić zdjęcie. – Justin

+0

Jeśli połączysz link, pokochasz książkę (przynajmniej zrobiłem). –

4

Jeśli naprawdę posuniesz się aż do zakazu pobierania państwa, będziesz ograniczony do testów behawioralnych, prawdopodobnie poprzez szydercze ramy, takie jak TypeMock, który ma moc śledzenia zachowania twojego obiektu. Jeśli jesteś w stanie zrobić czysty BDD, teoretycznie możesz potwierdzić poprawność całego systemu, tak jak zachowuje się on.

W praktyce okazało się, że BDD jest bardziej kruchy w wielu przypadkach niż tylko testowanie stanowe. Podczas gdy niektórzy ludzie mogą wymagać pewnej teorii, działa to tylko wtedy, gdy działa dla ciebie. Testy oparte na stanie nadal stanowią 90% wszystkich testów jednostkowych, które piszemy, i dobrze wiemy o BDD w naszym zespole.

Zrób to, co działa najlepiej.

2

To co wymieniłeś nazywa się testowaniem stanu. Są też testy zachowania. Stosowane techniki to iniekcja zależności, odwracanie sterowania i kpiny:

Wszystkie efekty uboczne twojej klasy są zaimplementowane jako wywołania metod w jej "zależnościach" - tj. Obiektach dostarczanych z zewnątrz, zwykle w konstruktorze. Następnie w teście jednostkowym dostarczasz fałszywy obiekt zamiast prawdziwego. Fałszywy obiekt może zapamiętać, czy została wywołana określona metoda i to jest to, co potwierdzacie w swoim teście.

Istnieje wiele Szokujących struktur, które automatyzują tworzenie obiektów pozorowanych przez dynamiczne generowanie klas implementujących dany interfejs. Najpopularniejsze są Rhino.Mocks i Moq.

+0

+1 W celu uzyskania zwięzłej odpowiedzi. Czy mógłbyś wyjaśnić, podając i przykład lub odwołanie do przykładu, w jaki sposób IoC byłby używany w ten sposób do śledzenia wywołań metod obiektu. Nie jest jasne, czy wstrzyknięte obiekty będą śledzić określone zewnętrzne wywołania metod na innych obiektach, czy też chodzi o śledzenie wewnętrznych wywołań metod na tym samym obiekcie lub obu. – jpierson

2

Hej, Justin, tak jak ty, ostatnio myślałem o dodaniu modułów pobierających do mojego obiektu tylko do zapisu dla celów testów jednostkowych, ale teraz jestem przekonany, że się myliłem. Zakładając, że w pierwszej kolejności kupiłeś ideę domeny tylko do zapisu, to jeśli masz w ogóle gettery, prosisz o kłopoty. Zasada domeny tylko do zapisu wymagałaby wywołania zdarzenia z obiektu domeny lub odczytu z projekcji, którą napisał obiekt domeny, lub czegoś podobnego. Kiedy ujawnisz gettery, zaczynasz eksponować "kształt" obiektu, a jak mówi Greg Young, "Obiekty domen mają Zachowanie, a nie Kształt".

Mówiąc to, zmagam się z tym samym pytaniem ... w jaki sposób testujesz obiekt domeny tylko do zapisu? Oto mój obecny plan: mam zamiar wywołać w moim obiekcie domenowym zdarzenie domeny, mówiąc: "Te właściwości się zmieniły", aw teście mojej jednostki zarejestruję się, zanim wyślę "EditCommand". Sprawdź posta Udi Dahana na temat wydarzeń w domenie here, a także zobacz what Eric Evans says about Domain Events.

1

Zastanawiam się, to samo, aż w końcu natknąłem się na następujące dokumenty. Znalazłem je za wielkie starterów na przeprowadzenie weryfikacji zachowań, zwłaszcza pierwszy dostarczenie mi kilka „aha chwile”:

  1. Using Mocks and Tests to Design Role-Based Objects
  2. Mock Roles, Not Objects
+0

linki są zepsute. Oto plik PDF dla drugiego elementu: http://www.jmock.org/oopsla2004.pdf i tutaj znajduje się link do większości pierwszego elementu: http://msdn.microsoft.com/en-us/magazine/dd882516.aspx – sivabudh

+0

Drugi link działa dla mnie, a pierwsze działa, jeśli zmienisz mockobjects.com na www.mockobjects.com – SCFrench

9

OK, to odpowiedź jest o rok za późno ;-)

Ale gdy chcesz przetestować modele CQRS, możesz tworzyć asercje na wywołanych zdarzeniach w domenie zamiast asercji na stanie encji.

np. , jeśli chcesz przetestować, czy wywołanie: customer.Rename ("Foo") powoduje prawidłowe zachowanie.

Zamiast testu, jeśli nazwa klienta.nazwa jest równa "foo", należy raczej sprawdzić, czy istnieje oczekujące zdarzenie CustomerRename o wartości "Foo" w oczekiwanym magazynie zdarzeń. (w twoim uow lub w twojej liście zdarzeń w zależności od implementacji)