精华内容
下载资源
问答
  • 代码分层了解下.zip

    2019-09-28 15:12:22
    无意中看到关于代码分层的代码,想了解下,可以download下。
  • 代码分层的设计之道

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

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

    MVC分层结构.png | left | 240x433

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

    MVC三层模型.png | left | 428x314

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

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

    代码分层 (1).jpg | left | 827x699

            其中,数据持久层 承载了数据存储和访问的能力,它既与底层数据进行交换,包括 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 实现具体的业务逻辑。

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

    屏幕快照 2018-10-13 下午5.43.16.png | center | 604x1224

            那么,我们可以跨层级调用吗?笔者认为:我们需要禁止跨层级调用,因为每个层级都自己的职责,并且对上层而言是透明的,就像 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 时,统一封装成字符串。

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

    如果你有不同的想法和兴趣,欢迎加我微信一起探讨与交流哟~

    原文地址:梁桂钊的博客

    博客地址:blog.720ui.com

    欢迎转载,转载请注明作者及出处,谢谢!

    展开全文
  • 如何合理的设计代码分层,论代码分层的设计之道 。 分层思想,是应用系统最常见的一种架构模式,我们会将系统横向切割,根据业务职责划分。 MVC 三层架构就是非常典型架构模式,划分的目的是规划软件系统的逻辑...

    https://mp.weixin.qq.com/s?__biz=MzA5NDg3MjAwMQ==&mid=2457102792&idx=1&sn=ab9c0437873bbcd8e0c4fd04b0b30f9d&chksm=87c8c166b0bf48709949841cd300c6a692eb6269c3ee23ab08a77a22f5c2bd37e71f3b60bc7c&scene=21#wechat_redirect

    首先,感谢「芋道源码」艿艿的邀请(微信公众号:芋道源码),才会有这篇文章的诞生。

     

    话不多说,开始正题。今天我想分享的话题是:如何合理的设计代码分层,论代码分层的设计之道

    分层思想,是应用系统最常见的一种架构模式,我们会将系统横向切割,根据业务职责划分。 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 时,统一封装成字符串。

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

    如果你有不同的想法和兴趣,欢迎加我微信一起探讨与交流哟~

    展开全文
  • javaee开发常见的模式有MVC模式,在C层中常常会再次分层,如:servlet(web层)、service(业务逻辑层)、dao(数据访问层),其中service和dao最容易混在一起,如转钱交易场景,service层需要执行“事务”操作,会...
  • 今天就来讲讲优秀IT人的代码都是如何分层的。 一、背景 说起应用分层,大部分人都会认为这个不是很简单嘛 就controller,service, mapper三层。 看起来简单,很多人其实并没有把他们职责划分开,在很多代码中,...

    代码规范重要吗?很重要很重要,整洁的代码能让你和同事都心旷神怡,也能让你在离职的时候不会被骂.....今天就来讲讲优秀IT人的代码都是如何分层的。

    一、背景

    说起应用分层,大部分人都会认为这个不是很简单嘛 就controller,service, mapper三层。

    看起来简单,很多人其实并没有把他们职责划分开,在很多代码中,controller做的逻辑比service还多,service往往当成透传了,这其实是很多人开发代码都没有注意到的地方,反正功能也能用,至于放哪无所谓呗。这样往往造成后面代码无法复用,层级关系混乱,对后续代码的维护非常麻烦。

    的确在这些人眼中分层只是一个形式,前辈们的代码这么写的,其他项目代码这么写的,那么我也这么跟着写。

    但是在真正的团队开发中每个人的习惯都不同,写出来的代码必然带着自己的标签,有的人习惯controller写大量的业务逻辑,有的人习惯在service中之间调用远程服务,这样就导致了每个人的开发代码风格完全不同。

    后续其他人修改的时候,一看,我靠这个人写的代码和我平常的习惯完全不同,修改的时候到底是按着自己以前的习惯改,还是跟着前辈们走,这又是个艰难的选择,选择一旦有偏差,你后来的同事又维护你的代码的时候,恐怕就要怼人了。

    所以一个好的应用分层需要具备以下几点:

    • 方便后续代码进行维护扩展;
    • 分层的效果需要让整个团队都接受;
    • 各个层职责边界清晰

    二、如何进行分层

    2.1、阿里规范

    在阿里的编码规范中约束的分层如下:

    看完阿里的代码规范,立马学会代码分层,再也不会被同事怼

     

    开放接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行 网关安全控制、流量控制等。

    终端显示层:各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染,JS 渲染, JSP 渲染,移动端展示等。

    Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。

    Service 层:相对具体的业务逻辑服务层。

    Manager 层:通用业务处理层,它有如下特征:

    1. 对第三方平台封装的层,预处理返回结果及转化异常信息;
    2. 对Service层通用能力的下沉,如缓存方案、中间件通用处理;
    3. 与DAO层交互,对多个DAO的组合复用。

    DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase 进行数据交互。

    阿里巴巴规约中的分层比较清晰简单明了,但是描述得还是过于简单了,以及service层和manager层有很多同学还是有点分不清楚之间的关系,就导致了很多项目中根本没有Manager层的存在。下面介绍一下具体业务中应该如何实现分层。

    2.2、优化分层

    从我们的业务开发中总结了一个较为的理想模型,这里要先说明一下由于我们的rpc框架选用的是thrift可能会比其他的一些rpc框架例如dubbo会多出一层,作用和controller层类似:

    看完阿里的代码规范,立马学会代码分层,再也不会被同事怼

     

    最上层controller和TService是阿里分层规范里面的第一层:轻业务逻辑,参数校验,异常兜底。通常这种接口可以轻易更换接口类型,所以业务逻辑必须要轻,甚至不做具体逻辑。

    Service:业务层,复用性较低,这里推荐每一个controller方法都得对应一个service,不要把业务编排放在controller中去做,为什么呢?如果我们把业务编排放在controller层去做的话,如果以后我们要接入thrift,我们这里又需要把业务编排在做一次,这样会导致我们每接入一个入口层这个代码都得重新复制一份如下图所示:

    看完阿里的代码规范,立马学会代码分层,再也不会被同事怼

     

    这样大量的重复工作必定会导致我们开发效率下降,所以我们需要把业务编排逻辑都得放进service中去做:

    看完阿里的代码规范,立马学会代码分层,再也不会被同事怼

     

    Mannager:可复用逻辑层。这里的Mannager可以是单个服务的,比如我们的cache,mq等等,当然也可以是复合的,当你需要调用多个Mannager的时候,这个可以合为一个Mannager,比如逻辑上的连表查询等。如果是httpMannager或rpcMannager需要在这一层做一些数据转换

    DAO:数据库访问层。主要负责“操作数据库的某张表,映射到某个java对象”,dao应该只允许自己的Service访问,其他Service要访问我的数据必须通过对应的Service。

    三、分层领域模型的转换

    在阿里巴巴编码规约中列举了下面几个领域模型规约:

    • DO(Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。
    • DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。
    • BO(Business Object):业务对象。由Service层输出的封装业务逻辑的对象。
    • AO(Application Object):应用对象。在Web层与Service层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
    • VO(View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。
    • Query:数据查询对象,各层接收上层的查询请求。注意超过2个参数的查询封装,禁止使用Map类来传输。

    看完阿里的代码规范,立马学会代码分层,再也不会被同事怼

     

    每一个层基本都自己对应的领域模型,这样就导致了有些人过于追求每一层都是用自己的领域模型,这样就导致了一个对象可能会出现3次甚至4次转换在一次请求中,当返回的时候同样也会出现3-4次转换,这样有可能一次完整的请求-返回会出现很多次对象转换。如果在开发中真的按照这么来,恐怕就别写其他的了,一天就光写这个重复无用的逻辑算了吧。

    所以我们得采取一个折中的方案:

    1、允许Service/Manager可以操作数据领域模型,对于这个层级来说,本来自己做的工作也是做的是业务逻辑处理和数据组装。

    2、Controller/TService层的领域模型不允许传入DAO层,这样就不符合职责划分了。

    3、同理,不允许DAO层的数据传入到Controller/TService。

    看完阿里的代码规范,立马学会代码分层,再也不会被同事怼

     

    四、总结

    总的来说业务分层对于代码规范是比较重要,决定着以后的代码是否可复用,是否职责清晰,边界清晰。

    当然这种分层其实见仁见智, 团队中的所有人的分层习惯也不同,所以很难权衡出一个标准的准则,总的来说只要满足职责逻辑清晰,后续维护容易,就是好的分层。

    最后,如果你的团队有更好的分层,或者上面所描述的有什么错误的地方还请评论指正一下。

    展开全文
  • Laravel应用代码分层

    2020-12-07 18:14:15
    应用代码分层 我们在写应用里的代码时根据代码负责的不同任务讲其分为五大块Controller, Repository, Service, Model, View。 Model 数据模型, 数据模型面向的是数据层,在这里我们只关心数据表的问题,在 Model ...

    应用代码分层

    我们在写应用里的代码时根据代码负责的不同任务讲其分为五大块Controller, Repository, Service, Model, View

    • Model 数据模型, 数据模型面向的是数据层,在这里我们只关心数据表的问题,在 Model 中应该只定义数据与对象映射相关的属性和方法如:表名、主键名、是否让 laravel 管理时间字段等属性,以及模型关联、查询作用域等方法。其他与数据表无关的业务逻辑都不应出现在这里。
    • Repository 数据逻辑访问层,由它来对接 Model 层,理论上有一个 Model 就会有一个相应的Repository,除了做最基础的数据访问外与数据相关的逻辑也放在这里,如果一个相对复杂的数据应用到了Repository对应的Model外其他Model的数据,不要直接去访问相关Model,应该由Repository调用相关ModelRepositoryRepository是具体interface的实现,比如做订单相关的业务,应该有OrderRepositoryInterface定义Order数据交互流程中必须要实现的方法然后由OrderRepository去具体实现,之后将OrderRepositoryInterfaceOrderRepository注册到服务容器中,解析时直接使用OrderRepositoryInterface解析出具体实现,这样消费层既不需要关心数据来自哪里是Mysql还是MongoDB,也给项目提供了足够的灵活性。当数据来源从Mysql更改为MongoDB后,我们只需要重新写一个实现类OrderMongoRepository然后将服务容器里OrderRepositoryInterface的实现切换成OrderMongoRepository就好,消费层完全不需要改动。
      (Repository 是我之前一直觉得在程序设计中特别多余而现在觉得特别重要的一个 Layer,之前在 Service 中揉进去了 Repository 的职能,后续会把相关的 Example 也做一下修改)
    • Service 项目中除了数据的 CRUD 还会有图片上传、请求外部 API 获取数据、发送邮件等等其他这些功能,这些功能应该定义在Service层。
    • Controller 控制器,面向的对象是一个完整的页面或者是接口,其主要职责是作为接收请求和发送响应的中控程序,通过调度项目中的 Service、 Repository 等来完成请求、组合响应数据,并通过页面响应或者接口数据的形式将响应返回给客户端。
    • View 视图, 负责渲染 HTML 响应,使用 Laravel 自带的 blade 模版引擎,并且应该尽量减少 PHP 代码。

    总结:所以如果一个请求对应的业务逻辑相当复杂,我们可以通过 Controller 方法调用多个 Service 方法(单一逻辑)来完成这个复杂的逻辑,在 Service 方法中我们通过多个 Model 操作来实现更新、获取数据。通过这种原则来对复杂逻辑进行解耦。

    我们通过看两个例子来更好的理解代码如何分层:

    代码示例

    Example 1: 应该在哪里写 SQL 操作

    如果一个查询在项目中只会用到一次,那么我们直接在 Controller 方法里写这个查询就很好, 举例来说你想查出所有的管理员用户:

    $admins = User::where('type', 'admin')->get();
    

    现在假设你需要在不止一个 Controller 方法中用到这个查询, 你可以在UserRepository类里包装对User模型的访问:

    class UserRepository
    {
        public function getAlladmins()
        {
            return User::where('type', 'admin')->get();
        }
    }
    

    现在你可以在用到UserRepositoryController中通过依赖注入UserRepository, 然后通过这个 UserRepository 方法获取所有管理员用户:

    //Controller
    public function __construct(UserRepository $UserRepository)
    {
        $this->UserRepository = $UserRepository;
    }
    //Controller action
    public function index()
    {
        $admins = $this->UserRepository->getAllAdmins();
    }
    

    最后,假设你还需要一个查询来计算管理员的数量, 可以在把这个查询封装到 UserService 的一个方法里:

    public function getAdminNum()
    {
        return User::where('type', 'admin')->count();
    }
    

    这样写是 OK 的,但是你可能已经注意到了User::where('type', 'admin')这个片段在getAllAdmins这个查询里也有用到,所以我们可以用查询作用域来改进它(查询作用域也会让你的代码可读性变得更高):

    //UserModel
    public function scopeAdmins($query)
    {
       return $query->where('type', 'admin');
    }
    

    然后在 UserRepository 里我们可以向下面这样重写它的查询:

    //UserRepository
    public function getAllAdmins()
    {
        return User:admins()->get();
    }
    
    public function getAdminNum()
    {
        return User::admins()->count();
    }
    

    就像上面说的那样在 Model 中我们应该撇开业务逻辑,面向数据表进行抽象,只定义表相关的属性、模型关联和查询作用域, 具体怎么应用 Model 中定义的这些内容, 那是 Controller 层和 Service 层要关心的事情。

    Example2: 通过 Service 类提高代码复用率

    我们在做 CMS 系统管理内容时, 通常都会涉及到文章的上下线,置顶等操作。假设在系统中我们会用两个数据表分别存储文章和置顶, 在项目中对应两个 Model: Article 和 TopArticle。

    假设我们需要实现下线文章的功能,如果文章是置顶文章,还要把文章取消置顶,我们在 ArticleService 里包装这个操作:

    public function setArticleOffline(Article $article)
    {
       if ($article->is_top == 1) {//如果是置顶文章需要将文章取消置顶
           $this->cancelTopArticle($article);
       }
       $article->status = Article::STATUS_OFFLINE;
       $article->offline_time = date('Y-m-d H:i:s');
       $article->save();
    
       return true;
    }
    
    /**
     * 取消文章的置顶
     * @param \App\Models\Article $article
     */
    public function cancelTopArticle($article)
    {
        if (TopArticle::specificArticle($article->id)->count()) {
            //删除置顶表里的记录(待上线的置顶文章上线后置顶表中才能有相应的记录)
            TopArticle::specificArticle($article->id)->delete();
        }
        //将文章的is_top字段置为0
        $article->is_top = 0;
        $article->save();
    
        return true;
    }
    

    在 Controller 的 Action 里我们只需要负责验证接收来的参数,查询文章对象传递给 Service 来做下线操作, 这里之所以把取消置顶也单独提取出来是因为通常 CMS 系统里还有单独的文章取消置顶功能。

    //ArticleController
    public function setArticleOff(Request $request, ArticleService $artService)
    {
        ...//表单验证
    
        $article = Article::find($request->get('article_id'));
        $this->articleService->setArticleOffline($article);
    
        ...
    }
    

    除了上面讲到的主动下线文章的功能, 一般的文章系统里还会有定时上下线文章的功能, 因为我们在 ArticleService 里包装了下线文章的功能, 所以在设置定时任务时就可以再次调用 setArticleOffline 方法来完成文章下线的功能:

    //App\Console\Commands\ArticleCommand
    public function __construct(ArticleService $articleService)
    {
       $this->articleService = $articleService;
       parent::__construct();
    }
    
    public function handle()
    {
       $operation = $this->argument('operation');
       switch ($operation) {
           case 'offline':
            $this->setOffline();
            break;
        default:
            break;
    }
    
    public function setOffline()
    {
       ......//前置条件查出要下线的文章
       $this>articleService>setArticleOffline($article);
       ......
    }
    

    上面两个例子简单说明了我们把代码分层后每个层里应该写什么类型的程序,以及代码分层后在可读性、耦合性、维护成本等方面带来的收益。

    展开全文
  • Java架构-代码分层的设计之道

    千次阅读 2018-11-28 14:48:11
    分层思想,是应用系统最常见的一种架构模式,我们会将系统横向切割,根据业务职责划分。MVC 三层架构就是非常典型架构模式,划分的目的是规划软件系统的逻辑结构便于开发维护。MVC:英文即 Model-View-Controller,...
  • DDD代码分层架构

    千次阅读 2020-06-09 15:46:18
    过渡完成后,废弃防腐层代码 通过分层的方式来控制需求的变化从外到里对系统的影响,收到的需求的影响会越来越小,面对用户端可以快速在应用层调整,对服务和聚合进行组合和编排达到快速适配的效果。
  • 不同于其它的架构方法,领域驱动设计DDD(DomainDrivenDesign)提出了从业务设计到代码实现一致性的要求,不再对分析模型和实现模型进行区分。也就是说从代码的结构中我们可以直接理解业务的设计,命名得当的话,非...
  • 浅谈代码分层:构建模块化程序

    千次阅读 2017-03-18 13:21:35
      浅谈代码分层:构建模块化程序 Author: Kevin Lynx Date: 4.4.2011 Contact: kevinlynx at gmail dot com 模块化的程序是怎样的程序?我
  • 在一般的springboot项目中,会包含如下几个分层: datamodel:定义数据模型,包括entity,dto,vo等。 repository:用途是封装数据库的操作,简单的项目中直接使用repository,复杂的项目中会分成repository层和dao...
  • 1、背景 说起应用分层,大部分人都会认为这个不是很简单...的确在这些人眼中分层只是一个形式,前辈们的代码这么写的,其他项目代码这么写的,那么我也这么跟着写。但是在真正的团队开发中每个人的习惯都不同,写出来
  • python selenium po代码分层设计

    千次阅读 2019-10-21 15:48:27
    po设计模式(PageObject):自动化测试脚本的减少代码重复、更易读、减少维护成本 基础层---元素定位层--元素操作层--业务层--编写case--收集case并执行 项目结构如下 基础层:base_p...
  • C语言编程代码架构搭建——代码分层

    万次阅读 多人点赞 2017-10-09 22:52:52
    像Linux一样打印系统运行时间编程代码前遵循结构设计,大体分为三部分,底层驱动,硬件抽象层,系统任务调用层,程序设计按照这部分来进行设计。底层驱动底层驱动是对应相应的MCU而制定的,与MCU的库函数,开发环境...
  • 前面将基础打好了,接下来就是具体的使用了,业务层主要是页面中... 那为什么不直接写在测试类中呢,这样是为了将业务操作与测试用例分离,因为多个用例可能是对应一个业务操作的,这样,我业务代码是不用动的,只需要
  • 当当网的后期版本,是一个不错学习分层思想的实例。 两个实现很相似。
  • 常用的软件架构模型可以... 代码分层、分离,封装 。  页面结构分模块,分而治之。解耦,代码可读性高,底层统一优化。  模块化是个一般概念,这一概念也适用于软件开发,可以让软件按模块单独开发,各模块通常...
  • [Embeded--SW_分层]嵌入式C代码分层

    千次阅读 2015-07-11 00:16:48
    问题描述:嵌入式、单片机中C...对C代码分层设计知识在网络搜索学习了下,并结合自己的点点经验做下记录,方便以后更改和提升。  一、分层模式概述--参考自[1]:     分层(Layer)模式是最常见的一种架构模式。
  • 前言:做UI自动化,不可避免的要和页面上的元素打交道,有的童鞋可能会选择把页面元素的定位,操作都写在测试代码中,当页面元素比较少,测试代码比较少的情况下还好,但是一旦页面元素多起来(实际运用中也不太可能...
  • 代码如何分层

    千次阅读 2019-01-17 09:42:54
    原文参见:代码分层的设计之道 在复习设计模式的知识点,首先复习的是单一职责原则。这个原则本身理解简单,实践却并不容易,需要在编码和架构设计的过程中,不仅对代码本身做的事了解,还需要对业务有总体了解,...
  • 浅谈JavaWeb项目代码如何分层

    万次阅读 多人点赞 2018-07-23 14:04:56
    代码分层,对于任何一个Java Web开发来说应该都不陌生。一个好的层次划分不仅可以能使代码结构更加清楚,还可以使项目分工更加明确,可读性大大提升,更加有利于后期的维护和升级。  从另外一个角度来看,好的代码...
  • 代码结构分层

    2019-09-03 19:28:07
    service层通用能力的下沉,这里的manger层是处于service层和dao层之间的层次,对于service调用的dao层多表操作代码段可以进行封装。其次,对于缓存以及重点间等的通用操作方法也可以进行封装,使的多个servcie层可以...
  • 优秀的代码应该如何分层

    千次阅读 2019-02-27 17:58:57
    说起应用分层,大部分人都会认为这个不是很简单嘛 就controller,service, mapper三层。看起来简单,很多人其实并没有把他们职责划分开,在很多代码中,controller做的逻辑比service还多,service往往当成透传了,这...
  • 代码分层、分模块的好处

    千次阅读 2011-09-28 16:09:55
    没有分层,把逻辑都写在一个方法里面的代码就好比是一本没有目录的电子书,要找哪一章哪一节全得凭感觉,得点进去看,得结合上下文来分析。 良好的代码层次结构则相当于给这电子书创建了目录,而且按住Ctrl+鼠标就...
  • 一个非常好的文档来介绍DDD分层架构参考代码目录结构,接口层,应用层,领域层和基础层等!
  • Java Web应用的代码分层最佳实践。

    千次阅读 2018-05-07 10:02:47
    代码分层,对于任何一个Java Web开发来说应该都不陌生。一个好的层次划分不仅可以能使代码结构更加清楚,还可以使项目分工更加明确,可读性大大提升,更加有利于后期的维护和升级。从另外一个角度来看,好的代码分层...
  • 采用springboot+mybatis,并多层设计,分为web、service、
  • 代码分层,对于任何一个Java开发来说应该都不陌生。一个好的层次划分不仅可以能使代码结构更加清楚,还可以使项目分工更加明确,可读性大大提升,更加有利于后期的维护和升级。 从另外一个角度来看,好的代码分层...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 178,775
精华内容 71,510
关键字:

代码分层