Где (на каком уровне) должны находиться перечисления в многоуровневой архитектуре?

Имеется каркас приложения с использованием многоуровневой (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 шт):

Автор решения: A K

Вообще говоря с чисто практической точки зрения я обычно делаю в проекте Domain папку Models и Enums. И этого вполне хватает для обычных целей.

Если же рассматривать луковые и DDD-based архитектуры, то в них обычно рекомендуется делать проект Domain (абстракции, характерные для вашего приложения) и проект Core (абстракции характерные для предметной области). В этом случае смотрите сами, куда ваши конкретные Enum'ы относятся - специфичные для приложения или специфичные для вашей предметной области.

Я бы так сильно проекты не дробил (сомневаюсь, что вы из каждого проекта будете отдельный nuget собирать для внешних подрядчиков), но если очень хочется -- то лучше назовите ваш проекта как RootNs.Domain.Enums или хотя бы RootNs.Domain.Core, слово Shared как по мне тянет избыточные ассоциации.

Вот пример из моего реального проекта (некоторые фрагменты описывал ранее):

введите сюда описание изображения

Здесь большинство enum'ов (типа словаря ролей - мафия, шериф, мирный житель) лежат себе в Domain и нет никакой потребности интерейсы и енамы по отдельным проектам распихивать.

А вот тут можно посмотреть старые архитектуры, которые я строил на сервисах и репозиториях, тут видно, что все интерфейсы лежат в домене, а реализации -- в DAL/Persistence. Судя по вашему вопросу у вас реализации интерфейсов подключают проекты домена и БД, в таком случае как по мне enum'ы должны лежать там, где нужнее (если в домене не понадобились -- снесите в реализацию, если понадобились - вынесите в домен).

Также часто в DDD проектах я вижу проект Common в который сносят вещи, которые не влезают в чёткие абстракции :)

→ Ссылка