Interfejsy PHP pozwalają na definiowanie stałych w interfejsie, np
interface FooBar
{
const FOO = 1;
const BAR = 2;
}
echo FooBar::FOO; // 1
Każda klasa implementująca będzie miała automatycznie dostępne te stałe, np
class MyFooBar implement FooBar
{
}
echo MyFooBar::FOO; // 1
Osobiście uważam, że wszystko, co Globalne, jest Złem . Ale zastanawiam się, czy to samo dotyczy stałych interfejsu. Biorąc pod uwagę, że kodowanie w oparciu o interfejs jest ogólnie uważane za dobrą praktykę, czy używanie stałych interfejsu jest jedynymi stałymi, których można używać poza kontekstem klasy?
Chociaż jestem ciekawy twojej osobistej opinii i tego, czy używasz stałych interfejsu, czy nie, szukam głównie obiektywnych powodów w twoich odpowiedziach. Nie chcę, aby było to pytanie typu ankiety. Interesuje mnie, jaki wpływ ma używanie stałych interfejsu na utrzymywalność. Sprzęganie. Lub testy jednostkowe. Jak to się ma do SOLID PHP? Czy narusza jakiekolwiek zasady kodowania uważane za dobre praktyki w PHP? Masz pomysł …
Uwaga: w przypadku Javy pojawia się podobne pytanie, w którym wymieniono całkiem dobre powody, dla których są one złymi praktykami, ale ponieważ Java nie jest PHP, uznałem za uzasadnione, aby zadać je ponownie w tagu PHP.
Odpowiedzi:
Cóż, myślę, że sprowadza się to do różnicy między dobrym a dostatecznie dobrym .
Chociaż w większości przypadków można uniknąć stosowania stałych poprzez implementację innych wzorców (strategii lub wagi muszej), jest coś do powiedzenia na temat braku potrzeby stosowania pół tuzina innych klas do reprezentowania koncepcji. Myślę, że sprowadza się to do tego, jak prawdopodobne jest zapotrzebowanie na inne stałe. Innymi słowy, czy istnieje potrzeba rozszerzenia ENUM zapewnianego przez stałe w interfejsie. Jeśli możesz przewidzieć potrzebę jego rozszerzenia, zastosuj bardziej formalny wzór. Jeśli nie, to może wystarczyć (będzie wystarczająco dobry, a zatem będzie mniej kodu do napisania i przetestowania). Oto przykład wystarczająco dobrego i złego użycia:
Zły:
Wystarczająco dobry:
Powód, dla którego wybrałem te przykłady, jest prosty.
User
Interfejs definiuje enum typów użytkowników. Jest bardzo prawdopodobne, że z czasem będzie się to rozwijało i lepiej pasowałoby do innego wzorca. AleHTTPRequest_1_1
jest to przyzwoity przypadek użycia, ponieważ wyliczenie jest zdefiniowane przez RFC2616 i nie zmieni się przez cały okres istnienia klasy.Ogólnie rzecz biorąc, nie uważam problemu ze stałymi i stałymi klas za problem globalny . Postrzegam to jako problem zależności. To wąskie rozróżnienie, ale definitywne. Widzę problemy globalne jak zmienne globalne, które nie są narzucane i jako takie tworzą miękką zależność globalną. Jednak zakodowana na stałe klasa tworzy wymuszoną zależność i jako taka tworzy twardą zależność globalną. Więc obie są zależnościami. Ale uważam, że globalność jest znacznie gorsza, ponieważ nie jest wymuszana ... Dlatego nie lubię grupować zależności klas z zależnościami globalnymi pod tym samym szyldem ...
Jeśli piszesz
MyClass::FOO
, jesteś na stałe zakodowany w szczegółach implementacjiMyClass
. Tworzy to twarde sprzężenie, które sprawia, że kod jest mniej elastyczny i dlatego należy go unikać. Istnieją jednak interfejsy, które umożliwiają dokładnie ten typ sprzężenia. DlategoMyInterface::FOO
nie wprowadza żadnego konkretnego połączenia. Powiedziawszy to, nie wprowadzałbym interfejsu tylko po to, aby dodać do niego stałą.Więc jeśli używasz interfejsów, a ty jesteś bardzo pewny, że Ty (lub ktoś inny o to chodzi) nie będzie potrzebować dodatkowych wartości, to naprawdę nie zobaczyć ogromny problem ze stałych interfejs ... Najlepszym projekty nie zawierałyby żadnych stałych, warunkowych, liczb magicznych, łańcuchów znaków ani niczego zakodowanego na stałe. To jednak dodaje dodatkowy czas na rozwój, ponieważ musisz wziąć pod uwagę zastosowania. Uważam, że w większości przypadków absolutnie warto poświęcić dodatkowy czas na zbudowanie świetnego, solidnego projektu. Ale są chwile, kiedy dostatecznie dobre jest naprawdę akceptowalne (i zrozumienie różnicy wymaga doświadczonego programisty) iw takich przypadkach jest w porządku.
Ponownie, to tylko mój pogląd na to ...
źródło
Myślę, że zwykle lepiej jest traktować stałe, specjalnie wyliczone stałe, jako oddzielny typ („klasa”) od interfejsu:
lub, jeśli chcesz użyć klasy jako przestrzeni nazw:
Nie chodzi o to, że używasz tylko stałych, używasz koncepcji wartości wyliczonych lub wyliczeń, które to zestaw wartości zastrzeżonych są uważane za określony typ, z określonym zastosowaniem („domena”?)
źródło