-
Notifications
You must be signed in to change notification settings - Fork 237
为什么要分 MVC 三层开发
这里提高的MVC是广义上的,MVC主要应用于之前的web开发模式,现在大部分业务都是开发接口的方式,所以我们可以分为这三层:Contoller 层、Service 层、Repository 层。当然也适用于web开发的模式。对于这种分层方式,我相信大部分人都很认同,甚至成为了一种开发习惯,但你有没有想过,为什么我们要分层开发?很多业务都比较简单,一层代码搞定所有的数据读取、业务逻辑、接口暴露不好吗?你可以把它作为一道面试题,试着自己思考下,然后再看我下面的说明。
对于这个问题,我总结了以下几点原因。
同一个 Repository 可能会被多个 Service 来调用,同一个 Service 可能会被多个 Controller 调用。比如,UserService 中的 getUserById() 接口封装了通过 ID 获取用户信息的逻辑,这部分逻辑可能会被 UserController 和 AdminController 等多个 Controller 使用。如果没有 Service 层,每个 Controller 都要重复实现这部分逻辑,显然会违反 DRY 原则。
分层体现了一种抽象和封装的设计思想。比如,Repository 层封装了对数据库访问的操作,提供了抽象的数据访问接口。基于接口而非实现编程的设计思想,Service 层使用 Repository 层提供的接口,并不关心其底层依赖的是哪种具体的数据库。当我们需要替换数据库的时候,比如从 MySQL 到 Oracle,从 Memcache 到 Redis,只需要改动 Repository 层的代码,Service 层的代码完全不需要修改。
除此之外,Controller、Service、Repository 三层代码的稳定程度不同、引起变化的原因不同,所以分成三层来组织代码,能有效地隔离变化。比如,Repository 层基于数据库表,而数据库表改动的可能性很小,所以 Repository 层的代码最稳定,而 Controller 层提供适配给外部使用的接口,代码经常会变动。分层之后,Controller 层中代码的频繁改动并不会影响到稳定的 Repository 层。
Repository 层只关注数据的读写。Service 层只关注业务逻辑,不关注数据的来源。Controller 层只关注与外界打交道,数据校验、封装、格式转换,并不关心业务逻辑。三层之间的关注点不同,分层之后,职责分明,更加符合单一职责原则,代码的内聚性更好。
单元测试的时候,不依赖不可控的外部组件,比如数据库。分层之后,Repsitory 层的代码通过依赖注入的方式供 Service 层使用,当要测试包含核心业务逻辑的 Service 层代码的时候,我们可以用 mock 的数据源替代真实的数据库,注入到 Service 层代码中。代码的可测试性和单元测试我们后面会讲到,这里你稍微了解即可。
所有的代码都放到一个类中,那这个类的代码就会因为需求的迭代而无限膨胀。我们知道,当一个类或一个函数的代码过多之后,可读性、可维护性就会变差。那我们就要想办法拆分。拆分有垂直和水平两个方向。水平方向基于业务来做拆分,就是模块化;垂直方向基于流程来做拆分,就是这里说的分层。
@ 1024casts