10

фонГде определить интерфейсы для репозитория в многоуровневой архитектуре?

Я пытаюсь создать простое приложение, чтобы действительно понять весь стек DDD + TDD + и др. Моя цель - динамически вводить классы репозитория DAL во время выполнения. Это позволяет тестировать уровни доменов и приложений приложений . Я планирую использовать «бедняк DI» для достижения это сейчас ... так что я хотел бы сделать это в простом приложении консоли рядом с запуском:

 

    // Poor man's DI, injecting DAL repository classes at runtime 
    var productRepository = new SimpleOrder.Repository.ProductRespository(); 
    var customerRepository = new SimpleOrder.Repository.CustomerRepository(); 
    var orderRepository = new SimpleOrder.Repository.OrderRepository(); 

    // Constructor injection into this class in the Application Services layer, 
    // SimpleOrder.ApplicationFacade 
    OrderEntry oe = new OrderEntry(customerRepository, orderRepository, productRepository); 

Для достижения этой инъекции зависимостей, я создал три хранилищу интерфейсы:

 
-- ICustomerRepository 
-- IOrderRepository 
-- IProductRespository 

типичная реализация:

 

    namespace SimpleOrder.Domain.Interfaces 
    { 
     public interface ICustomerRepository 
     { 
      Customer GetCustomerById(int customerId); 
      void SaveCustomer(Customer customer); 
     } 
    } 

** Обратите внимание, что SaveCustomer ссылается на класс модели клиента, определенный в Doma в слое. Это типично для других репозиториев.

ОДНАКО Я не уверен, какой проект/слой, они должны быть реализованы в I 5 проектов в растворе:

  1. SimpleOrder.ConsoleClient (презентация) - Я хочу, чтобы впрыснуть. конкретная реализация домена здесь в качестве приложения

  2. SimpleOrder.ApplicationFacade (услуги приложений) - коренастого более высокого уровня, более крупных зерен способов оплаты rchestrating методы нижнего уровня в домене

  3. SimpleOrder.Contracts - классы DTO, используемые для связи между презентацией и прикладными услугами

  4. SimpleOrder.Domain (домен/BLL) - домен классы моделей клиентов, заказ, OrderItem, продукт

  5. SimpleOrder.Repository (даль) - реализует репо sitory интерфейсы

Вот мои варианты, как я вижу это:

Вариант 1: Определить интерфейсы хранилища в SimpleOrder.Contracts ...

PRO: это где я думаю они должны принадлежать, потому что я создал это для обмена контрактами между различными проблемами/слоями. например, DTO.

CON: однако метод подписи в каждом интерфейсе ссылается на классы модели домена.
Это означает, что мне нужно будет добавить ссылку на SimpleOrder.Domain, но когда SimpleOrder.Контракты ссылаются в другом проекте, он должен будет нести SimpleOrder.Domain для поездки. Это не так.

Вариант 2: тот же сценарий, что и выше, но я также определить интерфейсы для каждого домена модель класса в SimpleOrder.Contracts, так что я могу разорвать связь интерфейсов хранилища для реальных классов модели.

Пример:

 

    namespace SimpleOrder.Domain.Interfaces 
    { 
     public interface ICustomerRepository 
     { 
      ICustomer** GetCustomerById(int customerId); 
      void SaveCustomer(ICustomer customer); 
     } 

     public interface ICustomer 
     { 
      int CustomerId { get; set; } 
      string Name { get; set; } 
      System.Collections.Generic.List Orders { get; } 
     } 
    } 

IMPACT: Каждая модель доменный класс должен реализовать свой соответствующий интерфейс. то есть

 

    public class Customer : SimpleOrder.Domain.Interfaces.ICustomer 
    { 
     public Customer() 
     { 
      _orders = new List(); 
     } 

     public int CustomerId { get; set; } 
     public string Name { get; set; } 

     private List _orders; 
     public virtual List Orders { 
      get { return _orders; } 
     } 
    } 

PRO: Устраняет проблему Вариант 1.

CON: Это взрывает количество файлов (и воспринимаемую сложность) в проекте, потому что у каждый класс домена имеет связанный интерфейс.

Вариант 3: Определение хранилища intefaces в SimpleOrder.Domain

