Статический метод get – это плохая практика?

Было ли обсуждение с коллегой о том, что это плохая практика или нет. Теперь я не могу найти немедленные примеры этого онлайн.

У нас много картотекторов объектов базы данных, и мы называем его такими функциями

(пример) – метод setId получает строку из базы данных и устанавливает ее в предопределенные свойства

class Person { public static function get($id) { $object = new Person; $object->setId($id); return $object; } } 

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

 $person = Person::get($id); 

вместо

 $person = new Person; $person->setId($id); 

Теперь мой инстинкт говорит мне, что это плохая практика. Но я не могу это объяснить. Может быть, кто-то здесь может объяснить, почему это так, или это не плохая практика

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

 class CatalogArticle { public static function get($id) { } public static function getByArticlenumber($articlenumber) {} //$articlenumber is unique in the database public static function getRandom() {} //Runs a query returning a random row } 

Это не ужасно . Это реализация шаблона проектирования Factory Method . Это совсем не плохо в принципе.

Однако в вашем конкретном примере это не делает ничего значительного, поэтому я не уверен, что это необходимо. Вы можете устранить необходимость, взяв (возможно, необязательный) параметр для конструктора для id. Тогда любой может вызвать $foo = new Person($id); а не на явной фабрике.

Но если инстанцирование является сложным или вы хотите создать несколько разных типов людей, которые могут быть определены только логикой, фабричный метод может работать лучше. Например, предположим, что вам нужно определить тип человека для создания экземпляра по некоторому параметру. Тогда подходящий заводский метод для Person . Метод определит, какой «тип» загружается, а затем создает экземпляр этого класса.

Статику в целом трудно проверить и не допускать полиморфных изменений, подобных экземпляру. Они также создают жесткие зависимости между классами в коде. Они не ужасны , но вы должны действительно думать об этом, если хотите его использовать. Вариант будет заключаться в использовании Builder или абстрактной фабрики . Таким образом, вы создаете экземпляр фабрики / фабрики, а затем пусть этот экземпляр определяет, как создать экземпляр полученного класса …

Еще одно замечание. Я бы переименовал этот метод из Person::get() в нечто более семантически подходящее. Возможно, Person::getInstance() или что-то еще подходящее.

Это сообщение в блоге должно рассказать вам, почему люди не любят статические методы лучше, чем я мог:

http://kore-nordmann.de/blog/0103_static_considered_harmful.html

Вопрос, который больше всего меня поражает в вашем текущем фрагменте кода: Является ли Лицо позволенным НЕ иметь идентификатор?

Я чувствую, что это должен быть аргумент конструктора, если он представляет реальную Личность. Если вы используете этот класс для создания новых лиц, то из c может не работать.


Разница между двумя вызовами незначительна. Оба «создают» класс Person и устанавливают Id, чтобы вы не выигрывали / не теряли что-либо там, когда речь заходила о «жестких проводных зависимостях».

Преимущество показывает только тогда, когда вы хотите передать Личность другому объекту и что объекты должны изменить ID (например, сообщение в блоге должно объяснить это лучше, чем я сделал здесь).

Я только добавляю сообщение edorian, но в прошлом я использовал статические методы get, где есть механизм кэширования, и (например) у меня мог бы быть данный объект Person в memcache, и он бы скорее его извлек из кеша, чем переход в базу данных.

Например:

 class Person { public static function get($id) { if(Cache::contains("Person", $id)) { return Cache::get("Person", $id); } else { //fictional get_person_from_database, basically //getting an instance of Person from a database $object = get_person_from_database($id); } return $object; } } 

Таким образом, вся обработка кэша выполняется рассматриваемым классом, а не вызывающим абонентом, вызывающим вызов пользователя, который должен беспокоиться о кеше.

Короче говоря, да, это плохая практика:

Хорошая причина в том, что вы должны «проверять свой код». Статические методы вызывают проблемы, поэтому у вас есть веская причина:

  • если вы хотите следовать хорошей практике, проверьте свой код
  • Ergo, если статические причины проблемы с тестированием, статические предупреждения не позволяют писать тесты, поэтому он предотвращает следование передовым методам 🙂