分层思想,是应用系统最常见的一种架构模式,我们会将系统横向切割,根据业务职责划分。MVC 三层架构就是非常典型架构模式,划分的目的是规划软件系统的逻辑结构便于开发维护。MVC:英文即 Model-View-Controller,分成模型层、视图层、控制层。将页面和业务逻辑分离,提高应用的可扩展性及可维护性。如图所示。

事实上,MVC 三层架构只是概念层面的指导思想,我们会将层次结构划分的更加细致。例如,传统后端的 MVC 模式对于前后端的划分界限比较模糊。一般情况下,前端开发人员负责编写项目的静态页面,包括 HTML 页面、CSS 样式与 JavaScript 交互部分,并提供给服务端开发人员编写视图层业务,甚至有的项目直接让前端开发人员完成视图层的业务开发任务。这样的开发模式造成的问题在于,前后端在开发过程中分工不明确,并且存在相互强依赖,前端开发人员需要关心服务端的业务,服务端开发人员也需要依赖前端的进度。并且随着 Android、 IOS、 PC 以及 U3D 等多个客户端加入,程序的开发成本与维护成本会指数级上升。为了提高开发效率,细化职责,前后端分离的需求越来越被重视。前后端分离在于服务端提供 API 接口,前端调用 AJAX 实现数据交互。如图所示。

此外,随着数据存储能力的不断扩展(MySQL、Oracle、Redis、MongoDB、ElasticSearch、PostgreSQL、HBase 等),以及随着微服务的流行与普及,我们经常通过 RPC(Dubbo、HSF、Thrift 等)依赖很多外部接口或 HTTP 调用第三方平台。因此,我们需要一套细致划分的代码结构。此外,很多时候,我们在开发过程中,也并没有把它们职责划分开。例如,在代码结构中,我们将非常多的逻辑业务放在了 Controller 层,而只把 Service 作为数据透传的途径了。事实上,这个是不对的。无独有偶,我们还会发现有的项目中在 Dao 层调用远程服务,也有的会在 Service 层或者 Controller 层进行这样的操作,由于不同研发同学的习惯不同,或者偷工取巧导致开发代码风格完全不同,代码层次结构混乱。

总结一下,MVC 三层架构只是概念层面的指导思想,我们会将层次结构划分的更加细致。现在,我们来深入探讨“如何合理的设计代码分层,论代码分层的设计之道”。在笔者看来,合理的代码分层应该是这样的。如图所示。

其中,数据持久层 承载了数据存储和访问的能力,它既与底层数据进行交换,包括 MySQL、Oracle、Redis、MongoDB、ElasticSearch、PostgreSQL、HBase 等,又通过 Pxoxy 的代理和包装与远程服务数据进行联动。因此,在业务逻辑层调用时,它对底层的数据实现方式是无感知的,无论是哪种数据存储方式,以及它是远程数据,还是本地数据,都可以非常容易的调用。换句话说,我们需要将数据的查询和更改操作限制在数据持久层,并只能被业务逻辑层访问。

那么,业务逻辑层 的职责是与数据持久层交互,对多个数据源的操作进行聚合,并且提供组合复用的能力。此外,它也是业务通用能力的处理层,其中还包括缓存方案、消息监听(MQ)、定时任务等等。此外,我们要将尽可能多的业务处理放在业务逻辑层,包括了参数校验、数据转换、异常处理等,而不是在 Controller 再去处理。

笔者认为:请求处理层具有三块能力,一个是通过模板引擎渲染,例如 FreeMarket、Velocity 的页面渲染,以及通过 Controller 层封装的 RESTful API 的 HTTP 接口。如果项目中用到了 Dubbo、HSF、Thrift 等 RPC 服务,我们还需要提供对于的服务给上游的业务方使用,它通过 Service 来实现并暴露成 RPC 接口。这里,Service 的命名是相对的,一般通过 Client 提供接口,通过 Service 实现具体的业务逻辑。

我们了解了逻辑结构,那么,笔者认为比较清晰的物理代码结构应该是这样的。

那么,我们可以跨层级调用吗?笔者认为:我们需要禁止跨层级调用,因为每个层级都自己的职责,并且对上层而言是透明的,就像 OSI 七层协议模型和 TCP/IP 四层协议模型一样,只有将职责限制在自己的边界内,整体层次结构才清晰明了。那么对于同级调用,笔者认为在业务逻辑层是允许的,但是,要特别注意循环调用的产生。

现在,我们再横向理解几个领域模型:VO、BO、DO、DTO。这个概念,是由阿里编码规约提到的,由于其业务非常复杂,因此为了更好地进行领域建模和模型隔离,提出了这几个概念。其中,DO(Data Object)与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。 而 DTO(Data Transfer Object)是远程调用对象,它是 RPC 服务提供的领域模型。注意的是,对于 DTO 一定要保证其序列化,实现 Serializable 接口,并显示提供 serialVersionUID,否则在反序列化时,如果 serialVersionUID 被修改,那么反序列化会失败。事实上,DO 和 DTO 唯一的区别在于,一个是本地数据源的领域模型,一个是远程服务的序列化领域模型。对于 BO(Business Object),它是业务逻辑层封装业务逻辑的对象,一般情况下,它是聚合了多个数据源的复合对象。那么,VO(View Object) 通常是请求处理层传输的对象,它通过 Spring 框架的转换后,往往是一个 JSON 对象。例如,你需要解决 Long 类型的数据精度丢失的问题(如果直接传给 Web 端的话,在 Long 长度大于 17 位时会出现精度丢失),你就可以在 Controller 层通过 @ResponseBody 将返回数据自动转换成 JSON 时,统一封装成字符串。

