Пробежался по статье, автор похоже делает подмену понятий: описываемые недостатки присущи 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. А фабрику чтобы это все ручками не собирать.