Это плохая практика, чтобы реализовать интерфейс дважды? - PullRequest
2 голосов
/ 13 февраля 2020

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

Ситуация:

An Сущность и Отношения оба имеют общие (INode) и уникальные методы (IEntity или IRelation)

Класс должен знать об общих и уникальных методах, используя либо интерфейс IEntity или IRelation.

Вопрос:

Являются ли архитектуры ниже хорошей или плохой практикой при попытке программирования по принципу SOLID & DRY?

дополнительная информация: основная причина этого вопроса заключается в том, что на первой диаграмме (в настоящее время реализованной) сущность и отношение реализуют интерфейс INode дважды.

Ситуация 1:

situation 1

Ситуация 2:

situation 2

1 Ответ

5 голосов
/ 14 февраля 2020

Ваши диаграммы очень хорошо иллюстрируют тонкую разницу между разделением интересов (концептуальное) и разделением интерфейса (проект класса).

В вашем случае есть не два, а четыре варианта:

  1. Ваша первая диаграмма говорит, что IEntity и IRelation являются специализациями INode. IEntity ВСЕГДА INode. Вы можете написать код, который обрабатывает сущности и отношения как узлы, но есть возможность повторного использования: IEntity связан с INode, даже если это две разные несвязанные концепции.
  2. Ваша вторая диаграмма говорит о том, что IEntity и IRelation - это разные несвязанные вещи, если смотреть на них через их интерфейс. Оба теперь отделены друг от друга и могут использоваться независимо друг от друга, но вы не понимаете, что у них есть что-то общее и, следовательно, они вынуждены иметь дело с ними по отдельности.
  3. Другим вариантом будет решение 1, но без наследования между интерфейсами. В этом подходе у вас есть независимые интерфейсы: IEntity будет реализовывать как общий, так и специальный c интерфейс. Преимущество: у вас сегрегация интерфейса, как в 2, но с лучшим разделением интересов. Неудобство в том, что IEntity больше не может быть самостоятельным.
  4. Еще один вариант (мой любимый) - разделить INode на два независимых интерфейса: общий INamedObject и специальный c графический интерфейс INode. IEntity и IRelation будут наследоваться от INamedObject, но не от INode. Преимущество состоит в том, что у вас есть истинное разделение интересов: вещи не разделены искусственно по техническим причинам, но в соответствии с концепцией, которую они представляют.

В конце концов, даже если лично я бы посоветовал вариант 4, вы должны найти правильный баланс для своего собственного дизайна. Потому что только вы можете знать, как вы собираетесь использовать свои интерфейсы и классы и концепции, которые вы действительно хотите представить.

enter image description here

...