我的架构经验系列文章 - 后端架构 - 设计层面
设计层面:
- 分层架构
分层架构是项目设计中很重要的一点,从根本的目的上来说就是为了职责的分离。最经典的三层架构,到四层五层六层,甚至有人开玩笑说十八层的分层,根据项目的需要可以分不同的层。这里说的层其实是逻辑层,从物理层的角度来说也有三层、四层五层的分层架构。之所以三层架构这么流行是因为它的分层把大的关注点进行了分离,层数恰到好处,表现层、业务逻辑层和数据访问层,分别处理面向用户呈现的、面向逻辑处理的和面向数据库存取数据的三大关注点。资源分享
- 在分层架构中除了分层之外还需要对每一层都提取出自己需要的模型,比如表现层的视图模型、业务逻辑层的业务模型或领域模型以及数据访问层的实体,当然如果还有服务层的话还有服务层的契约或数据传输对象。带来的一个问题就是这些实体或模型之间怎么进行转换,当然最简单可靠的办法就是手写代码进行赋值,如果对象中的字段属性超过10个的话就会让人崩溃,因此现在有很多映射Mapper类库可以用来实现各个不同模型之间的转换。
- 分层分的好不好直接影响了系统代码的清晰性和可读性。有的人会问,我使用了三层结构无非就是上层调用下层,改了数据库字段的话还要同时改三层这是多麻烦的事情啊?其实之所以会有这样的疑问是因为:首先,你的项目不够大,或者说逻辑实在是太简单了,导致你的代码中就是上下级的调用。其次,即使你把所有的代码都混在了一起,改了数据库的字段也是需要修改SQL语句的也是需要修改参数校验规则的也是需要修改界面来多呈现这个字段的,其实要改的东西没有少改只不过代码都混在了一起,觉得好像改的地方不多罢了。第三,修改数据库字段这种操作其实对于一个稳定的系统来说不会经常发生,往往我们会改界面会改逻辑,这样的话如果有分层我们只需要修改相应层的代码就可以了,如果每一层是单独分程序集或分jar包编译的话,那么我们甚至只用进行组件的替换。
- 虽然说三层架构很简单,但是要真正落实三层架构的分离理念其实不是这么容易的。举一个例子,同样是对字段判断必须是数字的这个操作,应该在表现层写还是业务逻辑层写还是数据库层写?我们要明确,每一层都只是做自己层职责上的事情,不应该去越权,并且要做的事情一定要做好。首先这个判断每一层都要进行,表现层脚本和代码验证,履行好表现层的职责,业务逻辑层也不能因为表现层验证了就不验证,业务逻辑层不关心表现层做了什么,参数不符合类型就提出了,同样数据访问层对于数字类型的参数就要确保是数字类型的确保在为参数设置了正确的类型。心理很清楚每一个层需要负责的事情,也要很清楚每一层只关心自己的事情,这样就能把正确的代码写在正确的位置了。资源示例
- 高内聚低耦合
高内聚低耦合是一个很重要的设计理念,其实这个理念大家都知道但是怎么样能让这个理念在代码中落实?我觉得可以抓住下面几个原则,这几个原则始终记在脑子里面即可:
- 任何一个方法都检查一遍是不是只做了一件事情。如果一段代码又在做界面展现,又有SQL语句,或是又在处理员工的工资又在处理员工的考勤,那么往往表示这段代码做了过多不是自己的事情了。它或许应该分成两个方法,甚至是不同类型的两个方法。
- 任何一个类型都检查是不是只做了一件事情。这是非常重要的一个检查,如果一个类型做了太多的事情,很明显你没有对类型的职责进行一个明确的划分(当然这个类型就是来负责协调的作为门面类型例外),请检查类中的所有功能是不是符合类名,如果一个类型叫做NetworkingAdapter而其中有处理XML的代码的话显然不合适,是否应该使用其它继承的类型来处理XML,或者是使用类似于策略模式来处理不同的数据?
- 任何一段代码都检查是不是只在一个地方出现。这也是非常重要的一个检查,往往我们可以用这一条金标准来做重构。如果一段代码在多处出现要么这是一段和业务无关的代码,可以AOP解决,要么就有大问题了,一段相同的业务逻辑在多个地方出现,一旦业务逻辑有改有多少人知道要改两个甚至更多的地方,很明显应该把代码提取出来封装在一个地方。
- 任何一个类型都检查是不是依赖过多的类型。除非是门面类型否则一个类型应该不会依赖过多的类型,暂且不说类型的依赖可以通过IOC来解决,如果一个类型依赖了过多的类型,它就会和其它类型进行比较多的强耦合。可以考虑使用门面模式来梳理类型之间的关系,尽量减少和太多的类型之间发生关联。
- 如果一个类型都检查是不是依赖的类型也同样依赖自己。如果产生这种双向依赖的话,建议使用中间人来处理两个类型之间的依赖,不要让两个类型相互调用相互依赖。在有的时候我们可以考虑类型A把数据写到一个地方,类型B从这个中间点去获取数据然后进行处理处理后还是把结果存在这个中间点,类型A再从这个中间点获取结果。这样的话A和B其实没有很强的依赖,大家都依赖中间点获取结果,即使把B替换成C只要它最终输出的东西是大同小异的那么A就不需要修改。资源分享
- 设计模式
所有的设计模式其实都是前人在大量的编程实践后总结出来的,每一个模式都有适用的地方,每一个模式都是解决一个问题的,因此针对设计模式我的建议如下:
- 应该对每一个设计模式都了解,然后你自然可以想到在合适的时候使用合适的模式。
- 不要去滥用设计模式,好的设计模式可以增强代码的高内聚低耦合也可以让代码对扩展友好,但设计模式滥用可能会导致代码的性能问题以及不必要的编码。
- 作为开发gof的设计模式应该熟读,只是读还不够,自己想办法去在今后的编码过程中体会应用设计模式,如果一个设计模式没用那么他就在书上,如果用了那么他就在你脑子里。
- 面向对象
面向对象的三大要素许多人也是熟读在心了,但是个人认为要彻底明白面向对象三大要素是需要大量OO实践积累的。对于过程式的开发其实是结果导向的,这比较容易理解。但OO开发其实是维护导向的,通过OOD后开发出来的代码是比较容易进行扩展的,也是可以支撑复杂业务的。对一套好的OO代码进行扩展可能门槛会比较高,因为每一个对象都有自己的职责,需要理清楚对象之间的关系,一旦入手了就会发现非常爽的感觉。可以大量利用系统内已经实现的类型,如果继承和重写实现自己的需求,然后还可以通过实现接口把自己的实现插到原有的OO体系中去,也就是可能只需要几行代码就可以对系统进行改造。对于没有OO的代码改造上手不一定很困难,因为代码很直白,但是一旦进行几十次改造之后代码就没有可维护行了,因为所有的代码都交织在一起,而且会有大量的硬编码(面向结果的代码特点就是可能从上到下很多地方都可以改,而且可以实现相同的效果,一旦这么做了可能就会导致原来的逻辑被破坏,代码可维护性降低)。对于OO的学习我的体会是:
- 可以从设计模式入手,设计模式是OO的一个总结,学习了设计模式有助于理解OO的三大理念。资源示例
- 可以多阅读优秀的框架或类库的代码,优秀的开源框架一定是对扩展友好的,因此它的设计往往是非常OO的,通过阅读改造开源代码可以提升OOD的能力。
- 多重构多思考,根据上面提到的高内聚低耦合中说的那些问题想办法去重构代码,你会发现很多优化只能通过OO的手段进行,思考重构然后再重构来进步。