Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> App pod kątem PHPUnit i dobrej praktyki OOP
trzczy
post 11.09.2016, 19:50:55
Post #1





Grupa: Zarejestrowani
Postów: 460
Pomógł: 49
Dołączył: 5.06.2011

Ostrzeżenie: (0%)
-----


W aplikacji jest kilka klas implementujących ten sam interfejs.

W dalszym opisie będę te klasy nazywał "tymi klasami"

Każda z tych klas ma metody, które musi posiadać ze względu na wymóg zawarty w interfejsie. Oprócz tego każda z tych klas korzysta z kilku metod, takich samych dla każdej z tych klas.

I teraz pytanie: jak udostępnić te wspólne metody dla każdej z tych klas?

Jest kilka możliwości:

1. Te klasy dziedziczą metody wspólne dla tych klas po klasie abstrakcyjnej, która te metody deklaruje.
2. Te klasy używają wspólnego trait z tymi metodami wspólnymi dla tych klas.
3. Specjalny obiekt zawierający wspólne dla tych klas metody wstrzykiwany jest do instancji każdej z tych klas.
4. Instancja każdej z tych klas wstrzykiwana jest do instancji pewnej specjalnej klasy, która posiada te metody wspólne dla tych klas.

A może jeszcze inaczej?

Mam nadzieję, że to zrozumiałe. Z góry dziękuję
Go to the top of the page
+Quote Post
lukaskolista
post 11.09.2016, 20:24:13
Post #2





Grupa: Zarejestrowani
Postów: 872
Pomógł: 94
Dołączył: 31.03.2010

Ostrzeżenie: (0%)
-----


Co do tematu tej dyskusji: stosując TDD (red->green->refactor) to w trakcie pisania powinno Ci wyjść najlepsze rozwiązanie.

1. Zależy od konkretnego przypadku.
2. Trait to generalnie nienajlepszy pomysł.
3. I każda z tych klas proxuje te metody bez powodu? - chyba bez sensu (proxy ma sens w konkretnych przypadkach, w tym raczej nie, chociaż nie zdradziłeś szczegółów, więc ciężko powiedzieć).
4. Dekorator - w tym przypadku bez sensu, bo dekoratory stosuje się w kontekstach, a nie generycznie.

Może powiedz konkretnie o co chodzi, na pewno nikt Ci kodu nie ukranie, a tylko ułatwisz dojście do najlepszego rozwiązania, bo w tej chwili trudno cokolwiek powiedzieć.

Ten post edytował lukaskolista 11.09.2016, 20:25:01
Go to the top of the page
+Quote Post
Skie
post 11.09.2016, 20:30:55
Post #3





Grupa: Zarejestrowani
Postów: 555
Pomógł: 84
Dołączył: 20.02.2008
Skąd: Małopolska

Ostrzeżenie: (0%)
-----


Jeżeli dobrze rozumiem problem, pytasz jak dla N klas udostępnić współdzieloną logikę? Z tego co mówisz ta logika jest osobno oprócz metod zawartych w interfejsie, zatem wzmianka że wspóldzielą jakiś tam interfejs jest bez znaczenia, bo dotyczy innego fragmentu kodu, niż ten o który pytasz. To tylko zaciemnia przekaz pytania.

Tak naprawdę to wszystkie przedstawione przez Ciebie opcje są dopuszczalne, zgodne z OOP i TDD. Wybór jednej z nich powinien zależeć tutaj nie od implementacji, a od przeznaczenia tych klas i ich odniesienia względem budowanego przez Ciebie systemu. W opcji nr 1 mówisz o dziedziczeniu po innej klasie, opcje nr 2 i 3 to w rózny sposób wykonana kompozycja, a 4 to strategia. Jeżeli głównym celem działania tych klas, jest ta wspóldzielona logika, a metody interejsu definiują w jaki sposób klasy ją spełniają, wtedy powinieneś użyć strategii. Jeśli jednak głownym celem jest interfejs, a wspóldzielona logika to różnego rodzaju helpery, czy też metody należące do innego interfejsu wtedy raczej obstawałbym za opcją dziedziczenia lub kompozycji. Tutaj z kolei, jeśli mozesz użyć dziedziecznia - użyj go - jeśli jest to niemożliwe - wtedy kompozycja. Wybór pomiędzy użyciem trait lub wstrzykiwaniem dodatkowego obiektu w przypadku kompozycji to pytanie dotyczące, które z tych dwóch metod pozwoli Ci na łatwiejszy maintenance istniejącego systemu i która z tyhc metod będzie konsystenatna z tym co już istnieje.

TLDR - pod wzgldem OOP i TDD wszystkie 4 metody są tak samo akceptowalne, a wybór leży po stronie projektowej, a nie stricte technologicznej.

Ten post edytował Skie 11.09.2016, 20:37:09


--------------------
Wieloprocesowość i wielowątkowość w PHP, poznaj Kraken PHP!
Serwer HTTP i WebSocket w PHP | Promise/A+
Strona Domowa | Elradia MMORPG
FireFox: make the web better.
Go to the top of the page
+Quote Post
lukaskolista
post 11.09.2016, 20:39:30
Post #4





Grupa: Zarejestrowani
Postów: 872
Pomógł: 94
Dołączył: 31.03.2010

Ostrzeżenie: (0%)
-----


