Цитата из документации к Zenject полностью звучит так:
note that injecting the DiContainer is usually a sign of bad practice, since there is almost always a better way to design your code such that you don't need to reference DiContainer directly (the exception being custom factories, but even in that case it's often better to inject a factory into your custom factory. Once again, best practice with dependency injection is to only reference the DiContainer in the "composition root layer" which includes any custom factories you might have as well as the installers. However there are exceptions to this rule.
Да, я понимаю, что использование контейнера напрямую это не стандартный способ, но вот утверждать, что это плохая практика и почти всегда есть способ сделать лучше, я не готов.
Приведу пример. У меня есть обучающая цепочка заданий. У каждого задания есть возможность что-то сделать с игрой в начале задания и при его завершении.
В коде это выглядит так:
public abstract class QuestCallback : ScriptableObject
{
public abstract void Invoke(DiContainer diContainer, QuestData quest);
}
Даже с недоделанным до конца туториалом, у меня уже накопилось с десяток имплементаций
QuestCallback, каждому из которых требуется та или иная зависимость.Какая альтернатива использованию
DiContainer в этой ситуации? Явно перечислить все необходимые зависимости в параметрах метода QuestCallback.Invoke? И для каждой новой имплементации дописывать ещё параметры? А разве мы не нарушаем этим самым Open–closed principle? И чем плох мой вариант?В статье и её переводе объясняется, почему Service Locator - это антипаттерн, но вот только есть ли вариант лучше?
#программирование #нерешенное