2021-10-07 17:18:49
?-> вместо NullObject: по следам дискуссииПредыдущий пост бурно и полезно обсудили, расписываю основные мысли.
"За" и "против" использования ?-> для опциональных зависимостей:
самый лаконичный способ до выхода PHP 8.1 (там можно будет использовать new для значений параметров по умолчанию);
обходится дешевле в рантайме, так как в null-сценарии выполняется меньше кода
(сразу оговорюсь, что это вообще сомнительный аргумент, в частности, трудно себе представить приложение без логгирования в продакшне);
скрытый и "ненужный" if;
NullObject — более корректное и универсальное с точки зрения ООП решение, null-safe подход может быть уместен только в нескольких случаях;
на проекте без статического анализатора вероятность ошибки выше.
Также в Пыхтелке затронули очень важную тему: зависимости редко бывают опциональными. Действительно, nullable зависимости часто сигнализируют о нарушении SRP. Необязательные поведения лучше оформлять в виде декораторов или middleware — их легко включать и выключать, не изменяя код (см. OCP).
Что касается логгирования, его не всегда можно представить в виде декоратора. Зачастую полезная для логов информация инкапсулирована в реализации и не протекает через контракт. Скорее всего, в этом случае тоже где-то нарушается SRP, но добавление абстракции исключительно ради логгирования может быть неоправданным усложнением.
И последний нюанс: зачем вообще делать логгер опциональной зависимостью, если он всегда есть в контейнере? Мой ответ простой: лень. В юнит-тестах, не тестирующих само логгирование, не хочется каждый раз писать new Service(/** required dependencies, */ new NullLogger()) .
Итак, теперь мы знаем, что можно вот так нестандартно использовать ?->, но что это не всегда хорошая идея. Всем спасибо за комментарии!
2.5K viewsВалентин Удальцов, edited 14:18