Czy 4. to strategia - na pierwszy rzut oka tak, ale po przemyśleniu wydaje mi się, że autorowi chodzi tutaj o dekorator, tylko źle to opisał. Czemu tak mi się wydaje? Ponieważ współdzielona logika jest jedna, a strategia zakłada, że każda klasa implementuje daną metodę inaczej.

Najlepiej jak poda szczegóły, to będzie łątwiej.

Ten post edytował lukaskolista 11.09.2016, 20:40:45
Go to the top of the page
+Quote Post
trzczy
post 11.09.2016, 22:32:49
Post #5





Grupa: Zarejestrowani
Postów: 460
Pomógł: 49
Dołączył: 5.06.2011

Ostrzeżenie: (0%)
-----


Napisałem wyjaśnienie na prośbę @lukaskolista, ale straciłem internet ma pewien czas. Kiedy odzyskałem, pojawił się komentarz @Skie. Z tego co czytam, Skie zrozumiał o co biega, i faktycznie ten temat interface jest tu raczej bez znaczenia. Istotne jest to, że kilka klas korzysta z tej samej logiki, tych samych metod.

Przy okazji: co to jest strategia? Albo gdzie o tym czytać.




Odpowiedź dla @lukaskolista zasejwowana przed utratą internetu: ;-)
Ta aplikacja zajmuje się ustalaniem kolejności grup różnych rzeczy. Przykładowo stringów albo obiektów stdClass, albo liczb, albo tablic.

Danymi wejściowymi są te rzeczy oraz info, że niektóre rzeczy są poprzedzone przez inne rzeczy. Jest pewien algorytm matematyczny, który na podstawie tej info ustala grupy rzeczy i kolejność tych grup. Zatem wypluwana jest tablica tablic z tymi rzeczami.


W zależności od tego, jakie to są rzeczy, tworzona jest inna klasa, implementująca ten sam interfejs. Załóżmy, że zajmujemy się sortowaniem pewnych obiektów stdClass. Wtedy tworzymy klasę np. MyStdClassObjects implementującą interfejs, który narzuca zadeklarowanie metody isLike.

Metoda isLike jest to metoda, dzięki której można określać tożsamość poszczególnych rzeczy typu stdClass. Jest ona porzebna, aby właściwie intepretować informację o tym, że jakiś obiekt stdClass jest poprzedzony innym obiektem stdClass.

Gdybyśmy zajmowali się sortowaniem liczb, wymagana interfejsem metoda isLike by po prostu sprawdzała równość liczb.

Ale wróćmy do sortowania obiektów stdClass i do klasy MyStdClassObjects. Z zasobów tej klasy korzysta metoda create, która pozwala uzyskać końcową tablicę tablic. Metoda create jest literalnie ta sama bez względu na to, co sortujemy: czy liczby, czy stringi, czy obiekty itd. Metoda create korzysta z właściwej metody isLike. Poza tym korzysta z kilku metod pomocniczych, które są takie same niezależnie od tego, co sortujemy. Jedną z takich metod jest metoda hasFormerThings, która mówi, czy dana rzecz następuje po innej rzeczy.

Zatem widać, że są metody wspólne, takie same dla każdej implementacji interfejsu. I pytanie brzmi, jak te metody mają się komunikować z klasą implementującą ten interfejs, czyli np. z klasą MyStdClassObjects. Gdzie mają być zgrupowane. Jak mają być udostępnione tej klasie?
Go to the top of the page
+Quote Post
Skie
post 11.09.2016, 22:45:44
Post #6





Grupa: Zarejestrowani
Postów: 555
Pomógł: 84
Dołączył: 20.02.2008
Skąd: Małopolska

Ostrzeżenie: (0%)
-----


Jak dla mnie to co opisujesz brzmi jak typowe zastosowanie dla strategii.

Teoria: https://en.wikipedia.org/wiki/Strategy_pattern
Strona opisująca implementację tego wzorca: http://www.oodesign.com/strategy-pattern.html
Trochę prostsza wersja tego co powyżej w PHP: http://www.phptherightway.com/pages/Design-Patterns.html

Ten post edytował Skie 11.09.2016, 22:48:30


--------------------
Wieloprocesowość i wielowątkowość w PHP, poznaj Kraken PHP!
Serwer HTTP i WebSocket w PHP | Promise/A+
Strona Domowa | Elradia MMORPG
FireFox: make the web better.
Go to the top of the page
+Quote Post
trzczy
post 12.09.2016, 09:34:47
Post #7





Grupa: Zarejestrowani
Postów: 460
Pomógł: 49
Dołączył: 5.06.2011

Ostrzeżenie: (0%)
-----


No to już wiem, co to jest strategia. Dzięki. Rzeczywiście w mej aplikacji jest strategia, niemniej, jak już się wcześniej zgodziliśmy, pytanie raczej dotyczy dostępu poszczególnych klas klienckich do wspólnej logiki.

Zrobiłem to na zasadzie użycia Trait przez każdą z klas klienckich, ale nie wiem, jakie to niesie ze sobą skutki dla TDD, bo nie mam doświadczenia. Wybrałem Trait, gdyż chciałem sobie zagadnienie Trait poćwiczyć. Wniosek z dyskusji, że co do dostępu do tej logiki, to jest kilka równorzędnych dróg, chyba, że "w praniu" wynikną jakieś zalety jednej z nich.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.03.2024 - 11:40