Внедрение ограниченного контекста в инфраструктуру на основе Entity Framework

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

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

Я попытался объяснить текущую ситуацию следующим образом.

DbCore: отвечает за операции с данными. Код Entity Framework 5 Впервые использован. Существует только один класс DbContext и все DbSet, определенные в нем. Также шаблон GenericRepository и шаблон Unit of Work реализованы на основе следующих интерфейсов.

IGenericRepository

public interface IGenericRepository<TEntity>
     where TEntity : class {
        void Delete(object id);
        void Delete(TEntity entityToDelete);
        System.Collections.Generic.IEnumerable<TEntity> Get(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Func<System.Linq.IQueryable<TEntity>, System.Linq.IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
        System.Collections.Generic.IEnumerable<TEntity> GetAll();
        TEntity GetByID(object id);
        System.Collections.Generic.IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters);
        void Insert(TEntity entity);
        void Update(TEntity entityToUpdate);
    }

IUnitOfWork

 public interface IUnitOfWork {
        void Dispose();
        IGenericRepository<Test> TestRepository {
            get;
        }
        IGenericRepository<Log> LogRepository {
            get;
        }
        void Save();
    }

Модели: ответственное хранение моделей сущностей для DbCore и Entity Framework. Домен: уровень бизнес-логики представления также хранит DTO для объектов сущностей, которые хранятся в проекте Models. В настоящее время бизнес-логика хранится в классе Service, который реализует следующий интерфейс IService.

public interface IService<TEntity> {

        IEnumerable<TEntity> Get();
        TEntity GetByID(int id);
        void Insert(TEntity entity);
    }

Этот класс обслуживания получает UnitOfWork через параметр ctor и использует его для операций. Также Automapper реализован для преобразования объектов сущностей в DTO или наоборот. Отныне все верхние уровни больше не интересуются моделями сущностей, а используют только DTO. Так что почти все проекты (включая API и веб) ссылаются на этот проект.

Общие. Отвечает за хранение часто используемых библиотек, таких как ведение журналов.

WebCore. Отвечает за хранение часто используемых библиотек для веб-проектов, таких как API или MVC. Также содержит расширения, обработчики и фильтры для проектов на основе MVC.

Api: проект веб-API ASP.Net MVC представляет уровень службы. Использует уровень домена и обслуживает клиентов. Контроллеры получают интерфейс IService в качестве параметра ctor и используют его для доступа к уровню данных через уровень домена.

Интернет: веб-проект на основе ASP.Net MVC 4, отвечающий за взаимодействие с пользователем. Использует методы API для доступа к данным. Все контроллеры получают интерфейс с именем IConsumeRepository, который подключается к API через HttpClient.

 public interface IConsumeRepository<TEntity> {
        Task<TEntity> Create(TEntity TestInfo);
        Task Delete(int id);       
        Task<IEnumerable<TEntity>> Get();
        Task<TEntity> Get(int id);
        TEntity New();       
        Task<TEntity> Update(TEntity TestInfo, int entityId);
    }

Autofac отвечает за IoC и DI для всех проектов.

На данный момент это моя текущая инфраструктура, я думаю, что объяснил все, что нужно оценить.

Теперь я пытаюсь выяснить следующие вещи,

Вопрос 1: Есть ли что-то, что НЕ ДОЛЖНО быть реализовано так, как я использовал?

Вопрос 2. Каков наилучший подход к реализации ограниченных контекстов? Недавно я посмотрел видео Джули Лерман и просмотрел множество примеров проектов. Обычная вещь, которую я видел, получая BC от DbContext. Но я не мог быть уверен. Потому что я думал, что BC должны быть на уровне домена (бизнес-логика), а не на уровне DbCore (доступ к данным).

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

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




Ответы (1)


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

Вопрос 2. Сколько различных моделей предметной области (с разными распространенными языками) у вас есть? Один? Два? Три? Максимально изолируйте каждую модель от других моделей и проблем инфраструктуры.

Эрик Эванс определяет ограниченный контекст прежде всего как лингвистическую границу (цитата из его книги):

ОГРАНИЧЕННЫЙ КОНТЕКСТ ограничивает применимость конкретной модели, чтобы у членов команды было четкое и общее понимание того, что должно быть согласованным, и как это связано с другими КОНТЕКСТАМИ. В рамках этого КОНТЕКСТА работайте над сохранением логической унификации модели, но не беспокойтесь о применимости вне этих границ. В других КОНТЕКСТАХ применяются другие модели, с различиями в терминологии, в концепциях и правилах, а также в диалектах ВЕЗДЕСУЩЕГО ЯЗЫКА.

DBContext может указать вам правильное направление, но помните, что это артефакт инфраструктуры, а не предметная концепция. Он «представляет собой комбинацию шаблонов Unit-Of-Work и Repository и позволяет запрашивать базу данных и группировать изменения, которые затем будут записаны обратно в хранилище как единое целое». //msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=vs.103).aspx" rel="noreferrer">документы MSDN).

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

Вопрос 3. DTO может быть хорошим способом обеспечить соблюдение границ контекста, например, для API. Затем API может функционировать как уровень защиты от коррупции для других моделей. Причина, по которой люди обычно используют их для пользовательских интерфейсов, заключается в том, чтобы избежать включения концепций пользовательского интерфейса в модель предметной области.

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

person Paul Rayner    schedule 15.02.2013
comment
хотелось бы иметь возможность нажимать здесь +1 несколько сотен раз! - person Julie Lerman; 15.02.2013