通过遵循最佳实践,可以编写更好的节制器。所谓的“瘦”节制器(指代码更少、职责更少的节制器)更容易阅读和维护。并且,一旦你的节制器很瘦,大概就不需要对它们举办太多测试了。相反,你可以专注于测试业务逻辑和数据会见代码。瘦节制器的另一个利益是,它更容易维护节制器的多个版本。
这篇文章接头了使节制器变胖的坏习惯,然后摸索了使节制器变瘦和易于打点的要领。我列出编写节制器的最佳实践大概并不全面,但我已经接头了最重要的一些,并在适当的环境下提供了相关的源代码。在接下来的几节中,我们将研究什么是胖节制器,为什么它是一种代码坏味道,瘦节制器是什么,为什么它是有益的,以及如何使节制器瘦、简朴、可测试和可打点。
从节制器中删除数据会见代码
在编写节制器时,你应该僵持单一责任原则,这意味着节制器应该有“一个责任”或“有且只有一个原因可以变动”。换句话说,你但愿将变动节制器代码的原因减至最少。下面的代码显示了具有数据会见逻辑的典范节制器。
在.NET生态系统中利用特定的技能仓库会发生一些狐疑,因为有许多选择,好比应该利用哪种范例的运行时?在这篇文章中,我们将试图把这些要点都说清楚。
public class AuthorController : Controller { private AuthorContext dataContext = new AuthorContext(); public ActionResult Index(int authorId) { var authors = dataContext.Authors .OrderByDescending(x=>x.JoiningDate) .Where(x=>x.AuthorId == authorId) .ToList(); return View(authors); } }
在action内部利用数据上下文实例读取数据,违反了单一职责原则,并使你的节制器充斥着不该该呈此刻哪里的代码。在本例中,我们利用一个DataContext(假设我们利用Entity Framework Core)来毗连、处理惩罚数据库中的数据。
来日诰日假如你抉择变动数据会见技能(为了更好的机能或其他原因),你也必需变动你的节制器。譬喻,假如我想利用Dapper毗连到底层数据库该怎么办?更好的要领是利用repository类来封装数据会见逻辑(尽量我不太喜欢repository模式)。让我们用以下代码更新AuthorController。
public class AuthorController : Controller { private AuthorRepository authorRepository = new AuthorRepository(); public ActionResult Index(int authorId) { var authors = authorRepository.GetAuthor(authorId); return View(authors); } }
节制器此刻看起来更瘦了。那么这是编写这个节制器的最佳要领吗?不是。假如你的节制器正在会见数据会见组件,那么它将做太多的工作,因此违反了单一职责原则。节制器不该该有直接会见数据会见组件的数据会见逻辑或代码。下面是AuthorController类的改造版本。
public class AuthorController : Controller { private AuthorService authorService = new AuthorService(); public ActionResult Index(int authorId) { var authors = authorService.GetAuthor(authorId); return View(authors); } }
AuthorService类操作AuthorRepository类执行CRUD操纵。
public class AuthorService { private AuthorRepository authorRepository = new AuthorRepository(); public Author GetAuthor (int authorId) { return authorRepository.GetAuthor(authorId); } }
制止编写样板代码来映射工具
你常常需要映射数据传输工具(DTO)和域工具,反之亦然。请参考下面给出的代码片断,它显示了节制器要领内部的映射逻辑。
public IActionResult GetAuthor(int authorId) { var author = authorService.GetAuthor(authorId); var authorDTO = new AuthorDTO(); authorDTO.AuthorId = author.AuthorId; authorDTO.FirstName = author.FirstName; authorDTO.LastName = author.LastName; authorDTO.JoiningDate = author.JoiningDate; }
你不该该在节制器中编写这样的映射逻辑,因为它会使节制器膨胀并增加特另外责任。假如你要编写映射逻辑,可以操作像AutoMapper这样的工具映射器东西来制止编写大量样板代码。
最后,你应该将映射逻辑移到前面建设的处事类中。留意AutoMapper是如何被用来映射两个不兼容的范例Author和AuthorDTO的。
public class AuthorService { private AuthorRepository authorRepository = new AuthorRepository(); public AuthorDTO GetAuthor (int authorId) { var author = authorRepository.GetAuthor(authorId); return Mapper.Map<AuthorDTO>(author); } }
制止在节制器中编写业务逻辑代码
不该该在节制器中编写业务逻辑或验证逻辑。节制器应该只接管一个请求,然后跳转下一个action,除此之外没有其他的。所有的业务逻辑代码都应该转移到其他类中(好比我们前面建设的AuthorService类)。有几种要领可以在请求管道中配置验证器,而不要在节制器中编写验证逻辑。这会使你的节制器变得不须要的臃肿,并让它认真它不该该做的任务。
更喜欢依赖注入而不是组合