общался сегодня с одним java-разработчиком
у себя на канале она статью про dip, di и иже с ними выложила
и в примере с dip был там следующий код:
class Service {
LoggerInterface logger;
public function Service() {
logger = new FileLogger();
}
}я до этого читал, что dip - это никаких упоминаний реализаций (в частности потому как они тянут за собой компилирование вашего пакета) + у дядюшки Боба читал, что никаких import, require или use быть не должно, и поэтому считал, что вот это вот
new FileLogger() является как раз нарушением этого принципа
пообщался с автором поста, она топит за то, что dip - это когда твой код с интерфейсом работает, а не с реализацией и инициализация сюда не входит
типа инициализация - это уже di скорее, а к dip'у только боком относится
и на мое замечание "тогда можно создать конкретный класс, перед каждым использованием приводить его к интерфейсу (типа
((LoggerInterface)logger)->log()) и всем говорить, что у нас соблюдается dip" она ответила, что да, это и будет dip
и вот интересно стало: а правда где?
я понимаю ее подход, но так же понимаю и подход "никаких упоминаний реализаций" и последний мне ближе
а потом подумал, будет ли следующий код соответствовать dip:
abstract class Service {
abstract function getLogger(): LoggerInterface;
}?
вроде здесь никаких упоминаний реализации, но получается, что мы реализацию перекладываем на клиента, а он внутри getLogger() может как конкретный объект создавать, так и возвращать заинъекченный по интерфейсу
и вот в моем понимании в первом случае будет нарушение dip, а во втором - нет
т.е. и абстрактный класс как бы завис: нарушать или нет?
и вот как правильно? включать инициализацию по интерфейсу, чтобы можно было говорить про dip? или работу с объектом через интерфейс и считать dip? даже если двумя строчками выше идет инициализация конкретной реализации
если последнее, то как тогда называется, когда у нас dip + инъекция по интерфейсу? по любому же название есть