Когда мы реализуем DI через Reader, мы делаем зависимость частью сигнатуры нашего метода. Предположим, что мы имеем (без реализаций):
trait Service1 { def f1:Int = ??? }
trait Service2 { def f2:Reader[Service1, Int] = ??? }
type Env= (Service1, Service2)
def c:Reader[Env, Int] = ??? //use Service2.f2 here
Теперь, f2
требуется дополнительная служба для реализации, скажем:
trait Service3
type Service2Env = (Service1, Service3)
//new dependecies on both:
trait Service2 { def f2:Reader[Service2Env, Int] = ??? }
Это сломает существующих клиентов, они больше не могут использовать Service2.f2
, не предоставив Service3
дополнительно.
С DI через внедрение (через конструктор или сеттеры), что является обычным явлением в ООП, я бы использовал в качестве зависимости только c
Service2
. Как оно построено и каков его список зависимостей, мне все равно. С этого момента любые новые зависимости в Service2
сохранят сигнатуру функции c
без изменений.
Как это решается с помощью FP? Есть варианты? Есть ли способ внедрить новые зависимости, но как-то защитить клиентов от изменений?