Плюсы и минусы интерфейсных констант [закрыто]
PHP интерфейсы позволяют определять константы в интерфейсе, например
interface FooBar
{
const FOO = 1;
const BAR = 2;
}
echo FooBar::FOO; // 1
любой реализующий класс автоматически будет иметь эти константы, например
class MyFooBar implement FooBar
{
}
echo MyFooBar::FOO; // 1
мой собственный взгляд на это что все глобальное-это зло. Но мне интересно, если то же самое относится к константам интерфейса. Учитывая, что Кодирование от интерфейса считается хорошей практикой в целом, использует константы интерфейса единственные константы, которые являются допустимо использовать вне контекста класса?
хотя мне любопытно услышать ваше личное мнение и используете ли вы интерфейсные константы или нет, я в основном ищу объективные причины в ваших ответах. Я не хочу, чтобы это был вопрос типа опроса. Меня интересует, как использование констант интерфейса влияет на ремонтопригодность. Связь. Или Модульное Тестирование. Как это относится к SOLID PHP? Нарушает ли он какие-либо принципы кодирования, которые считаются хорошей практикой в PHP? Вы поняли идею...
Примечание:есть аналогичный вопрос для Java это перечислило некоторые довольно веские причины, почему они являются плохой практикой, но поскольку Java не PHP, я счел оправданным снова спросить его в теге PHP.
2 ответа:
Ну, я думаю, что это сводится к разнице между хороший и достаточно хорошо.
хотя в большинстве случаев вы можете избежать использования констант, реализуя другие шаблоны (стратегия или, возможно, flyweight), есть что-то, что нужно сказать, чтобы не нужно было полдюжины других классов для представления концепции. Я думаю, что это сводится к тому, насколько вероятно, что есть необходимость в других константах. Другими словами, есть ли необходимость расширять перечисление обеспечивается константами на интерфейсе. Если вы можете предвидеть необходимость его расширения, то идите с более формальным шаблоном. Если нет, то этого может быть достаточно (это будет достаточно хорошо, и, следовательно, будет меньше кода для написания и тестирования). Вот пример достаточно хорошего и плохого использования:
плохое:
interface User { const TYPE_ADMINISTRATOR = 1; const TYPE_USER = 2; const TYPE_GUEST = 3; }
Достаточно Хорош:
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(); }
теперь причина, по которой я выбрал эти примеры, проста. Элемент
User
интерфейс определяет перечисление типов пользователей. Это очень вероятно расширяйте с течением времени и лучше всего подойдет другой шаблон. Но этоHTTPRequest_1_1
является достойным вариантом использования, так как перечисление определяется RFC2616 и не будет меняться в течение всего срока службы класса.в общем, я не вижу проблемы с константами и константами класса как глобальные проблема. Я рассматриваю это как проблему зависимости. Это узкое различие, но определенное. Я вижу глобальные проблемы, как в глобальных переменных, которые не применяются, и таким образом, создается мягкая глобальная зависимость. Но жестко закодированный класс создает принудительную зависимость, и как таковой создает жесткую глобальную зависимость. Так что оба являются зависимостями. Но я считаю, что глобальные быть гораздо хуже, так как это не исполняется... Вот почему я не люблю валить зависимостями класс С глобальные зависимости под тем же знаменем...
если вы пишите
MyClass::FOO
, вы жестко запрограммированы на детали реализацииMyClass
. Этот создает жесткую связь, что делает ваш код менее гибким, и поэтому его следует избегать. Однако существуют интерфейсы, позволяющие именно этот тип связи. ПоэтомуMyInterface::FOO
не вводит никакого конкретного соединения. С учетом сказанного, я бы не стал вводить интерфейс только для того, чтобы добавить к нему константу.так что если вы используете интерфейсы, а вы очень уверен, что вам (или кому-либо еще в этом отношении) не понадобятся дополнительные значения, тогда я действительно не вижу огромного проблема с константами интерфейса... Лучшие проекты не включали бы никаких констант или условных обозначений, магических чисел или магических строк или жестко закодированных чего-либо. Однако это добавляет дополнительное время для разработки, так как вы должны учитывать использование. Я считаю, что в большинстве случаев это абсолютно стоит взять дополнительное время, чтобы построить большой твердый дизайн. Но бывают случаи, когда достаточно хорошо действительно приемлемо (и требуется опытный разработчик, чтобы понять разница), и в тех случаях это нормально.
опять же, это только мой взгляд на это...
Я думаю, что обычно лучше обрабатывать константы, специально перечисленные константы, как отдельный тип ("класс") из вашего интерфейса:
define(TYPE_CONNECT, 'connect'); define(TYPE_DELETE , 'delete'); define(TYPE_GET , 'get'); define(TYPE_HEAD , 'head'); define(TYPE_OPTIONS, 'options'); define(TYPE_POST , 'post'); define(TYPE_PUT , 'put'); interface IFoo { function /* int */ readSomething(); function /* void */ ExecuteSomething(/* int */ param); } class CBar implements IFoo { function /* int */ readSomething() { ...} function /* void */ ExecuteSomething(/* int */ param) { ... } }
или, если вы хотите использовать класс в качестве пространства имен:
class TypeHTTP_Enums { 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'; } interface IFoo { function /* int */ readSomething(); function /* void */ ExecuteSomething(/* int */ param); } class CBar implements IFoo { function /* int */ readSomething() { ...} function /* void */ ExecuteSomething(/* int */ param) { ... } }
это не то, что вы используете только константы, вы используете понятие перечисляемых значений или перечислений, которые набор ограниченных значений, считаются определенным типом, с определенным использованием ("домен"? )