Хочется прояснить несколько вопросов по указанной связке и по архитектурным вопросам в целом.
1) Во-первых DDD + REST, каким образом они вообще обьединяются? Что-то ничего нормального не нагугливается, приводятся тривиальные примеры get/post/put/delete где user/id=5 и никаких примеров из реальной жизни. Как сделать в REST что-то из рязряда GetAllUsersWhoWasBornOnMonday(), ActivateUser(int id), SelectCardsWithZeroBalance(), LoadUserDetailsPage(), AssignUserToGroup(int userID, int groupID)
2) Как производится тестирование слоя DDD и сервисов. Скажем есть у нас домейн класс Person
Person
{
public string Name {get;set}
public string Surname {get;set}
public Date DOB {get;set};
public CalculateAge()
}
и есть сервис который дергается из REST
UserWorkflow
{
public bool SendUserPromotion(int userID)
{
if (userID < 0)
throw new InvalidUserID();
User user = UserRepository.GetUser(userID);
if (user == null)
throw new InvalidUser();
if (user.CalculateAge() > 18)
{
EmailService.SendPromotionEmail(userID);
LogService.LogCommunition(userID, "Promotion was send");
UserRepository.UpdateUserLastPromotionDate(userID);
return true;
}
else
{
LogService.LogError(userID, "Promotion was not send, user is too young");
return false;
}
}
Понятно, что тут для юнит-тестирования следует замокить email service и repository, однако есть пара вопросов:
— Как проверить что EmailService, LogService и UserRepository были вызваны с нужными параметрами (юзер старше 18 лет) или не вызваны?
— Что делать собственно с домейн классом Person, если я его напрямую использую в тесте сервиса, то это вроде уже не юнит тест будет, а интеграционный, а мокить Person через интерфейс будет откровенный ужас и оверкилл
— Стоит-ли тестировать Person.CalculateAge() метод в этом случае
— Обьединяя с вопросом номер 1 — как будет SendUserPromotion() операция выглядить через интерфейс REST?
3) Вопрос по Репозиторию. Очевидно его интерфейс быстро обрастает методами UpdateUserLastPromotionDate(), GetAllUsersWhoWasBornOnMonday() и AssignUserToGroup(). Какие существуют методы по структуризации всего этого, что-бы его класс не превращался в свалку из десятков таких разношерстных методов?
Скажу сразу я знаю о существовании идеи не использовать репозиторий вообще, а прямо в методе сервиса писать соответствующие EF запросы, однако такие идеи хороши в теории, а на практике приводят к лапше из кода бизнес-логики, запросов к данным и конвертации модели данных к бизнес-моделям, а самое главное для написания юнит-тестов всего этого проходится мокить сам EF контекст, что отнимает жуткое количество времени, и позволяет тестить только простейшие запросы