МОК и интерфейсы - PullRequest
       1

МОК и интерфейсы

6 голосов
/ 12 октября 2011

У меня есть такая структура проекта: -

CentralRepository.BL
CentralRepository.BO
CentralRepository.DataAccess
CentralRepository.Tests
CentralRepository.Webservices

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

Ответы [ 3 ]

6 голосов
/ 13 октября 2011

На комбинаторном уровне у вас есть три варианта:

  • Определение интерфейсов в отдельной библиотеке
  • Определение интерфейсов вместе с их потребителями
  • Определение интерфейсов вместе с их исполнителями

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

Определения интерфейса вместе с потребителем часто бывает достаточно, и лично я делаю дополнительный шаг, определяя интерфейс в отдельной библиотеке, когда разрозненные потребители находятся в игре (что обычно происходит, когда вы отправляете публичную версию). API).

1 голос
/ 12 октября 2011

BO - это, по сути, ваши доменные объекты или, по крайней мере, это мое предположение. В общем, если вы не используете шаблон, подобный ActiveRecord, они являются только объектами состояния. Интерфейс, с другой стороны, определяет поведение. Из многих «лучших практик» не очень хорошая идея смешивать поведение и состояние. Теперь я, вероятно, немного побродит, но думаю, что фон может помочь.

Теперь к вопросу о том, где должны существовать интерфейсы. Есть несколько вариантов.

  1. Вставьте интерфейсы в библиотеку, к которой они принадлежат.
  2. Создать отдельную библиотеку контрактов

Проще всего вставить их в одну и ту же библиотеку, но тогда ваши макеты полагаются на библиотеку, а также на ваши тесты. Не такая уж большая сделка, но она слегка пахнет.

Мой обычный метод - настроить проекты следующим образом:

{компания}. {Программа / проект}. {Беспокойство (необязательно)}. {Область}. {Подрайон (необязательно)}

Первые два-три бита имени покрыты вашим словом "CentralRepository". В моем случае это будет MyCompany.CentralRepository или MyCompany.MyProgram.CentralRepository, но соглашение об именах не является основной частью этого поста.

Части "области" - это основной смысл этого поста, и я обычно использую следующее.

  1. Настройка библиотеки объектов домена (вашего BO): CentralRepository.Domain.Models
  2. Настройка библиотеки исключений домена: CentralRepository.Domain.Exceptions
  3. Все / большинство других проектов ссылаются на вышеупомянутые два, поскольку они представляют состояние в приложении. Конечно, ВСЕ бизнес-библиотеки используют эти объекты. Библиотеки персистенции могут иметь другую модель, и у меня может быть модель представления в библиотеке (библиотеках) опыта.
  4. Настройте основную библиотеку следующим образом: CentralRepository.Core (может иметь подрайоны?). Именно в этом и заключается бизнес-логика (фактическое применение, поскольку изменения в постоянстве и опыте не должны влиять на основные функции).
  5. Настройка библиотеки тестирования для ядра: CentralRepository.Core.Test.Unit.VS (У меня есть Unit.VS, чтобы показать, что это модульные тесты, а не интеграционные тесты с библиотекой модульных тестов, и я использую VS, чтобы указать MSTest - другие будут иметь разные названия).
  6. Создание тестов, а затем настройка бизнес-функций. При необходимости настройте интерфейсы. Пример * +1032 *
  7. Нужны данные из DAL, поэтому интерфейс и макет настроены для данных, которые будут использоваться для тестов Core. Имя здесь будет что-то вроде CentralRepository.Persist.Contracts (может также использовать подрайон, если существует несколько типов постоянства).

Основной концепцией здесь является «ядро как приложение», а не n-уровень (они совместимы, но если рассматривать только бизнес-логику как парадигму, то вы будете слабо связаны с постоянством и опытом).

Теперь вернемся к вашему вопросу. Способ, которым я настраиваю интерфейсы, основан на расположении "интерфейсных" классов. Итак, я бы, вероятно, имел:

CentralRepository.Core.Contracts CentralRepository.Experience.Service.Contracts CentralRepository.Persist.Service.Contracts CentralRepository.Persist.Data.Contracts

Я все еще работаю с этим, но основная концепция - это мой IoC, и следует рассмотреть и тестирование, и у меня должна быть возможность изолировать тестирование, что будет лучше, если я смогу изолировать контракты (интерфейсы). Логическое разделение - это хорошо (отдельная библиотека), но я обычно так не думаю, потому что есть хотя бы пара «зеленых» разработчиков, которым трудно увидеть логическое разделение без физического разделения. Ваш пробег может варьироваться. : -0

Надеюсь, этот бродяга поможет каким-то образом.

0 голосов
/ 12 октября 2011

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

Лично, когда я использую многоуровневый подход, я стремлюсь дать каждому слою собственную сборку и дать ему ссылку на слой под ним.На каждом уровне большинство общественных вещей - это интерфейсы.Итак, я на уровне доступа к данным, у меня могут быть ICustomerDao и IOrderDao в качестве открытых интерфейсов.У меня также будут публичные фабрики Дао в собрании DAO.Затем я буду иметь конкретные реализации, помеченные как внутренние - CustomerDaoMySqlImpl или CustomerDaoXmlImpl, которые реализуют открытый интерфейс.Затем общедоступная фабрика предоставляет пользователям реализацию (т. Е. Уровень домена), при этом пользователи не знают точно, какую реализацию они получают - они предоставляют информацию фабрике, и фабрика оборачивается и вручает им ICustomerDao, который они используют.

Причина, по которой я упоминаю все это, заключается в том, чтобы заложить основу для понимания того, какими на самом деле должны быть интерфейсы - контракты между обслуживающим устройством и клиентом API.Таким образом, с точки зрения зависимости, вы хотите определить контракт, как правило, где находится сервисер.Если вы определите это где-то еще, вы потенциально не управляете своими зависимостями с помощью интерфейсов, а просто вводите бесполезный уровень косвенности.

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

...