Prośba o "zadanie domowe" z SOLID (na bazie Symfony).

0

Witam,

zwracam się z nietypową prośbą związaną z moją samodzielną edukacją.

Posiadam doświadczenie z Symfony 2 i dwukrotne z Symfony 3. Nauczyłem się korzystać m.in. z technik:

  • automatycznego tworzenia CRUD,
  • dependency injection (serwisy),
  • rozszerzenia do twig,
  • adnotacje m.in. w doctrine,
  • FormType,
  • Security Voters,
  • ...

Czeka mnie kilka tygodni urlopu zdrowotnego (około miesiąca) i chciałbym umieć po tym okresie czasu coś więcej niż pisać CRUD'y.

Czy zadałby mi ktoś konkretne zadanie w którym mógłbym się nauczyć koncepcji S.O.L.I.D., a może nawet stosowania wzorców projektowych?
Czy ktoś mi podpowie jaki rodzaj aplikacji byłby dla mnie odpowiedni?
Przykładowe aplikacje:

  • Forum - jestem raczej za słaby nawet by wspierać gotową instancję (sprawdzałem na Coyote i phpBB).
  • Blog - czy dużo by mnie nauczyło z SOLID, czy to jedynie coś podobnego jak CRUD?
  • ...

Z góry dziękuję za wszelkie podpowiedzi i rady,
pozdrawiam

1

Możesz utworzyć aplikację, która będzie zarządzała powiadomieniami. Wymagania:

  • powiadomienia mogą być wysyłane różnymi kanałami. SMS, email, dzwoneczek (np. tak jak tutaj na forum).
  • każde powiadomienie jest wyświetlane w systemie jako dzwoneczek i dodatkowo powinna być możliwość określenia jakimi dodatkowymi kanałami poza głównym może zostać wysłane:
    • powiadomienie o złożeniu zamówienia przez kanał email
    • powiadomienie o planowanym terminie doręczenia zamówienia przez kanał SMS i email
  • użytkownik powinien mieć możliwość wyboru jakimi kanałami chce otrzymywać powiadomienia. Może wyłączyć kanał email i sms, wtedy powiadomienie trafia tylko do głównego kanału, czyli do bazy.
  • SMS nie mogą być wysyłane w godzinach ciszy nocnej. Dla uproszczenia przyjmijmy, że jeżeli ktoś spróbuje to zrobić, to po prostu olewamy kanał SMSowy.
  • aplikacja powinna udostępniać API z następującymi endpointami
    • Dodanie użytkownika do systemu: imię, nazwisko, email, telefon, respektowane kanały powiadomień -> zwraca ID użytkownika
      POST /api/users
    • Możliwość pobrania powiadomień dla danego użytkownika po ID użytkownika -> zwraca wysłane powiadomienia
      GET /api/users/1/notifications
    • Możliwość wysyłki powiadomienia dla użytkownika po ID
      POST /api/users/1/notifications i w body dane potrzebne do wysyłki konkretnego powiadomienia razem z typem
  • Cały moduł powiadomień powinien być możliwy do wyjęcia z aplikacji. To znaczy, nie możesz mieć zależności na encji User i pokrewnych. Nie możesz mieć żadnej logiki w kontrolerach. One powinny tylko używać interfejsów wystawionych przez twój moduł.
  • Aplikacja nie musi mieć frontendu, wszystko ogarniesz przez API :)

Dodatkowe uwagi:

  • moduł powinien być łatwo rozszerzalny o kolejne kanały powiadomień, np. integracja ze Slackiem.
  • moduł powinien być łatwo rozszerzalny o kolejne powiadomienia, np. powiadomienie o opóźnieniu w wysyłce
  • powinna być możliwość łatwego przełączania między implementacjami wysyłki SMS. Na przykład masz klasę (DummySmsSender), która ma metodę send i loguje SMS do pliku. W przyszłości bez modyfikacji klasy, która wywołuje tą metodę powinieneś móc podmienić DummySmsSender na przykład na SMSApiSender.

S - każda klasa/metoda modułu powinna mieć pojedynczą odpowiedzialność, np. nie wrzucasz do jednej klasy wysyłki wszystkimi kanałami

O - to wynika z pierwszego. Jeżeli wszystko zapakujesz do jednej klasy, to klasa nie będzie zamknięta na modyfikacją, bo żeby dodać kolejny kanał będziesz musiał ją zmodyfikować.

L - Tutaj możesz się nadziać przy wysyłce różnymi kanałami w trakcie ciszy nocnej. Pamiętaj, że LSP mówi: "preconditions cannot be strengthened in a subtype."

I - zależy od kodu i Twojej architektury :)

D - To Ci załatwia podmiana implementacji SmsSender z tego co loguje do pliku na tego, co wysyła prawdziwe SMSy. I przy okazji załatwia Ci tez OCP. Jeżeli nie zrobisz tego dobrze, to przy podmianie implementacji będziesz musiał zmodyfikować klasę, która używa SmsSendera.

Wzorce, które mogą (ale nie muszą) Ci się przydać:
https://designpatternsphp.readthedocs.io/en/latest/Behavioral/Specification/README.html (ten w uproszczeniu, czyli same klasy z isSatisfiedBy i pętla)
https://designpatternsphp.readthedocs.io/en/latest/Behavioral/Strategy/README.html
https://designpatternsphp.readthedocs.io/en/latest/Structural/Adapter/README.html
https://designpatternsphp.readthedocs.io/en/latest/Structural/DependencyInjection/README.html
https://designpatternsphp.readthedocs.io/en/latest/Structural/Facade/README.html
https://designpatternsphp.readthedocs.io/en/latest/Creational/FactoryMethod/README.html
https://designpatternsphp.readthedocs.io/en/latest/Creational/SimpleFactory/README.html

0

@Desu dzięki za odpowiedź. Podoba mi się to zadanie, chociaż prawdę mówiąc jeszcze nie wszystko jest dla mnie jasne - w najbliższych dniach będę jeszcze zadawał pytania.

1 użytkowników online, w tym zalogowanych: 0, gości: 1