Луковая архитектура

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

Создал слой Domain, перекинул все модели из старого проекта в новый, но появилась проблема. В сущности, пусть будет Article(статья), есть метод, который генерирует дату создания статьи

        public string GetData(Article model)
        {
            int createDate = Convert.ToInt32(model.CreateDate.ToString("dd"));
            int dateNow = Convert.ToInt32(DateTime.Now.ToString("dd"));

            if (createDate == dateNow)
                return $"Сегодня, {model.CreateDate.ToString("HH:mm")}";
            else if (dateNow - createDate == 1)
                return $"Вчера, {model.CreateDate.ToString("HH:mm")}";
            else
                return $"{model.CreateDate.ToString("dd MMMM, HH:MM")}";

        }

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

Так как слой Domain не может ничего знать про слой Service возникает проблема, ибо интерфейс находится в папке Service.

Как лучше поступить? Понимаю, что можно убрать наследование у модели, тогда не будет ошибки. Но так ведь не грамотно? Да и вообще, правильно ли содержать метод в модели?


Ответы (1 шт):

Автор решения: TemaKonkin

Шалом!

На самом деле проблема не в самом методе, а в том, что он находится в модели(энтити).

В луковой архитектуре есть несколько типов классов для работы с данными - это

  1. Entity
  2. DTO
  3. ViewModel

Это всё модели, которые хранят данные. Данные передаются из Базы данных в твое представление (WEB View на пример). Модели не содержат в себе методов, которые обрабатывают эти данные. Все манипуляции с данными в модели происходят в Service слое архитектуры проекта. В твоем случае - если надо обработать даты и записать в модель нужные тебе данные - то тебе нужно получить исходные данные из вьюхи или из базы, и обработать их в сервисе.

Собственно есть и архитектурные слои.

  1. Domain (тут твои Entity)
  2. Service (Тут DTO)
  3. Infrastructure (Различные интерфейсы и общие для Service и Presentation классы)
  4. Presentation (Тут ViewModel)

На пример тебе из вью пришла дата в виде 01-01-2023, тебе надо получить из неё только месяц и записать номер месяца в базу в виде числа. Тебе дата из вью пришла в контроллер, потом ты передаёшь её в сервис, в сервисе из даты берешь месяц, и дальше передаешь в домейн уже месяц в виде числа, записываешь энтити с месяцем в виде числа в БД.

Это работает и в обратную сторону. Если в базе у тебя хранится дата в виде 01-0-2023, а тебе надо в контроллере получить месяц из этой даты в виде числа - то ты в контроллере обращаешься к сервису, сервис обращается к домейну, домейн берет из базы данные, потом возвращает в сервис, сервис из даты берет месяц в виде числа, потом возвращает в контроллер уже число, контроллер передает во вью число месяца.

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

В этом суть луковой архитектуры и суть твоей проблемы - в этой архитектуре есть слои, и каждый слой имеет свою роль. Твоя модель выполняет роль сервиса (она производит изменение данных). Перенеси метод преобразования данных этой модели в сервис, а в модели оставь только поля, и будет тебе красота. Модель в сервис передашь, в сервисе преобразуешь как тебе надо, из контроллера вызовешь этот метод сервиса и получишь то что тебе надо, не нарушая идеи слоёв.

→ Ссылка