docker build -t testapp:latest .
docker-compose up -dТак как это тестовое задание, оно не должно занимать много времени на выполнение, поэтому я решила уделить ему не более пары вечеров. Если бы это было реальное задание, я бы уделила больше времени на проработку архитектуры приложения, я бы не стала допускать некоторых упрощений, к примеру:
- В тестовом задании не было указано требование по аутентификации и авторизации пользователей, поэтому я сознательно не стала создавать сервис для получения идентификатора пользователя, а добавила его в качестве параметра в запросы.
- Архитектура немного упрощена, не реализованы механизмы диспетчеризации доменных событий, не реализованы очереди сообщений для взаимодействия между сервисами. Для отправки уведомлений через SignalR сервис INotificationService напрямую инжектится в IConfigurationService, что в реальном приложении, как мне кажется, лучше вынести в обработчики доменных событий.
- Не было явного указания обязательности логирования, поэтому я не подключала NLog или Serilog, но в реальном приложении я бы обязательно это сделала.
- Вместо миграций базы данных присутствует простая проверка на наличие базы при старте приложения с помощью context.Database.EnsureCreated().
- Не заведены кастомные исключения для различных ошибок, не реализована глобальная обработка ошибок.
- Юнит-тесты плотно покрывают доменный слой, в application слое тесты покрывают только основные сценарии, связанные с внесением изменений в данные.
По структуре приложение разделено на 4 стандартных слоя:
- Domain - сущности, интерфейсы репозиториев и сервис доменного слоя.
- Application - сервисы приложения.
- Infrastructure - реализация репозиториев, контекст базы данных.
- API - содержит контроллеры и настройку веб-приложения.
Доменная сущность состоит из корневого агрегата (непосредственно сама конфигурация), сущности (версии конфигурации) и Value Objects (непосредственно настройки). Поля сущностей помечены модификаторами private set, изменять их можно только через методы. Небольшое исключение касается только Settings.cs - для записи в БД я использовала тип jsonb с исползованием JSON конвертера, поэтому для возможности сериализации/десериализации у класса Settings пришлось оставить публичные сеттеры (init) и конструктор без параметров.