Статический метод получения - это плохая практика? - PullRequest
14 голосов
/ 02 марта 2011

Был разговор с коллегой о том, что это плохая практика или нет.Сейчас я не могу найти непосредственные примеры этого онлайн.

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

(пример) - метод 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
}

Ответы [ 5 ]

14 голосов
/ 02 марта 2011

Это не ужасно Персей.Это реализация фабричного метода шаблона проектирования.В принципе, это совсем не плохо.

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

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

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

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

5 голосов
/ 02 марта 2011

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

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

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

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


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

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

2 голосов
/ 02 марта 2011

Я только добавляю к сообщению 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;
    }

}

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

1 голос
/ 30 апреля 2014

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

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

  • если вы хотите следовать передовым практикам, протестируйте свой код
  • Значит, если статическое вызывает проблемы с тестированием, статическое препятствует написанию тестов, поэтому оно мешает следовать рекомендациям: -)
0 голосов
/ 07 мая 2019

время идет, все меняется.

на тот случай, если у вас возникнут проблемы с тестированием, вы можете использовать библиотеку AspectMock https://github.com/Codeception/AspectMock

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

...