Статические методы: они все еще плохо относятся к PHP 5.3 поздней статической привязке?

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

Итак, это все еще верно, учитывая, что в PHP 5.3 вы можете делать все, что хотите, с введением static::?

Добавить

http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html

Обратите внимание, что он объясняет, как использовать синглтон без какой-либо проблемы с тестированием:

Ответ 1

Если у вас есть статическая функция-член, она обычно может быть свободной. Обычная реакция заключается в том, что кодер выбрал статическую функцию-член только из-за мифа о том, что "все должно быть в объекте".

Вот почему люди отговаривают их.

И, поскольку это не очень убедительный аргумент, эти люди вместо этого указали на модульное тестирование. Не уверен, что они сделают сейчас.

Ответ 2

Статические методы сами по себе не плохи. Иногда некоторые операции не имеют смысла требовать от конкретного объекта. Например, функция, такая как квадратный корень, будет иметь больше смысла быть статичной.

Math::sqrRoot(5);

вместо того, чтобы создавать экземпляр объекта Math, а затем вызывать функцию.

$math = new Math();
$result = $math->sqrRoot(5);

Ответ 3

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

Конечно, вы обнаружите, что есть еще один глобальный доступ к объектам и создающий один с "новым". Объекты должны быть созданы где-то, поэтому мы не можем устранить это (хотя сведение к минимуму это хорошая идея). Статические методы как глобальный доступ к классу являются плохими, если только он не заменит "новый" на более высокий уровень программирования:

$user = new User();
$user->setPointsTo(100);

// vs

$user = User::with100StartingPoints();

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

Изменить: позвольте мне привести пример того, как статические методы "могут" быть смертью тестируемости (обратите внимание, как в приведенном выше примере вам даже не нужно издеваться над статическим методом, но может легко протестировать новый и статический метод дает тот же результат). Позвольте использовать пример вашего регистратора:

class Logger {
    public static function log($text) { // etc }
}

class AccessControl {
    public function isAllowed(User $user, $action) {
      // do stuff, determine if $allowed
      if (!$allowed) {
          Logger::log('user X was not allowed to do Y');
      }
      // do stuff
    }
}

Мы не можем проверить этот метод чисто из-за глобального вызова Logger:: log. Это будет зависеть от правильной работы класса Logger.