Dependency Injection – Refaktoryzacja projektu

Kontynujemy dział o dependency injection, w tym artykule będziemy refaktoryzować kod z poprzedniego wpisu a jak pamiętamy tamten kod nie był zbyt przyjazny do czytania, testowania i rozbudowy. Dzisiaj postaramy się to zmienić 🙂

 

Najpierw musimy zrefaktoryzować ten kod, żeby mieć co wstrzykiwać, więc można dojść do wniosku, że jak używamy dependency injection to i spełniamy zasady solid co znaczy, że dependency injection niejako sugeruje nam przestrzeganie tych zasad.

Na początek zobaczmy jak się zmieniły klasy postaci, czyli klasy Thief, Mage, Barbarian, Paladin i tak jak pamiętamy w tamtym przykładzie te klasy dziedziczą po klasie konkretnej a nie powinny. Nawet ośmielę się pomyśleć, że nie mogą, amen.

Zobaczmy jak można sobie z tym poradzić. Przy przykładach poprawionego kodu będe też mówił co w następnym artykule z poprawionego kodu będziemy jeszcze poprawiać(trochę masło maślane…) już za pomocą dependency injection 🙂

Żebyś nie musiał patrzeć do poprzedniego artykułu jak te klasy wyglądały wkleje je tutaj, wyglądały one tak:

A teraz zmieniliśmy je na coś takiego:

Jak widać teraz te klasy implementują interfejs, więc zależą teraz od abstrakcji oraz zmienne są lepiej zahermetyzowane dzięki zaimplementowanemu interfejsowi.

Przejdźmy do rozdawania punktów umiejętności po wybraniu klasy.

Kod przed zmianami z poprzedniego przykładu wygląda tak:

No to jest jakaś tragedia 😥 ta metoda robi więcej niż jedną rzecz, więc będzie ciężka do zrozumienia i do rozbudowy oraz jest ona bardzo cieżka do testowania.

A teraz kod po zmianach:

Czy to nie wygląda lepiej? Wszystkie instancje klas postaci są wydzielone do jednej klasy tak jak powinno być, więc mamy porządek o wiele łatwiej jest to zrozumieć i przetestować.

Jednak to jeszcze nie jest to co bym chciał, tworzymy instancje wszystkich klas postaci a jak wiemy użytkownik wybierze tylko jedną klasę, ale my nie wiemy jaką oraz są metody odpowiadające oddzielnie za rozdanie umięjętności dla każdej klasy. Nie lepiej byłoby utworzyć tylko jedną klasę, którą będzie używał użytkownik oraz tylko jedną metodę rozdającą umiejętności?

W następnym artykule zobaczysz jak dependency injection ułatwia życie 🙂

Zobaczmy jak wyglądają testy do tej klasy.

Sprawdzamy umiejętności po wybraniu klasy, testy dobrze jest pisać dla metod, które przyjmują jakieś argumenty i jakieś zwracają, ale u nas jest wyjątek bo te metody operują na dwóch zmiennych oraz u nas cały kod jest uporządkowany, wystarczy wywołać metody rozdające punkty umiejętności i sprawdzić całkowitą ilość umiejętności w klasie postaci, którą wybraliśmy, więc w dalszym ciągu te metody są łatwe do przetestowania.

Jednak jest dużo tych testów gdyby była tylko jednak metoda odpowiadająca za rozdanie punktów umiejętności to testów byłoby dwa. Ale spokojnie wszystko to zrobimy w następnym artyule za pomocą dependency injection 🙂

Metody walidujące hasło oraz login przyjmują oraz zwracają argumenty, więc właśnie w ten sposób jak opisałem powyżej napiszemy do nich testy.

Bez testów można czasem się zdzwić czemu i co po zmianie nie działa…😐

Zobaczmy, więc jak wyglądają klasy do walidacji loginu i hasła.

Kod do walidacji hasła i loginu przed zmianami.

Tu też jest tragedia 😥 wszystko wrzucone do jednej metody, ciężko się to czyta, też strach tu coś ruszać bo do tego nie da się napisać testów. 😐

Zobaczmy teraz jak to wygląda po zmianach. Podzieliłem to na dwie klasy walidujące osobno hasło i login.

Klasa walidująca hasło:

Oraz klasa walidująca login:

To już wygląda o niebo lepiej 🙂 , walidacja hasła i loginu zostały wydzielone do osobnych klas co jest bardziej czytelne i łatwiejsze w rozbudowywaniu oraz łatwe do przetestowania. Zobaczmy jak wyglądają testy do nich.

Testy do klasy LoginValidator

I testy do klasy PasswordValidator

I teraz zobaczymy czy wszystkie testy przechodzą do walidacji loginu oraz hasła jak i do testów sprawdzających poprawne rozdanie punktów umiejętności.

Jak widać przechodzą 🙂

Lepiej zadbać, żeby po napisaniu 100 linijek kodu wszystko działało 🙂

Na koniec zobaczmy główną klasę GameServer

W metodzie RegisterUser(), jeśli metody walidujące login i hasło zwrócą nam warunek true, rejestrujemy użytkownika, jeśli, któraś z metod zwróci false, wyświetlamy błąd.

W metodzie CreateCharacter(), w zależności od przekazanej klasy postaci rozdajemy punkty umiejętności. Można by w tej metodzie użyć wzorca Strategia, żeby pozbyć się tych if-ów, ale jest inny lepszy sposób również z dependency injection związany. To również w następnym artykule 🙂

W konstruktorze przekazujemy obiekty klas, których potrzebujemy, ale przekazujemy je do typów klas konkretnych czego nie powinno się robić.

Jest sposób, żeby te obiekty wynikały z abstrakcji, ale o tym w następnym artykule.

I klient, który korzysta z klasy GameServer.

Chciałem wyświetlić punkty umiejętność przed jak i po rozdaniu, żeby wszystko było zrozumiałe.

Wynik:

 

Podsumowanie

W następnym artykule będziemy już używać technik dependency injection i jeszcze bardziej zrefaktoryzujemy ten kod.

Link do githuba ze wszystkimi przykładami:  https://github.com/Slaw145/Dependency-injection–refactored-game-project

Standardowo, przypominam o newsletterze, którym wysyłam powiadomienia o nowych wpisach oraz dodatkowe informacje na temat, ogółem mówiąc, świecie IT.

KONIECZNIE dołącz do społeczności DevmanCommunity na fb, części społeczności jest w jednym miejscu 🙂

-strona na fb: Devman.pl-Sławomir Kowalski

-grupa na fb: DevmanCommunity

Pytaj, komentuj pod spodem na końcu wpisu, podziel się nim, oceń go, rób co wolisz🙂

Do następnego! Do zobaczenia 🙂

 
Jeśli ten wpis ci się przydał podziel się nim ze swoimi znajomymi :)

Post a comment

Be first!

avatar
  Subscribe  
Notify about