php wzorce projektowe, dziedziczenie, klasy abstrakcyjne, interfejsy

0

Witam, mam kilka męczących mnie kwestii dotyczących wzorców projektowych oraz programowania OOP.
Chcę napisać jakąś sensowną aplikację w PHP - wiem ilu "anty-zwolenników" jest od PHP (więc może omińmy temat "sensowna aplikacja w PHP") - do mnie to nie do końca trafia. Przejdźmy do kwestii.

Załóżmy, że chcę zbudować sobie moduł do obsługi plików - np. niech będzie to .XML, .INI czy choćby .YML

Kwestia 1: (struktura katalogów)

Nazwa Modulu

  • Klasy
    -- Klasa XML
    -- KLASA INI
    -- KLASA YML
  • Klasy Abstrakcyjne
    -- Klasa Abstrakcyjna
  • Interfejsy
    -- Interfejs 1
    -- Interfejs 2

Czy taka struktura będzie odpowiednia ? - Na moje oko będzie to w miarę czytelne.

Kwestia 2: (klasy abstrakcyjne)
Wiadomo, że chodzi o plik, ale nie wiadomo jaki będzie to plik, więc mógłbym stworzyć sobie klasę abstrakcyjna np o nazwie ,,File".
W klasie stworzę metodę getExtension(), która pobiera rozszerzenie pliku.
Teraz klasa XML jest w stanie dziedziczyć po klasie abstrakcyjnej metodę getExtension() i sprawdzić czy podany plik posiada na pewno rozszerzenie XML - uwolniłoby mnie to od tworzenia tej metody dla każdej klasy.

Ale jakie będzie rozwiązanie, gdy zajdzie potrzeba odziedziczyć coś po innej klasy ? Odetnę sobie skrzydła ponieważ odziedziczyć mogę tylko po jednej klasie.
Czy takie rozwiązania mają sens ? Czy może przy mniejszych projektach nie warto tworzyć klas abstrakcyjnych ?

Kwestia 3: (interfejsy)
Biorąc pod uwagę nadal powyższy przykład, mógłbym zrobić interfejs, w którym zdefiniuje getExtension() i implementować go dla poszczególnych klas - tylko po co jeśli w powyższym przykładzie będzie lepiej zastosować klasę abstrakcyjną, która dostarczy już daną metodę.
Jakie jest dobre zastosowanie interfejsów w PHP ? - W chwili obecnej mam wrażenie, że jest to dobre rozwiązanie jeśli oddajemy jakiś projekt, a jedna (lub więcej) z klas podczas użycia będzie w potrzebie utworzenia kilku metod. (świetnym przykładem okazała, by się tutaj Java i klasa, która implementuje np. MouseListener).

Kwestia 4: (wyjątki)
Wiadomo, że w zależności od tego co wystąpi, chciałbym zwracać jakiś błąd, komunikat, etc.
Nie lubię zwracać stringów - np.

return "wszystko ok"; 
  • bezsensu.
    Jestem zwyczajny zwracać kody błędów, komunikatów.
    Do tej pory robiłem to sobie (zazwyczaj) w jakiejś klasie, gdzie nazwie zmiennej (statycznej) odpowiadała kodowi np. 04.
    Do tego robiłem stosowny słownik w innej klasie np. TA_SAMA_NAZWA_ZMIENNEJ_TXT = komunikat wypluty dla użytkownika.

W jednym pliku mogę stworzyć klasę, a w niej wszystkie wyjątki dla danego modułu (czyli klas XML, YML, INI) wiadomo, że będzie to mniej przejrzyste. W moim punkcie widzenia nie byłoby sensu, a żeby tworzyć każdą klasę wyjątków, a w niej takowe kody błędów etc.
Może właśnie tutaj z pomocą przychodzą interfejsy ? W folderze "Interfejsy" można dodać folder "Exception" i umieścić w nim interfejsy np. z końcówką "Exception", a każda klasa by implementowała dany interfejs.

Jak to mądrze rozwiązać - wydaje mi się, że na bazie interfejsów byłoby to w miarę czytelnie zrobione - są jednak i wady:

  1. ilość plików
  2. dodatkowy folder
  3. klasa już na start musi implementować jakiś interfejs.

PS. A może nie próbować odkrywać koła na nowo i po prostu w klasie zrobić zmienne const ?

Kwestia 5: (wzorzec projektowy)
Jaki wzorzec projektowy byłoby warto zastosować np. do aplikacji sieciowej ?
Mianowicie:
Uruchamiamy skrypt ---> skrypt wczytuje dane konfiguracyjne o serwerze, porcie
Skrypt podłącza się do serwera ---> słucha jakie polecenie dostaję (np. stwórz plik o nazwie "start.xml") (oczywiście też dostałby takie polecenie danym kodem np. "55").
Skrypt odwołuje się do modułu tworzenia plików .XML ---> dzięki metodzie, która znajduję się w klasie tworzy plik.
W razie potrzeby skrypt wypluwa coś do konsoli ---> JEŚLI zachodzi taka potrzeba.

Kwestia 6: (trait)
Od PHP 5.4 dostaliśmy "funkcję" korzystania z trait. Wygląda to bardzo podobnie do "wielokrotnego dziedziczenia".
Jednak nie spotkałem, się jeszcze, by ktoś korzystał jakoś specjalnie z tego "geniuszu".
Jak sądzicie - czy warto z tego korzystać - i w jakich sytuacjach skoro tak ?

Z góry dziękuje za wszystkie odpowiedzi!

0

Na razie tylko na temat traitów. Dla mnie to dziwny dodatek do OOP, mam mieszane uczucia. Korzystałem w sytuacji gdy:

  1. Mieliśmy zdefiniowane kilkadziesiąt małych klas w jednej przestrzeni (żeby dane reprezentować obiektami)
  2. Klasy te (poprzez wspólną publiczną metodę zwracającą wynik) wywoływały po 3-4 metody ze zbioru powiedzmy 20 metod, w bardzo dowolnej kombinacji
  3. Metody wyprowadziliśmy do powiązanych tematycznie traitów i zależnie od potrzeb każda klasa implementowała swój zestaw od jednego do kilku traitów.

Wyszło nawet spoko ale i tak potworzyliśmy klasy bazowe dla tych, które wykorzystywały te same traity. Ostatecznie wyszła niewielka różnica.

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