Как стать автором
Обновить
2
0

Пользователь

Отправить сообщение

Это вы сами предположили. Давайте считать, что принадлежит.

Это логично вытекает из вашего примера кода. Т.е. это не я предположил, а вы показали в коде через нейминг сущностей.
Но, если допустить, что вы просто неудачно подобрали имя для интерфейса и назвали его общим именем Notification , но методы этого интерфейса будут вызываться только из МВУ, где есть сущность UserRegistration и больше нигде, то да, тогда все корректно (но опять же, нейминг интерфейса намекает на обратное).

Ваш пример кода хорошо иллюстрирует проблематику трактовки принципа как "зависимость от абстракций". В статье как раз и объясняется, что просто так прокинуть куда-то абстракцию и заявить, что выполнен DIP недостаточно.

Не вижу нарушения, даже если интерфейс принадлежит, как вы выразились, проекту в целом. В моем понимании - к еще более верхнему модулю, для которого UserRegistration и EmailNotifier это модули нижнего уровня.

Модуль верхнего уровня — тот, который "потребляет" функционал. В вашем примере потребляет функционал UserRegistration  , значит он является сущностью из МВУ. Если Notification не принадлежит модулю c UserRegistration  , значит он принадлежит МНУ. Если интерфейс не принадлежит МВУ, то МВУ как зависел от чего-то, так и зависит, а абстракция это или нет — разницы нет. МВУ должен зависеть сам от себя.

Вы как раз привели пример нарушения принципа DIP.

Модулю верхнего уровня принадлежит класс UserRegistration , модулю нижнего уровня — EmailNotifier Осталось определить, какому модулю принадлежит интерфейс Notifier и судя по его названию, он явно не принадлежит модулю верхнего уровня, а принадлежит, скорее в целом проекту (т.к. название Notifier слишком общее) и значит DIP здесь не выполнен.

Просто прокинуть куда-то интерфейс - это не про инвертировать зависимость

Можете объяснить, что значит принадлежать?

Значит, что интерфейс должен физически находиться в границах МВУ

Именно поэтому в описании принципа есть фраза "Оба модуля должны зависеть от абстракций", которую автор поста почему-то проигнорировал.

Почему проигнорировал? ничего не проигнорировал, т.к. в его примерах оба модуля зависят от интерфейса

Все же это не просто дело нейминга, т.к. от этого зависит то, куда мы будем добавлять интерфейс.
Интерфейс в DIP должен принадлежать модулю верхнего уровня. Если его добавить в модуль нижнего уровня, то инверсии зависимостей не будет.
Т.е. модуль верхнего уровня - это тот модуль, который в конечном счете использует/потребляет реализацию другого модуля.
Существует большое заблуждение что DIP - это про зависимость от абстракций.
Ключевое в этом принципе как раз первый пункт: "модули верхних уровней не должны зависеть от модулей нижних уровней", который непосредственно отражает само название "инверсия зависимостей".

Сами по себе абстракции ничего не инвертируют. Например, в связках (класс Родитель)<-(класс Потомок), (абстрактный класс Родитель)<-(класс Потомок), (интерфейс Родитель)<-(класс Потомок) все зависимости направлены в одном направлении.
Весь проект может быть построен на абстракциях, но при этом в нем не будет ни одной инверсии зависимостей, если интерфейсы находятся не в модулях верхнего уровня

Как то тоже создавал подобный функционал для инициализации и дальнейшей работы со своими проектами на flutter, т.к. проблема насущная)

Концепция была похожая - есть шаблонный проект и файл конфигурации в .yaml формате. Только помимо инициализации, можно работать ещё с уже существующим проектом.

Для уже существующего проекта можно задать определенную команду и она будет вставлять необходимый код как в уже существующие файлы в определенные места, так и создавать новые файлы/директории. Например, можно создать команду addEntity=Product и будут созданы директория product вместе с репозиториями и сервисами, детальная страница для Product, и вставлены соответствующие url в роуты(т.е. изменения в существующем файле)

Вот если что код этого функционала: https://github.com/koliane/koliane

Как было сказано выше, интерфейс ни на йоту не меняет ситуацию со связанностью кода. 

Смотря связанность какого модуля имеется ввиду. Если имеется ввиду связанность модуля верхнего уровня, то мы избавляемся от зависимости, а значит уменьшаем кол-во связей (чуть подробнее написал далее)
В исходном случае DIP, мы зависим от модуля нижнего уровня. Применяя инверсию зависимости, путем добавления интерфейса в модуль (ВАЖНО)верхнего уровня (т.е. интерфейс - это часть модуля верхнего уровня), модуль верхнего уровня теперь зависит только от самого себя, т.е. от интерфейса, которого мы ему добавили.

Здесь введение интерфейса ничего не меняет в степени связности между Foo и Bar: если мы изменим ожидаемый строковый формат в Bar, то нам придется внести изменения и в Foo.

Мы не можем просто так менять Bar (модуль нижнего уровня) и подстраивать под него модуль верхнего уровня Foo. Модули нижних уровней должны подстраиваться под модули верхних уровней, а не наоборот.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность