【发布时间】:2012-03-07 07:40:55
【问题描述】:
我的 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 数据缓存),其中大部分都有“永不过期”缓存策略,因此我在需要时手动将其逐出(如上)。
而用户部分基本上是给用户代表做某事(如堆栈)。
让我们回顾一下:我们将缓存、用户信誉处理、审计一应俱全。确实不属于一个地方。因此存在当前代码的问题,以及试图弄清楚如何将其移走的问题。
我想重构它的原因有几个:
- 难以进行单元测试。多线程和单元测试并不能很好地发挥作用。
- 可读性。很难阅读。凌乱。
- 建议零售价。控制器做得/知道的太多。
我解决了 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 空间中实现的。
最初的想法会告诉我创建某种“事件管理器”。但后来我想,这去哪里了?在域中?那么它如何处理与缓存的交互,这是一个基础设施问题。然后是线程,这也是一个基础架构问题。如果我想做的是同步而不是异步怎么办?是什么做出了这个决定?
我不想把所有这些逻辑都堆放在其他地方。理想情况下,应该将其重新分解为可管理且有意义的组件,而不是转移责任,如果这有意义的话。
有什么建议吗?
【问题讨论】:
-
+1 这是一个针对常见问题的好问题。我希望看到提供 n+1 个解决方案。之后去哪里......嗯:)
标签: c# asp.net-mvc asp.net-mvc-3 events design-patterns