你 好,我是梁松华,今天想和你聊的话题是可复用架构之分离关注点。
可复用架构的本质就是分和合。先打散再组合起来,只对外暴露各个场景下业务逻辑的调用入口。就好比,一个模型中有多个对象,这些对象只有整体出现才有意义,我们不能只暴露对各个对象进行操作的方法,那样缺乏封装性,无法保证稳定性,没有稳定性就谈不上可复用了。
刚刚说的分有多种含义,包括服务的拆分,也包括单个服务各种模块的分层设计,它们划分的目的都是一样的,让自已专注解决某个层次的问题,职责单一。
而组合通常就是为了隐藏内部细节,只暴露入口,使用者传进来的参数只能先通过这个大门的检查才能触发功能逻辑,或者直接使用系统提供的默认参数,选择开箱即用。
说到这里,是时候给分离关注点下一个定义了。我们实现需求时,需要关注功能性需求,比如业务逻辑、数据持久化,还要关注非功能性需求,比如性能、监控、安全、日记,还要关注软件设计是否能灵活更换依赖的类等等。可以看到系统是一系列关注点的组合,这些关注点如果横跨系统多个模块的话,每个模块设计时都要考虑一大堆的关注点细节,关注细节太多,主干逻辑就有可能考虑欠佳,导致留下不易发现的问题。也就是说,如果不把关注点分离,系统将变得很难设计、理解和扩展。这样对分离关注点介绍还是过于抽象,接下来我以实际项目为例介绍下如何实践,加深你对它的理解。
我当时学习编程时是从MVC三层架构入门的,控制器Controller层负责参数校验、路由转发和封装返回结果,模型Model层负责对数据进行加工和存储,视图View层负责渲染页面。
不过随着前后端开发的分离,我们不再使用这个三层架构,而是使用RPC架构,通常分为Client、Dao、Common、Domain、Rpc、Service、Web层,Client层负责对外提供SDK包,Dao层负责对数据进行持久化,Common层负责通用工具的封装,Domain层负责对业务概念模型管理,Rpc层负责对上游依赖服务进行封装,Service层负责业务逻辑的组合,Web层负责实现对外接口的方法,类似MVC三层架构中的控制Controller层,这样就把业务控制和业务实现由不同层的模块来处理,实现了关注点的分离。
但是呢,将功能分层还不够,还需要对模型对象进行分离,不然还是会出现耦合。比如对外服务的参数叫DTO,服务层和Dao层的参数叫DO,控制层负责DTO和DO之间的转换,因为DO的字段个数肯定是比DTO多的,它需要记录一些中间计算出来的结果,这些中间值是不能由使用者传递进来,使用者也无需关心这些中间值,否则就等同于把自己的命根子交给给别人管理了。可以看到,我们对模型对象的划分,就把过程值和结果值的关注进行分离。
前面从软件设计分层的角度说明了关注分离点是如何实践的,这个示例我相信大家都有所认识,其实还有一个普通存在的示例,就是使用切面AOP编程实现鉴权控制。它将基本每个模块都要做的事情,而且是稳定不发生变化的逻辑,单独抽了出来,方便我们在业务逻辑前和业务逻辑后做一些通用逻辑,这样就把稳定不变的非功能性逻辑和容易发生改变的功能性逻辑进行了分离。
说了这么多的分离关注点的实践,那这种编程方式有什么看得见摸得着的好处呢?不难发现,分离关注点之后系统复杂度变低了,新人可以先熟悉主干流程,有时间再对模块细节展开了解,另外分离关注点后我们更加方便进行单元测试和覆盖测试,因为它们的变化都是隔离的,修改代码和重构时不会牵一发而动全身。
到这里,本文就要结束了,我带你总结一下今天的主要内容吧。我从可复用架构的本质引出了分离关注点这个概念,接着通过软件架构分层设计、面向切面编程这两个实践案例进行了说明,最后也给出了一些分离关注点的好处。
好,我是梁松华,希望今天的分享能帮助到你。
原文 http://mp.weixin.qq.com/s?__biz=MzU4ODkwMDI1OA==&mid=2247484097&idx=1&sn=caf277a3d40fccfbfaa1f7cef7e160c9