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

Фон

Я пытаюсь создать простое приложение, чтобы действительно понять весь стек 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 ссылается на класс модели Customer, определенный на уровне домена. Это типично для других хранилищ.

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

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

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

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

SimpleOrder.Domain (domain / bll) - доменная модель классов Customer, Order, OrderItem, Product

SimpleOrder.Repository (dal) - реализует интерфейсы репозитория

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

Опция 1: Определите интерфейсы репозитория в SimpleOrder.Contracts ...

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

CON: однако сигнатуры методов каждого интерфейса ссылаются на классы модели домена.
Это означает, что мне нужно было бы добавить ссылку на SimpleOrder.Domain, но когда ссылка на SimpleOrder.Contracts упоминается в другом проекте, он должен будет нести 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; }
        }
    }

ВОЗДЕЙСТВИЕ: Каждый класс модели предметной области должен был бы реализовать свой связанный интерфейс. т.е.

    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: Определите интерфейсы репозитория в 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, ОДНАКО, который оставляет неприятный вкус во рту по этому поводу. Есть ли лучший вариант? Я на правильном пути здесь?

Ответы на вопрос(2)

Ваш ответ на вопрос