Где (на каком уровне) должны находиться перечисления в многоуровневой архитектуре?
Имеется каркас приложения с использованием многоуровневой (Onion) архитектуры. На данный момент структура решения в VisualStudio выглядит так:
RootNs (Solution)
├ Domain (Solution Folder)
│ ├ RootNs.Domain.DataModel
│ ├ RootNs.Domain.Interfaces
│ └ RootNs.Domain.Core
├ Services (Solution Folder)
│ ├ RootNs.Services.DomainServices
│ └ RootNs.Services.ApplicationServices
├ Infrastructure (Solution Folder)
│ └ RootNs.Infrastructure
└ Presentation (Solution Folder)
└ RootNs.Presentation.Wpf
Интерфейсы (RootNs.Domain.Interfaces) находятся на самом нижнем/внутреннем уровне и по идее не должны ни от чего зависеть.
Но где в этом случае должны определяться перечисления, используемые при определении интерфейсов? Сейчас делаю так:
// RootNs.Domain.Core
public enum FontFamily
{
Serif = 0,
SansSerif = 1,
Monospace = 2
}
[Flags]
public enum TextDecoration
{
None = 0,
Bold = 1,
Italic = 2,
Underline = 4
}
// RootNs.Domain.Interfaces
public interface ITextBox
{
TextDecoration TextDecoration { get; set; }
FontFamily FontFamily { get; set; }
// etc.
}
// RootNs.Domain.DataModel
public class TextBox : ITextBox
{
// interface implementation...
}
В приведённом выше примере TextBox является частью сущности, которая будет сохранятся в хранилище. Само приложение будет содержать уровни представления для WPF и консоли.
На данный момент (по совету A K) добавил перечисления и структуры, используемые в интерфейсах и доменной модели, в RootNs.Domain.Core и уже Core добавил как зависимость в интерфейсы и модель. Правильно ли это?
Ответы (1 шт):
Вообще говоря с чисто практической точки зрения я обычно делаю в проекте Domain папку Models и Enums. И этого вполне хватает для обычных целей.
Если же рассматривать луковые и DDD-based архитектуры, то в них обычно рекомендуется делать проект Domain (абстракции, характерные для вашего приложения) и проект Core (абстракции характерные для предметной области). В этом случае смотрите сами, куда ваши конкретные Enum'ы относятся - специфичные для приложения или специфичные для вашей предметной области.
Я бы так сильно проекты не дробил (сомневаюсь, что вы из каждого проекта будете отдельный nuget собирать для внешних подрядчиков), но если очень хочется -- то лучше назовите ваш проекта как RootNs.Domain.Enums или хотя бы RootNs.Domain.Core, слово Shared как по мне тянет избыточные ассоциации.
Вот пример из моего реального проекта (некоторые фрагменты описывал ранее):
Здесь большинство enum'ов (типа словаря ролей - мафия, шериф, мирный житель) лежат себе в Domain и нет никакой потребности интерейсы и енамы по отдельным проектам распихивать.
А вот тут можно посмотреть старые архитектуры, которые я строил на сервисах и репозиториях, тут видно, что все интерфейсы лежат в домене, а реализации -- в DAL/Persistence. Судя по вашему вопросу у вас реализации интерфейсов подключают проекты домена и БД, в таком случае как по мне enum'ы должны лежать там, где нужнее (если в домене не понадобились -- снесите в реализацию, если понадобились - вынесите в домен).
Также часто в DDD проектах я вижу проект Common в который сносят вещи, которые не влезают в чёткие абстракции :)
