Wpis z mikrobloga

Miałbym do Was kilka pytań o architekturę bardziej zaawansowanej aplikacji w Laravel.

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
  • 3
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

@kot1401: Zamiast pytać jak pisać klasy – zacznij pisać testy (jednostkowe).

Dlaczego? Bo wiele rzeczy TDD wymusza, które są pozytywne z architektonicznego punktu widzenia.
  • Odpowiedz