总结一下,分层思想,将系统横向切割,根据业务职责划分。划分的目的是规划软件系统的逻辑结构便于开发维护。但是,随着微服务的演变和不同研发的编码习惯,往往导致了代码分层不彻底导致引入了“坏味道”。笔者试图提出一个新的代码分层思路来规避和规范这种分层结构。

更多关于Java的Kafka、Mysql、Tomcat、Docker、Spring、MyBatis、Nginx、Netty、Dubbo、Redis、Netty、Spring cloud、分布式、高并发、性能调优、微服务等架构技术大家可以关注我的知乎专栏:Java架构筑基

Java架构筑基​zhuanlan.zhihu.com

专栏免费分享针对以上架构技术的学习资料和视频

service 层 拼接的html 代码如何直接返回_代码分层的设计之道相关推荐

  1. service层拼接XML

    service层拼接XML 1.xml文件样式 <?xml version="1.0" encoding="UTF-8"?> <rows> ...

  2. mvc三层架构_Java架构-代码分层的设计之道

    分层思想,是应用系统最常见的一种架构模式,我们会将系统横向切割,根据业务职责划分.MVC 三层架构就是非常典型架构模式,划分的目的是规划软件系统的逻辑结构便于开发维护.MVC:英文即 Model-Vi ...

  3. service 层 拼接的html 代码如何直接返回_字符串拼接,会走StringBuilder 吗?

    前言 最近在突然想到了String字符串拼接问题,于是做了一个demo测试了一下,到底String类型的字符串在拼接的时候,哪种情况下会走会走StringBulider进行字符串拼接,而哪种情况编译器 ...

  4. service 层 拼接的html 代码如何直接返回_软件系统的分层,有效降低层与层之间的依赖...

    在分解复杂的软件系统时,架构师和程序员用得最多的技术之一就是分层.个人学习开发的时候,软件系统大多数是三层架构,也就是大家非常熟悉的表现层.领域层(业务层).数据源层.随着互联网的发展,智能手机普及手 ...

  5. nginx发布PHP代码,nginx服务器配置返回php代码

    我有一个nginx服务器,所有似乎工作finde但是当我为目录添加auth时,服务器返回php代码作为下载. server { listen 80 default_server; listen [:: ...

  6. js倒计时代码最简单的_代码设计开发-6大基本原则解读(最简单扼要的理解)

    前言 相信做过编程开发的都应该听说过设计模式,设计模式是历史上的编程大牛经过不断的探索,总结出来的一整套经验的总和.他们总结出来这23种设计模式,告诉我们编程按照这些编程的设计模式可以让我们代码的可重 ...

  7. c# mysql代码中写事务_代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性...

    [c#]代码库代码中使用事务前提:务必保证一个功能(或用例)在同一个打开的数据连接上,放到同一个事务里面操作. 首先是在D层添加一个类为了保存当前操作的这一个连接放到一个事务中执行,并事务执行打开同一 ...

  8. 怎么用代码自动点击_代码详解:用Mask R-CNN赋予自动驾驶汽车“火眼金睛”

    全文共 6625字,预计学习时长 13分钟或更长 划重点!!!本文主要内容: · Mask R-CNN是一种先进的算法框架,用于解决图像分割问题 · 本文将采用逐步推进.层层推进的方式来剖析Mask ...

  9. 我开发的代码,如何申请版权_代码简介:我花了3个月时间申请开发人员职位。 这是我学到的。...

    我开发的代码,如何申请版权 Here are three stories we published this week that are worth your time: 这是我们本周发布的三个值得您 ...

最新文章

  1. 【Raspberry pi】系统安装及基础配置
  2. Java范例集锦(一)
  3. 【语言处理与Python】1.4回到Python:决策与控制
  4. 在命令行中的vim编辑器加上行号
  5. 精通Android开发 1
  6. codeforces1494 D. Dogeforces(构造)
  7. MySQL 数据库导出导入操作
  8. os.path.join拼接错误
  9. 【动态规划笔记】区间dp:括号匹配(删除字符和括号匹配)
  10. 如何成为一名合格的CRUD工程师?
  11. 创业公司如何构建数据指标体系?
  12. mysql数据库表格导出为excel表格
  13. java项目开发教材_《Java Web开发实战》——Java工程师必备干货教材
  14. 系统辨识工具箱使用指南
  15. 禅与维修摩托车的艺术_罗伯特-M-波西格
  16. 全面了解小微信贷风控
  17. Vulnhub_COFFEE ADDICTS: 1
  18. uniapp 在线升级(热更新)及java后台
  19. win系统的阿里云服务器部署IDEASpringBoot项目保姆级教程
  20. shell脚本中的空格

热门文章

  1. 49个让你成功的人生细节
  2. C# 重写WndProc及发送消息
  3. MFC通过对话框窗口句柄获得对话框对象指针
  4. MFC的Main函数跑哪去了
  5. IOS之AFNetworking,SDWebImage,Kingfisher,Alamofire,FMDB框架的使用
  6. java 根据经纬度计算多边形的面积_强基初中数学amp;学Python——第二十九课 根据海伦秦九韶公式编程计算三角形面积...
  7. 解决vue中路由跳转同一个路径报错
  8. 使用UEFI Shell引导U盘启动
  9. mysql不被其他ip访问_mysql数据库无法被其他ip访问的解决方法
  10. python循环五要素_python常见单词在手,编程入门不愁