Пробежался по статье, автор похоже делает подмену понятий: описываемые недостатки присущи static-переменным, а не static-методам как таковым. Статический по своей сути метод ничего плохого в себе не несёт: я их регулярно использую, например, в качестве named constructors. Иногда использую в качестве обычной функции. Проблемы начинаются, если есть static-переменная (как в singleton, например).
public showAbs($num) {
return $num . "'s absolute value is " . abs($num);
}
Ты о чём, это просто синтаксический сахар. Приведи пример.Блин, я в реальных проектах наелся гавна со статик конструктором как раз для времени, когда часовые пояса поломали. Это жёсткая зависимость и пропатчить без форков и переписывания вендорского кода было невозможно. Понятно откуда берутся тупики и проблемы с поддержкой.
Мне кажется, что ты просто пришёл потроллить, либо ты не совсем понимаешь о чём идёт речь и решил просто слиться.Ну так не надо хардкодить зависимости ни синглетонами, ни статик методами, ни через new.
Ты рассказываешь какие-то сказки.Блин, я в реальных проектах наелся гавна со статик конструктором как раз для времени, когда часовые пояса поломали. Это жёсткая зависимость и пропатчить без форков и переписывания вендорского кода было невозможно. Понятно откуда берутся тупики и проблемы с поддержкой.
От какой такой зависимости? Ты имеешь в виду как избавиться от DateTime::getInstance()->getSystemTime() (чем по сути и является new DateTime('now'))? Просто передавать из уровня выше, либо использовать какой-то сервис а-ля Clock.А например доменные обьекты или такие вот системные как DateTime - как ты избавишься от зависимости на них? У тебя будет фабрика дат?
О, сервис заворачиваем в сервис в котором будет делаться статический вызов, а затем молимся чтобы никто не сделал прямой вызов статического метода в обход этого сервиса.От какой такой зависимости? Ты имеешь в виду как избавиться от DateTime::getInstance()->getSystemTime() (чем по сути и является new DateTime('now'))? Просто передавать из уровня выше, либо использовать какой-то сервис а-ля Clock.
Ты опять фантазируешь, я ничего такого не говорил.О, сервис заворачиваем в сервис в котором будет делаться статический вызов, а затем молимся чтобы никто не сделал прямой вызов статического метода в обход этого сервиса.
final class User
{
public static function register(int $id, string $name, DateTimeImmutable $registrationDate): User
{
return new self($id, $name, $registrationDate);
}
// ...
}
Это ничем не отличается от прямого инстанциирования сервиса с прямым же конструированием зависимостей в обход DI. Дурак всегда найдет свой стеклянный буй, код-ревью для того и существует.О, сервис заворачиваем в сервис в котором будет делаться статический вызов, а затем молимся чтобы никто не сделал прямой вызов статического метода в обход этого сервиса.
Я бы даже, наверное, обобщил: проблемы появляются тогда, когда у класса (а не у его инстанса) появляется понятие состояния и он сам со себе становится мутабелен.описываемые недостатки присущи static-переменным, а не static-методам как таковым
Не нужны скорее по той причине, что они описываются в DI-конфиге, там какой-то экпрессивности особо и не нужно. Но навскидку: у нас есть сервис для работы с внешним API, плюс два способа аутентификации: сертификат или login/password.Впрочем, в сервисах named constructor-ы нафиг не нужны.
final MyAwesomeExternalApiService
{
public static function loginPassword(
string $login,
string $password,
Guzzle $guzzle
): MyAwesomeExternalApiService {
// ...
}
public static function cert(string $certPath, Guzzle $guzzle): MyAwesomeExternalApiService {
// ...
}
public function query(Query $query): Response {
// ...
}
}
Ага. А в твоем примере, думаю, скорее эти все методы будут в каком-нибудь MyAwesomeExternalApiServiceFactory на практике.Не нужны скорее по той причине, что они описываются в DI-конфиге
Честно говоря, не думаю, что на практике у меня было бы так, поскольку это обозначает, что мы должны передать в конструктор уже какой-то sessionId. Тут либо мы теряем lazy loading, либо нужно будет делать дальнейшие усложнения для того, чтобы вернуть lazy loading (инжектить саму фабрику, париться с магией а-ля ProxyManager или ещё как-то).Ага. А в твоем примере, думаю, скорее эти все методы будут в каком-нибудь MyAwesomeExternalApiServiceFactory на практике.
Ну, что уж там, для инстанса мутабельность тоже ни к чему хорошему не приводитЯ бы даже, наверное, обобщил: проблемы появляются тогда, когда у класса (а не у его инстанса) появляется понятие состояния и он сам со себе становится мутабелен.
Иногда просто лениво заниматься подобной декомпозицией, от неё должен быть какой-то толк. А если разницы нет, то я не хочу платить больше.Ну, в твоем примере я бы, наверное, вообще передавал отдельно реализацию MyAwesomeExternalApiAuthScheme, они как раз могут конструироваться без зависимостей, а ему уж там в метод authenticate инстанс Guzzle передаст MyAwesomeExternalApiService. А фабрику чтобы это все ручками не собирать.