目录
- 应用分层
- 介绍
- 代码重构
- 应用分层的好处
- 企业规范
应用分层
通过上⾯的练习, 我们学习了Spring MVC简单功能的开发, 但是我们也发现了⼀些问题
⽬前我们程序的代码有点"杂乱", 然⽽当前只是"⼀点点功能"的开发. 如果我们把整个项⽬功能完成呢?
代码会更加的"杂乱⽆章"(⽂件乱, 代码内容乱)
也基于此, 咱们接下来学习应⽤分层.
类似公司的组织架构
公司初创阶段, ⼀个⼈⾝兼数职, 既做财务, ⼜做⼈事, 还有⾏政.
随着公司的逐渐壮⼤, 会把岗位进⾏细分, 划分为财务部⻔, ⼈事部⻔, ⾏政部⻔等. 各个部⻔内部还会再进⾏细分.
项⽬开发也是类似, 最开始功能简单时, 我们前后端放在⼀起开发, 随着项⽬功能的复杂, 我们分为前端和后端不同的团队, 甚⾄更细粒度的团队. 后端开发也会根据功能再进⾏细分. MVC就是其中的⼀种拆分⽅式.
但是随着后端⼈员不再涉及前端, 后端开发⼜有了新的分层⽅式
介绍
阿⾥开发⼿册中, 关于⼯程结构部分, 定义了常⻅⼯程的应⽤分层结构:
那么什么是应⽤分层呢?
应⽤分层 是⼀种软件开发设计思想, 它将应⽤程序分成N个层次, 这N个层次分别负责各⾃的职责, 多个层次之间协同提供完整的功能. 根据项⽬的复杂度, 把项⽬分成三层, 四层或者更多层.
常⻅的MVC设计模式, 就是应⽤分层的⼀种具体体现.
为什么需要应⽤分层?
在最开始的时候,为了让项⽬快速上线,我们通常是不考虑分层的. 但是随着业务越来越复杂,⼤量的代码混在⼀起,会出现逻辑不清晰、各模块相互依赖、代码扩展性差、改动⼀处就牵⼀发⽽动全⾝等问题. 所以学习对项⽬进⾏分层就是我们程序员的必修课了.
如何分层(三层架构)
“MVC”, 就是把整体的系统分成了 Model(模型),View(视图)和Controller(控制器)三个层次,也就是将⽤⼾视图和业务处理隔离开,并且通过控制器连接起来,很好地实现了表现和逻辑的解耦,是⼀种标准的软件分层架构。
⽬前现在更主流的开发⽅式是 “前后端分离” 的⽅式, 后端开发⼯程师不再需要关注前端的实现, 所以对于Java后端开发者, ⼜有了⼀种新的分层架构: 把整体架构分为表现层、业务逻辑层和数据层. 这种分层⽅式也称之为"三层架构".
- 表现层: 就是展⽰数据结果和接受⽤⼾指令的,是最靠近⽤⼾的⼀层;
- 业务逻辑层: 负责处理业务逻辑, ⾥⾯有复杂业务的具体实现;
- 数据层: 负责存储和管理与应⽤程序相关的数据
可以看到, 咱们前⾯的代码, 并不符合这种设计思想, ⽽是所有的代码堆砌在⼀起
按照上⾯的层次划分, Spring MVC 站在后端开发⼈员的⻆度上, 也进⾏了⽀持, 把上⾯的代码划分为三个部分:
- 请求处理、响应数据:负责,接收⻚⾯的请求,给⻚⾯响应数据.(表现层)
- 逻辑处理:负责业务逻辑处理的代码.(业务逻辑层)
- 数据访问:负责业务数据的维护操作,包括增、删、改、查等操作.(数据层)
这三个部分, 在Spring的实现中, 均有体现:
- Controller:控制层。接收前端发送的请求,对请求进⾏处理,并响应数据。
- Service:业务逻辑层。处理具体的业务逻辑。
- Dao:数据访问层,也称为持久层。负责数据访问操作,包括数据的增、删、改、查。
MVC 和三层架构的区别和联系
关于⼆者的关系, ⼀直存在不同的观点. 有⼈认为三层架构是MVC模式的⼀种实现, 也有⼈认为MVC是三层架构的替代⽅案, 等等各种说法都有. 根本原因是⼤家站在不同的⻆度来看待这个问题的.
从概念上来讲, ⼆者都是软件⼯程领域中的架构模式.
MVC架构模式由三部分组成, 分别是: 模型(Model), 视图(View)和控制器(Controller).
三层架构将业务应⽤划分为:表现层, 业务逻辑层, 数据访问层.
MVC中, 视图和控制器合起来对应三层架构中的表现层. 模型对应三层架构中的业务逻辑层,数据层,以及实体类
⼆者其实是从不同⻆度对软件⼯程进⾏了抽象.
MVC模式强调数据和视图分离, 将数据展⽰和数据处理分开, 通过控制器对两者进⾏组合.
三层架构强调不同维度数据处理的⾼内聚和低耦合, 将交互界⾯, 业务处理和数据库操作的逻辑分开.
⻆度不同也就谈不上互相替代了,在⽇常的开发中可以经常看到两种共存的情况,⽐如我们设计模型层的时候往往也会拆分出业务逻辑层(Service层)和数据访问层(Dao层)。
但是⼆者的⽬的是相同的, 都是"解耦,分层,代码复⽤"
软件设计原则:⾼内聚低耦合.
⾼内聚指的是:⼀个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越⾼,则内聚性越⾼,即 “⾼内聚”。
低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。修改⼀处代码, 其他模块的代码改动越少越好.
高内聚:一个模块内部的关系
低耦合:各个模块之间的关系
⾼内聚低耦合⽭盾吗?
不⽭盾, ⾼内聚指的是⼀个模块中各个元素之间的联系的紧密程度, 低耦合指的是各个模块之间的紧密程度
这就好⽐⼀个企业, 包含很多部⻔, 各个部⻔之间的关联关系要尽可能的⼩, ⼀个部⻔发⽣问题, 要尽可能对降低对其他部⻔的影响, 就是耦合. 但是部⻔内部员⼯关系要尽量紧密, 遇到问题⼀起解决,克服. 这叫做内聚.
⽐如邻⾥邻居, 楼上漏⽔, 楼下遭殃, 就是耦合. 家庭⼀个成员⽣病, 其他成员帮忙照顾, 就叫内聚.
⼀个家庭内部的关系越紧密越好, ⼀个家庭尽可能少的影响另⼀个家庭, 就是低耦合.
代码重构
我们使⽤上⾯的分层思想, 来对代码进⾏改造
先创建对应的包路径, 并把代码移到对应的⽬录
com.example.demo.controller
com.example.demo.service
com.example.demo.dao
com.example.demo.model
代码拆分
控制层: 接收前端发送的请求,对请求进⾏处理,并响应数据
@RestController
@RequestMapping("/book")
public class BookController {
private BookService bookService=new BookService();
@RequestMapping("/getBookList")
public List<BookInfo> getBookList(){
List<BookInfo> bookInfos = bookService.getBookList();
//3.返回数据
return bookInfos;
}
}
业务逻辑层: 处理具体的业务逻辑。
public class BookService {
private BookDao bookDao=new BookDao();
public List<BookInfo> getBookList(){
//1.获取图书数据
List<BookInfo> bookInfos=bookDao.mockData();
//2.对图书数据进行修改处理
for(BookInfo bookInfo:bookInfos){
if(bookInfo.getStatus()==1){
bookInfo.setStatusCN("可借阅");
}else{
bookInfo.setStatusCN("不可借阅");
}
}
return bookInfos;
}
}
数据访问层: 负责数据访问操作,包括数据的增、删、改、查
public class BookDao {
//mock - 虚拟数据,假数据
public List<BookInfo> mockData() {
//对于已知的数据量或者大概知道这个集合的数量时,创建List时建议指定初始化容量
List<BookInfo> bookInfos=new ArrayList<>(15);
for(int i=0;i<15;i++){
BookInfo bookInfo=new BookInfo();
bookInfo.setId(i);
bookInfo.setBookName("图书"+i);
bookInfo.setAuthor("作者"+i);
bookInfo.setCount(new Random().nextInt(200));
bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));
bookInfo.setPublish("出版社"+i);
bookInfo.setStatus(i%5==0?2:1);
bookInfos.add(bookInfo);
}
return bookInfos;
}
}
应用分层的好处
- 降低层与层之间的依赖, 结构更加的明确, 利于各层逻辑的复⽤
- 开发⼈员可以只关注整个结构中的其中某⼀层, 极⼤地降低了维护成本和维护时间
- 可以很容易的⽤新的实现来替换原有层次的实现
- 有利于标准化
企业规范
- 类名使⽤⼤驼峰⻛格,但以下情形例外:DO/BO/DTO/VO/AO
- ⽅法名、参数名、成员变量、局部变量统⼀使⽤⼩驼峰⻛格
- 包名统⼀使⽤⼩写,点分隔符之间有且仅有⼀个⾃然语义的英语单词.
- 数据库、字段,用蛇形
常⻅命名命名⻛格介绍
⼤驼峰: 所有单词⾸字⺟都需要⼤写, ⼜叫帕斯卡命名法, ⽐如: UserController
⼩驼峰: 除了第⼀个单词,其他单词⾸字⺟⼤写,⽐如: userController
蛇形: ⽤下划线(_)作⽤单词间的分隔符, ⼀般⼩写, ⼜叫下划线命名法, ⽐如: user_controller
串形: ⽤短横线(-)作⽤单词间的分隔符, ⼜叫脊柱命名法, ⽐如: user-controller