设计心得——分层和划分模块
一、分层
在实际的设计开发过程中,对于稍微大一些的项目,基本都涉及到分层。什么是分层呢?其实非常简单,就是利用某种逻辑或域的范围等把整个项目划分成多个层次。它们之间通过接口(可能是简单的函数接口也可以是服务等)进行通信。分层地目的其实非常明显,就是为了整个设计的解耦和重用,使得整个项目结构更清晰和控制更合理,也便 于后期的维护和扩展。
一般来说,分层是在更高层次上进行抽象,它属于对整个项目的横向切分。分层的优点非常多,比如高内聚、低耦合以及便于维护和接口扩展,提供了更好的技术更新接口等等。但在明白其的优势之后,更要明白它的劣势所在:
1、降低性能
增加层次的最主要的问题就是导致一定的性能损失。毕竟大家都明白,直接调用比通过接口处理一下,理论上一定是要快的。特别是在通信量巨大并且并发较高的情况下,其性能的损失会非常的明显。
2、增加复杂性
分层设计需要进行良好的层间接口设计,否则极有可能导致因为接口的问题导致层间的通信问题,比如对于一个任务是需要调用一个接口完成(单一原则)还是一个以上接口(效率)实现呢?这就需要设计者不断的根据实际情况进行调整。
3、工程化的风险
设计者们往往有一个爱好,一旦觉得某项技术不错,便会不断的在这个基础上进行强化,也就是过度设计。体现在分层上就是更乐意通过分层来解决很多问题。虽然分层在很多情况下可以将问题简化,但过多的引入分层等于变相的增加了另外一种复杂性。也就是说,设计者一定要明白,分层的适度性和科学性。而且过多的分层往往导致测试的复杂性和增加测试的难度。
虽然明白了分层的优势,但说起分层来大家可能有点熟悉又陌生的感觉,其实举一个常见的MVC的例子大家就明白了,它其实就是把整个程序分成了三层,上层的表示层用来处理接收的输入数据和处理后返回的数据;中间的控制层用来进行上下的交互数据管理;而最下面的模型层则进行数据的最终存储逻辑控制。
通过MVC明白了这种分层的设计的具像化,那么其它也就好理解了,比如常见的另外一种分层,网络分层,TCP/IP的分层等等。某些情况下,分层类似于见到的过滤器,一层层的过滤掉不同的物质(或者说一层只处理一个或几个业务)。这样,大家应该就对分层有了一个很显性的认识。
但需要注意的是,软件设计的分层往往从不同的角度看有不同的理解,大家不要教条和僵化,慢慢思考、理解和学习即可。
二、模块化
说了分层,再说设计高频遇到的名词,模块。其实模块这个概念就是一组功能相近的软件代码或组件。这里面水儿深着哪。首先,什么是一组,另外什么是功能相近?什么是代码或组件?这个其实没有强制的定义。给大家举个例子,一个函数就有可能是一个模块,而一个类也可能是一个模块,一个文档可能也是。一个软件可能也是…凡此种种。而模块化就是以模块为基础的设计方式。
模块会根据场景不一致而呈现中不同的情况。而上面所提到的功能相近等其实也可以站不同的角度和层次上来看。再举一个例子,一个大型的变电站运行软件,可能分成服务端软件,客户端软件,移动端软件和设备端软件等等。那么从这个角度来看,它们每个都算是一个独立的模块。一般来说,模块属于是在纵向上的划分,即更强功能的组合。
需要提醒的是,不要混淆模块的一些概念,比如在不少的程序语言中,都有模块这个概念。它们和设计中提到的模块基本类似,但也有着一些显著的不同。切记。
模块化设计的优点很多,和分层差不多,毕竟二者都是朝着同一个目的而来的。
模块化设计的主要优点包括:高内聚,低耦合,接口清晰,易维护,方便代码重用及团队协作。但它的缺点也不少:
1、模块化设计增加了设计的难度
不是每个设计者都能很好的把握模块的设计,这就可能导致模块设计的不合理性,进而导致各种问题。
2、降低效率
和分层一样,通过接口调用的模块,理论上会降低整体的效率
3、工程上的过度设计
一如分层,模块的过度设计,同样会导致整个软件的难于控制,过多的模块往往使得业务的碎片化;而过少的模块除了引入了一些复杂性,几乎没有体现出模块的优势。
4、模块的维护
设计完成的模块,需要从开始到结束都一套完善的管理流程,包括文档、工具等。如果开发者们没有按照设计要求进行,则可能导致引入不少的风险。最简单的例子就是不同的模块间,使用了不同的技术标准实现或者引入不相同功能的不同版本的库。都可能导致问题的出现,而且极有可能很难发现问题的原因。
但正如成语说得好,不能“因噎废食”。设计就是一种取舍和妥协!
三、二者关系
在分析了上述的分层和模块后,不少的新手可能会有一个疑问,怎么看待二者的设计上的抽象的不同呢?一般情况下,分层的抽象是高于模块的抽象的,但具体情况上则有可能有所不同 。比如在上面提到的变电站软件中,每个模块中,可能又会划分成不同的层次。这样看来,模块包含着分层。也就是说,实际应用中,分层和模块间没有明确的界限,二者可以互相包容。
其实,稍微大一些软件的设计,一般来说是分层优先,然后进行模块划分。经常可以看到系统的整体设计架构图,就是这样的。但凡是都有例外,分层和模块二者之间其实是一个互相补充互相协作上的抽象关系。从整体抽象看,分层是较大粒度的划分而模块则是较小粒度的划分。也即上面提到的分层是基于横向的水平划分而模块是基于纵向的垂直划分。
一般的情况下,分好的层次中,每层都包含若干个模块。模块间以接口通信,整合后通过层间的接口再与其它层进行通信。层次之间的数据依赖单向为主,但模块间的依赖则灵活很多。
四、二者的应用
分层和模块化的应用场景在不少的场景下是重叠的,但整体上来看,还是可以进行区别划分的。
1、分层的应用
a) 大规模的应用,特别是企业级的应用。包括框架、库和系统等
b) 分布式应用,为更好的协调分布式各个节点间的通信,分层是一个非常好的设计思路
c) Web应用,这个更容易理解,常见的MVC设计在Web服务中体现的最明显
d) 复杂应用,对业务或逻辑处理深度较大,恰恰是分层设计的良好应用场景
e) 其它一些特殊场景
2、模块化的应用
模块化设计几乎是所有的程序设计都离不开的。除非程序很小或者说一些例程,正常情况下,一个软件都要进行模块化的设计。
五、总结
设计一个从抽象到具体,从整体到细节,不断具体而微的过程。俗话说得好“教的曲儿唱不得”。设计不像技巧,多问两下多看两下代码就会用了。所以设计中的一些具体的手段和方法,要不断的从不同的角度不同的场景进行分析学习,并不断在实践中进行检验。反思得失,总结教训,形成自己的一套解决问题、处理问题的逻辑和流程。最终升华为自己的设计思想。
这一定是一个长期的,不断的否定之否定的过程!愿与诸君共勉!