@somekind: Co do testów to się nie czepiam. Co do rozbijania tego na pierdyliard klas i interfejsów to już jest coś czego lubię się czepiać. Dlaczego powinno się to tak szczegółowo rozbijać (oprócz testów)? Czytelność kodu? Jak rozbije to na kilka klas to nie mam całego bagna z logiką w jednym miejscu?
Masz logikę w jednym miejscu, interakcję ze źródłem danych w innym, a z miejscem zapisu w innym. To trochę tak jak w domu - piwo trzymamy w jednym miejscu, brudne skarpetki w innym, samochód w jeszcze innym.
Dzięki temu jest czytelnie - jeśli mam błąd związany z pobraniem danych z API, to szukam w klasie pobierającej dane z API, a nie w spaghetti kodzie, w którym odczyt, zapis i sterowanie wymieszane są razem.
Co miałeś na myśli z tym Product<UseCaseName>
? Jak to praktycznie wykorzystać, bo chyba nie rozumiem?
No bardziej może <UseCaseName>Product
, np. ImportProduct
, CreateProduct
, GetProduct
. Chodzi o to, aby zamiast jednej klasy ProductService
, która odpowiada za wszystkie przypadki użycia związane z produktami, ma około 15 tys linii kodu i 200 zależności, mieć zestaw małych klas, z których każda jest krótka i ma tylko te zależności, których faktycznie potrzebuje.
Wszystko i tak sprowadza się do wstrzyknięcia każdego z UseCase'ów
do kontrolera
Tak, no chyba, że użyjemy wzorca mediator i np. biblioteki MediatR. Wówczas mamy tylko jedną zależność w kontrolerze, do mediatora wysyłamy polecenie związane z danym przypadkiem użycia, a on wywołuje odpowiedni kawałek kodu odpowiedzialny za realizację tego przypadku użycia.
Aby przetestować działanie drzewa decyzyjnego nie potrzebuję ani połączenia a ActiveDirectory ani z bazą. Potrzebuję natomiast przygotować sobie różne scenariusze, tj zestawy danych dla których wiem w jaki sposób powinien zachować się system - co jest opisane w wymaganiach biznesowych, specyfikacji czy jakkolwiek zostanie to nazwane. W ten sposób będąc w pełni odizolowanym od tych zewnętrznych zależności mogę przetesować każdy interesujący mnie wariant.
Jeśli nie użyłbym mocka żadnego rodzaju to byłbym w pełni zależny od konfiguracji zarówno AD jaki i bazodanowej.
To zależy od tego, co to drzewo robi:
- jeżeli wynikiem działania drzewa są jakieś dane, to sam algorytm można wydzielić do jednostki zależnej jedynie od danych wejściowych i ją przetestować bez używania mocków.
- jeżeli wynikiem działania drzewa są interakcje z zewnętrznymi zależnościami dokonywane w trakcie przetwarzania danych, to mocki w testach są przydatne.
Mam wrażenie, że fanatycy nieużywania mocków w ogóle nie zdają sobie sprawy z tego, że może istnieć kod, którego wynikiem działania nie są dane lecz interakcje. Jakby zaczęli swoje światłe idee implementować w życiu w systemie tego typu, to szybko by zmienili zdanie (albo się bardzo męczyli w imię bezsensownej ideologii).
Z drugiej strony wielu ludzi nawet nie myśli o tym, że w wielu przypadkach można wydzielić kod przetwarzający dane od kodu operującego na zależnościach i elegancko testować go jednostkowo bez mocków. I też się męczą tracąc czas na mockowanie, którego mogłoby nie być.