Aktywne Wpisy
board_of_trustees +194
Jarczur +84
Zaraz czeka mnie najpewniej zmiana pracy (100% zdalnie), a też żyćko mnie zmusiło żeby wynieść się z mojego dotychczasowego "biura" w sypialni - więc musiałem sobie ogarnąć nową dziuplę w domu do roboty.
Skromnie, meble ikea, ale przynajmniej wreszcie podnoszone biureczko.
#chwalesie #pokazbiurko #pracbaza
Skromnie, meble ikea, ale przynajmniej wreszcie podnoszone biureczko.
#chwalesie #pokazbiurko #pracbaza
Obecnie mój projekt obfituje dziesiątki antywzorców, takich jak trzymanie logiki i walidacji danych w kontrolerze, brak obiektowości itd. itp.
Chciałbym to wszystko jak najszybciej zrefaktoryzować do wzorca "Repository Pattern".
Co prawda, w internecie jest mnóstwo artykułów na temat Repository Pattern w Laravelu, ale każdy różni się nieco od pozostałych, brakuje też jakichś bardziej zaawansowanych przykładów.
Stworzyłem 3 repozytoria, pobierające dane z modeli Eloquent:
EloquentAirplaneRepository (zwraca dane o samolotach należących do danej linii lotnicznej - wiek, model, nr rejestracyjny itd.)
EloquentAirplaneModelRepository (zwraca informacje o modelach samolotów - prędkość, cena, zasięg itd.)
EloquentAirlineRepository (zwraca informacje o linii/liniach lotniczych - stan konta, nazwa itd.)
Powyższe repozytoria implementują interfejsy:
AirplaneRepositoryInterface
AirplaneModelRepositoryInterface
AirlineRepositoryInterface
Następnie stworzyłem klasę BackendServiceProvider, w której w metodzie register() będę bindował interfejsy do repozytoriów.
PYTANIE 1: Czy mogę bindować wszystkie repo z w tej jednej klasie (BackendServiceProvider)? Czy też lepiej stworzyć 3 klasy ServiceProvider dla każdego repo oddzielnie (AirplaneServiceProvider, AirlineServiceProvider, ...)?
Po tych operacjach mogę już wstrzykiwać repozytoria do kontrolerów i np. wyświetlić wszystkie samoloty danej linii.
Teraz chciałbym stworzyć możliwość zakupu modelu samolotu przez linię.
PYTANIE 2: Jak to zrobić od strony architektury?
Wiem, że muszę stworzyć serwis, który sprawdzi:
- czy linia ma wystarczające fundusze do zakupu wybranego modelu
- czy wpisane dane (np. numer rejestracyjny nowego samolotu) się walidują
Po czym, jeśli te warunki zostaną spełnione, tworzymy nowy samolot: AirplaneRepo->create() i obciążymy konto linii lotniczej kosztem zakupu: AirlineRepo->decreaseFunds().
PYTANIE 3: Jak nazwać taki serwis i jakie powinien mieć metody? BuyAirplaneModelService, AirplaneModelService czy może AirplaneService z metodą buy()?
PYTANIE 4: Jak uruchomić taki serwis z poziomu kontrolera i jak przekazać mu potrzebne repozytoria?
Na prędko naszkicowałem taki serwis, ale chyba nie powinno tak to wyglądać:
class BuyAirplaneModelService
{
public function __construct(AirplaneRepositoryInterface $airplaneRepository)
{
$this->airplaneRepository = $airplaneRepository;
}
```public function buy(AirplaneModel $airplaneModel, Airline $airline, array $input){ if($this->airline->funds < $airplaneModel->price) { throw new NotEnoughFundsException("Brak wystarczających środków do zakupu tego samolotu."); } if((($input['seats_economy'] * Config::get('game.seat_space.e')) + ($input['seats_business'] * Config::get('game.seat_space.b')) + ($input['seats_firstclass']*Config::get('game.seat_space.f'))) > $airplaneModel->seats_capacity) { throw new NotEnoughSeatsCapacityException("Wybrałeś zbyt dużo foteli. Brak miejsca w kadłubie."); } $airplane = $this->airplaneRepository->create($input); return $airplane;}```
}
#laravel #php #programowanie #busineslogic #wzorceprojektowe #repositorypattern
Dlaczego? Bo wiele rzeczy TDD wymusza, które są pozytywne z architektonicznego punktu widzenia.