Недостатки статических методов в PHP - PullRequest
8 голосов
/ 16 декабря 2010

В теоретическом классе доступа к базе данных я обнаружил, что в классе я использую довольно много вспомогательных функций, которые не имеют ничего общего с экземпляром класса (и другими, которыми можно манипулировать, чтобы они не были связаны с экземпляром класса).используя внедрение зависимостей).

Например, у меня есть функция, которая получает строку между двумя другими строками в переменной.Я думал перенести это в класс String_Helper или что-то в этом роде.Эта функция уже сделана статической.

Также у меня есть функция, которая запрашивает базу данных, query($sql).Сведения о соединении предоставляются экземпляром, но я рассматривал возможность сделать его статичным и использовать query($sql, $connection).После этого разработчики смогут вызывать его статически, и ему вообще не нужно будет создавать экземпляр класса базы данных.

Для меня возникают следующие вопросы:

  1. Стоит ли это того, чтобысделать что-то подобное?Такие функции, как функция запроса, заставляют меня задуматься, не я ли пытаюсь сделать все как можно более статичным без какой-либо реальной необходимости.При каких обстоятельствах вы считаете это полезным?

  2. Я знаю, что статические функции сложнее тестировать, но если я убедлюсь, что их код полностью свободен от зависимостей (или использует инъекцию зависимостей при необходимости)тогда их так же легко проверить, как и все остальное, не так ли?

  3. На данный момент это не проблема, но если в будущем я решу расширитьклассы со статическими функциями, для меня было бы невозможно заставить текущий код использовать мои расширенные функции.Я думал о Singletons, но возникает та же проблема: код будет вызывать Singleton_Class::getInstance(), а не My_Extended_Singleton_Class::getInstance().Внедрение зависимостей, кажется, единственный способ решить эту проблему, но это может привести к более грубому API, так как каждая зависимость должна быть передана объекту в __construct().

  4. Iиметь класс контейнера, который статически содержит определенные фрагменты информации, чтобы к ним можно было получить доступ в любом месте скрипта (глобальная область).Если я не могу использовать статические функции или синглтоны, класс, который содержит экземпляры различных переменных, был бы великолепен.Можно использовать, например, Container::$objects['MyClass'] = $MyClass_object;, а затем остальной код может просто получить доступ к Container::$objects['MyClass'].Если бы я расширил класс MyClass, я мог бы использовать Container::$objects['MyClass'] = $MyExtendedClass_object;, а код, который использовал Container::$objects['MyClass'], использовал бы MyExtendedClass, а не MyClass.На мой взгляд, это лучший способ сделать это, но я бы хотел знать, что вы об этом думаете.

1 Ответ

10 голосов
/ 16 декабря 2010

Хорошо, позвольте мне ответить на них один за другим ...

1. Стоит ли делать что-то подобное

Да и нет. Разделение вспомогательных функций на их собственные классы - хорошая идея. Он сохраняет «область видимости» каждого из классов жестко определенными, и вы не получите ничего. Однако не делайте метод статичным только потому, что вы можете. Метод запроса призван облегчить вашу жизнь, управляя соединением, так почему вы хотите потерять это преимущество?

2. Их сложнее проверить

Их не сложнее проверить. Статические методы, которые зависят от состояния, сложнее протестировать (которые получают доступ к статическим переменным-членам или глобальным переменным). Но статические методы в целом так же легко тестировать, как и методы экземпляра (на самом деле, они могут быть проще, поскольку вам не нужно беспокоиться об экземплярах).

3. Продление классов

Это действительная проблема. Если вы введете String_Helper::foo() в самом классе, у вас возникнут проблемы. Но можно было бы установить имя помощника в качестве переменной класса. Таким образом, вы можете сделать {$this->stringHelper}::foo() (обратите внимание, только PHP 5.3). Таким образом, чтобы переопределить класс, все, что вам нужно сделать, это изменить вспомогательный класс строки в этом экземпляре. Фреймворк Lithium делает это много ...

4. Глобальный реестр

Я бы держался подальше от этого. Вы просто делаете каждый класс одиночным, не применяя его. Тестирование станет кошмаром, поскольку теперь вы зависите от глобальной области видимости. Вместо этого я бы создал объект реестра и передавал его классам через конструктор (Dependency Injection). Вы все еще выполняете то же самое, поскольку у вас есть хранилище для объектов / классов, но вы больше не зависите от глобальной области видимости. Это значительно облегчает тестирование.

В общем

Когда вы смотрите на подобные вещи, мне нравится останавливаться, когда я задаю подобные вопросы. Остановитесь, сядьте и подумайте * Какую реальную проблему я пытаюсь решить? " в долгосрочной перспективе действительно поддерживаемы (как с точки зрения исправления ошибок, так и с точки зрения добавления функций). Только если вы довольны обоими этими ответами, вам стоит даже подумать об этом. Программирование - это не создание самого сложного, самого умного или удивительного решения, а создание самого простого решения, которое решает проблему ...

Надеюсь, это поможет ...

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...