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:
interface User {
const TYPE_ADMINISTRATOR = 1;
const TYPE_USER = 2;
const TYPE_GUEST = 3;
}
Wystarczająco dobry:
interface HTTPRequest_1_1 {
const TYPE_CONNECT = 'connect';
const TYPE_DELETE = 'delete';
const TYPE_GET = 'get';
const TYPE_HEAD = 'head';
const TYPE_OPTIONS = 'options';
const TYPE_POST = 'post';
const TYPE_PUT = 'put';
public function getType();
}
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. Ale HTTPRequest_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 implementacji MyClass
. 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. Dlatego MyInterface::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 ...