Плюсы и минусы интерфейсных констант [закрыто]


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 94

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) { ... }
}

это не то, что вы используете только константы, вы используете понятие перечисляемых значений или перечислений, которые набор ограниченных значений, считаются определенным типом, с определенным использованием ("домен"? )