ВОЗДЕЙСТВИЯ: Для того, чтобы придать конкретные классы хранилища в слое служб приложений (проект SimpleOrder.ApplicationFacade) из SimpleOrder.ConsoleClient во время выполнения , SimpleOder.ConsoleClient также потребуется ссылка на SimpleOrder.Domain.

PRO: Это также решает Вариант 1

CON: Я пытался избежать ссылок домена слоя из слоя представления непосредственно, потому что теперь уровень представления может знать слишком много о доменном слое. Когда я буду заменять консольное приложение в будущем с помощью WPF или ASP.NET MVC-приложения в будущем, я рискую реализовать второй и последующие реализации уровня представления, пытаясь вызвать методы в модели вместо уровня приложений. (Тем не менее я считаю, что это в варианте 4.)

Вариант 4: Поместите интерфейсы в SimpleOrder.Domain, а затем ссылаться на SimpleOrder.Domain из SimpleOrder.ConsoleClient.

PRO: Устраняет все проблемы, описанные выше.

CON: Это не чувствует себя хорошо, потому что я бы предоставления доступа от слоя представления непосредственно к методам нижнего уровня в слое домена, когда я должен только предоставлять доступ к более высокому уровню коренастого методы в SimpleOrder.ApplicationFacade.

ВОПРОС Я попробовал каждый из них, но остановились на Вариант 4, ОДНАКО, что оставляет неприятный привкус во рту об этом. Есть ли лучший вариант? Я здесь, на правильном пути?

+0

При ближайшем рассмотрении ... варианты 3 и 4 в основном одинаковы. К сожалению. Мне следовало бы получить более подробное доказательство. –

ответ

9

Из чего я понимаю ваш вопрос, я бы согласился, что вариант 4 является лучшим. Интерфейсы репозитория должны быть объявлены на уровне домена рядом со всеми объектами домена. Реализация указанных интерфейсов должна быть частью уровня инфраструктуры - уровня, который соединяет ваш доменный мир с миром. Взгляните на Hexagonal Architecture, чтобы увидеть некоторые из причин для этого.

Чтобы решить проблему с опцией 4, вы не должны думать о том, что консольное приложение является только слоем презентации. У него также есть другие обязанности, такие как хост для приложения и composition root в терминах DI. В консольном приложении может быть компонент презентации, который взаимодействует только с приложениями. Вы также можете инкапсулировать службу приложения за open host service, реализованную с помощью ASP.NET WebAPI. Затем слой презентации будет ссылаться только на эту службу и быть скрытым от базового уровня домена.

+0

Основываясь на вашем ответе на мой предыдущий вопрос, и теперь этот, похоже, я собираюсь вам пить кофе или стейк или что-то в этом роде. :) У меня есть одно быстрое наблюдение ... вы написали «Из того, что я понимаю о вашем вопросе» ... по общему признанию, это было долгое время. Было ли что-то терминологическое или разумное, мудрое, что тоже звучало? СПАСИБО за ваш отличный ответ ... снова. –

+0

Что я имел в виду, так это то, что я не знаю всех деталей вашего проекта, поэтому я, возможно, пропустил ограничение. Но тем не менее, очень хорошо сформулированный вопрос! – eulerfx

0

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

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

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

+0

FYI луковая архитектура может быть по существу тем же самым, что и гексагональная; некоторые считают это рипоффом, так как гексагональная составляла некоторое время до лука. – eulerfx

+0

Я понимаю, что вы имеете в виду, спасибо за информацию. Почему архитектура архитектуры не описывает зависимость между UI/Application/Infrastructure? Обращаясь к вашему ответу, приложение несет ответственность за выбор того, какую реализацию инфраструктуры нужно использовать, потому что это выходит за рамки того, что они пытаются выразить с помощью этих моделей, или есть еще одна причина оставить это из моделей архитектуры? Я понимаю, что вы не создали модели; Мне просто интересно узнать ваше мнение по этому поводу. –

+0

В гексагональном интерфейсе пользовательский интерфейс является еще одним адаптером и может рассматриваться как инфраструктура. Возможно, я неправильно понял, что вы спросили? Какую зависимость между UI/App/Infrastructure вы имеете в виду? На мой взгляд, есть несколько перспектив. – eulerfx

Смежные вопросы