На моем сайте ASP.NET MVC 3 есть такой код контроллера:
[HttpPost]
public ActionResult Save(PostViewModel viewModel)
{
// VM -> Domain Mapping. Definetely belongs here. Happy with this.
var post = Mapper.Map<PostViewModel, Post>(viewModel);
// Saving. Again, fine. Controllers job to update model.
_postRepository.Save(post);
// No. Noooo..caching, thread spawning, something about a user?? Why....
Task.Factory.StartNew(() => {
_cache.RefreshSomeCache(post);
_cache2.RefreshSomeOtherCache(post2);
_userRepository.GiveUserPoints(post.User);
_someotherRepo.AuditThisHappened();
});
// This should be the 3rd line in this method.
return RedirectToAction("Index");
}
По сути, я имею в виду код в блоке потоков. Все вещи должны происходить, но пользователю не нужно ждать их (хороший пример для фонового потока, верно?).
Просто чтобы прояснить ситуацию, я использую кеширование (обычный кеш данных ASP.NET) по всему сайту, и у большинства из них есть политика кеширования "не истекает", поэтому я вручную выталкиваю ее, когда требуется (как описано выше).
И пользовательская часть, в основном, дает пользователю репутацию за что-то (например, стек).
Итак, подведем итоги: у нас есть кэширование, обработка репутации пользователя, аудит - все в одном. На самом деле не принадлежит ни к одному месту, делает это. Отсюда проблема с текущим кодом и проблема с попыткой выяснить, как его убрать.
Причина, по которой я хочу провести рефакторинг, по нескольким причинам:
- Сложно провести юнит-тест. Многопоточность и модульное тестирование не очень-то хороши.
- читаемость. Трудно читать. Грязное.
- SRP. Контролер делает / знает слишком много.
Я решил 1), обернув код, порождающий потоки, в интерфейс, и просто высмеял это.
Но я бы хотел сделать какой-нибудь шаблон, где мой код мог бы выглядеть так:
[HttpPost]
public ActionResult Save(PostViewModel viewModel)
{
// Map.
var post = Mapper.Map<PostViewModel, Post>(viewModel);
// Save.
_postRepository.Save(post);
// Tell someone about this.
_eventManager.RaiseEvent(post);
// Redirect.
return RedirectToAction("Index");
}
По сути, возлагать бремя на "что-то другое", чтобы реагировать, а не на контроллер.
Я слышал / читал о задачах, командах, событиях и т. Д., Но еще не видел ни одного, реализованного в пространстве ASP.NET MVC.
Первые мысли сказали бы мне создать своего рода "менеджера событий". Но потом я подумал, куда это денется? В домене? Тогда как он обрабатывает взаимодействия с кешем, что является проблемой инфраструктуры. А затем многопоточность, которая также является проблемой инфраструктуры. А что если я хочу сделать синхронно, а не асинхронно? Что делает это решение?
Я не хочу просто складывать всю эту логику где-то еще. В идеале он должен быть преобразован в управляемые и значимые компоненты, а не в сдвинутую ответственность, если это имеет смысл.
Любой совет?