Почему мы должны размещать интерфейсы с классами, которые их используют, а не с теми, которые их реализуют?

#oop #design-patterns #packages

#ооп #дизайн-шаблоны #упаковка #шаблоны проектирования #пакет

Вопрос:

Я просматривал статью Роберта К. Мартина, и в одном месте он привел подобный пример:

Первое изображение показывает, что между двумя пакетами существует циклическая зависимость. Чтобы устранить эту зависимость, на втором изображении добавлен новый интерфейс. B реализует интерфейс, а Y использует его. И Мартин выдвигает следующую точку зрения:

Интерфейсы очень часто включаются в пакет, который их использует, а не в пакет, который их реализует.

Мой вопрос в том, почему мы должны размещать интерфейсы таким образом? Каковы причины, лежащие в основе упаковки интерфейсов таким образом? Согласно Общему принципу закрытия, классы, которые меняются вместе, должны оставаться вместе. Является ли интерфейс ближе к его разработчику или пользователю с точки зрения изменений???

введите описание изображения здесь

Комментарии:

1. Но интерфейсы могут использоваться и могут быть реализованы в разных модулях. В нашей компании мы храним их в отдельном модуле, на который ссылаются все из них, таким образом, они сами по себе являются модулем. Для нас это важно, потому что у нас много, я имею в виду МНОЖЕСТВО интерфейсов, и так проще поддерживать все подобным образом … тем более, если у вас есть правила компании о том, кто может указывать некоторый путь в репозитории. И не каждый может вносить изменения в интерфейсы…

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

3. К вашему сведению — martinfowler.com/eaaCatalog/separatedInterface.html . Я думаю, это проясняет ситуацию. Необходимость обхода структуры зависимостей может вызвать подобную ситуацию. Но как насчет общих сценариев???

4. Дело больше в том, кто и когда может изменять интерфейсы… изменение интерфейсов часто означает плохой дизайн. Интерфейсы изменяются очень редко и всегда людьми, которые знают, что они делают и почему. Когда это произойдет, да, потребуется некоторая работа по настройке всех модулей, которые используют inreface (конечно, если что-то изменилось, а не было добавлено, поскольку добавление ничего не нарушает). Вы не можете полагаться на то, что все программисты в многонациональной компании на 10 сайтах по всему миру будут вести себя как эксперты, поэтому некоторые требования процесса должны иметь приоритет над шаблонами проектирования :/

Ответ №1:

Технически пользователь не ближе к интерфейсу, чем разработчик. С точки зрения изменений, оба должны будут измениться при изменении интерфейса.

Однако, почему интерфейс должен был измениться?

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

Поскольку пользователь диктует определение интерфейса, нет смысла менять интерфейс, если пользователю это не нужно. Разработчик, требующий изменения интерфейса для адаптации к реализации, должен выдавать красные флажки. Почему ему требуется больше или иная информация от пользователя? Какая от этого польза пользователю?

Кроме того, разработчик «просто» зависит от интерфейса в той степени, в какой ему необходимо предоставить реализации для каждого из методов в интерфейсе. Но он может бесплатно предоставлять пустые заглушки, по сути предоставляя NOP своим клиентам.

Таким образом, потребности пользователя приводят к изменениям интерфейса, а изменения в интерфейсе приводят к изменениям разработчика (ов). Таким образом, пользователь функционально гораздо ближе к интерфейсу, чем разработчик. Что является хорошим аргументом для объявления интерфейса пользователем, а не разработчиком.

Ответ №2:

Сначала следует сказать, что не существует единого способа освежевать кота.

Эта конкретная методология полезна при разделении проекта между несколькими проектными группами или создании системы с разделенными подсистемами. Интерфейс служит «контрактом» между двумя подсистемами. Размещая интерфейс на «своей территории», сторона-потребитель имеет лучшую гарантию того, что интерфейс останется неизменным, если только сторона-разработчик не свяжется с стороной-потребителем, чтобы запросить такое изменение.

Ответ №3:

Обычно мы используем интерфейсы как протокол между сервером и клиентом, чтобы клиент знал, какие службы доступны, но у этого подхода есть побочный эффект, клиент будет зависеть от сервера, и поэтому, если что-то изменилось на стороне сервера, что влияет на данный интерфейс, клиент тоже должен измениться. Итак, среди принципов SOLID есть такой принцип, изобретенный Робертом К. Мартином, и это «Принцип инверсии зависимостей» или «DIP» , который, как следует из названия, гласит, что мы должны инвертировать зависимость между клиентом и сервером, чтобы избежать изменений в клиенте в будущем.При таком подходе клиент говорит, что ему понадобится, через интерфейс, и сервер должен реализовать это, чтобы обслуживать то, что ему нужно, поэтому никакие изменения на стороне сервера не заставляют нас менять клиента.

Ответ №4:

Это проблема разрешения циклических зависимостей между компонентами AB и XY . Ни один из них не может быть скомпилирован без другого. AB ссылается XY и XY ссылается AB .

Роберт К. Мартин применяет шаблон InversinOfControl для решения этой проблемы

Теперь XY ссылается ABInterface . ABInterface вообще не нужно знать XY .

Вы правы, это нарушает сплоченность (вы назвали это общим принципом закрытия)

Это также противоречит принципу KeepItSimple. Самое простое решение будет иметь только один монолитный компонент ABXY , который намного сложнее поддерживать.

Комментарии:

1. Ну, вопрос действительно в том, почему он хочет сохранить интерфейс с классом, который его использует. Мы не хотим вдаваться в альтернативные проекты.

Ответ №5:

Нет причин внедрять интерфейс, пока не появится что-то, что в нем нуждается. ЯГНИ.

Комментарии:

1. Хм. Давайте предположим, что RCM разрабатывает шаблон, или скажем, что интерфейс «необходим». Меня здесь не интересует шаблон. Меня больше беспокоит заявление, которое он сделал о локальности интерфейсов.