软件模块化开发

一、什么是软件模块化

软件模块化是指将软件划分成独立命名且可独立访问的模块,不同的模块通常具有不同的功能或职责。每个模块都具有可以独立地开发、测试,最后组装成完整的软件。模块独立性是指软件系统中每个模块只涉及软件要求的具体的一个子功能。每个子模块的设计之间的接口尽量简单。这也是模块设计的一个重要原则,来衡量模块之间的好坏是用模块间的耦合和模块内的内聚。
  
模块的藕合度(Coupling)是一个软件结构内不同模块之间联系程度的度量.软件设计应追求尽可能松散隅合的系统.模块间联系简单.则一处发生的错误传播到他处的可能性就小。所以模块间的锅合度对系统的可理解性、可测试性、可靠性和可维护性影响极大.

不同藕合方式的耦合度从弱到强如下排列:无直接耦合、数据耦合、标记耦合、控制耦合、外部耦合、公共耦合、内容耦合。
  (1)无直接耦合:模块间无任何直接联系。
  
  (2)数据耦合:两个模块之间通过参数交换信息,而且交换的信息仅是数据.
  
  (3)标记耦合:是数据藕合的变种.通过模块接口传递的是数据结构的某一部分,而不是简单的参数.
  
  以上三种属弱耦合.
  (4)控制耦合:一个模块明显地控制了另一模块的执行顺序.如一个模块将控制执行顺序的开关值或控制变量送入另一模块,以此影响另一模块的执行.对控制耦合,发送控制信息的模块必须对接收控制信息的模块有十分具体的了解一旦接收模块有改动,势必影响到这种控制关系。另一方面控制模块的修改也会影响到接收模块.
  
  (5)外部耦合:模块间通过指定的外部设备而发生联系。如I/O把一模块与指定设备、格式连接起来.
  外部藕合必然会有,但必须加以限制.使软件结构中这类模块的数量尽可能少.
  
  (6)公共耦合:模块之间通过公共数据环境相互作用。如多个模块引用同一个全局数据时就出现这类强藕合.又如FORTRAN中的Common语句,多个模块访问同一个磁盘文件等.有公共摇合时诊断既费时又困难.因为这次出现的故障可能是以前另一模块访间公共数据环境出错而引起的.
  外部藕合和公共耦合都是强耦合,应限制使用。
  
  (7)内容耦合这是最强的一类耦合.以下四种情况都属内容耦合。
  ①一个模块访问另一模块的内部数据(修改程序段或数据).这是早期开发常用的方式。  
  ②一个模块不通过正常入口转入另一模块内部. 
  ③两个模块共享一段代码(汇编语言程序中常用的方式)。
  ④一个模块有多个入口.
内容藕合极其有害,应坚决不用.事实是,大多数高级语言已不允许这类藕合.由此可得如下的藕合原则:
尽量使用数据耦合,少用控制耦合,限制公共耦合.完全不用内容藕合。

模块的内聚性主要有以下几种:
  1:偶然内聚。是指一个模块内的几个处理元素之间没有任何关联。

2:逻辑内聚。是指模块内的执行几个逻辑上相似的功能。通过参数确定该模块完成哪一个功能。

3:时间内聚。把需要同时执行的动作组合在一起形成一个模块。

4:通信内聚。指模块内所有处理元素都在同一个数据结构上操作,或者指各处理使用相同的输入数据或者产生相同的输出数据。

5:顺序内聚。指一个模块内各个处理元素都密切相关于同一功能并且必须顺序执行,前一个功能元素的输出就是下一个功能元素的输入。

6:功能内聚。是最强的内聚,指模块所有元素共同完成一个功能,缺一不可。

二、软件模块化目的

软件模块化的目的是建立可重用的软件组件,在不需要修改或仅作少量修改的情况下,可再次用来组建新的软件系统,提高软件的开发周期和可靠性。由于软件模块有在不同的系统中使用的需求,决定了软件模块的设计和专用于单一系统的软件代码存在差别,这具体体现在以下方面:

1. 软件模块需要更好的弹性,增加适用范围;

2. 软件模块需要有更好的可移植性,增加适用范围;

3. 软件模块需要更清晰地定义接口,避免模糊含混;

4. 软件模块需要有更好的稳定性,避免错误影响范围扩散;

5. 软件模块需要有更好的独立性,避免引用牵连模块,形成依赖链。

三、解决思路

3.1如何提供更好的设计弹性

长期的软件实践表明,良好的弹性来自于抽象。引入更多的更高层次的抽象会增加软件的弹性。而一个抽象的层次高低来自于设计者对问题域的本质认识的深刻程度,所以要设计更有弹性的模块,首先需要提高自己对模块所解决的问题的认识。额外的抽象层次基本上都会带来性能损失,所以设计上应该考虑到性能和弹性的平衡,但在性能问题没有确证之前,弹性优先。弹性带来的另一个问题是复杂性,过于复杂的软件会带来理解和维护上的困难,所以过度的弹性设计也是不可取的。

改进模块弹性的一般的手段有:

1. 采用接口提供服务而非具体实例。通过不同的方案实现接口,可提供弹性,而对客户不产生影响;

2. 采用单一职责的简单模块而非复杂庞大的。实践证明细粒度的软件单元有更好的适用范围,不同职责的服务应该使用分离(物理的或逻辑上)的接口,不要在一个模块中提供2个以上的服务;

3. 提供可扩展机制,允许客户自行添加新的功能来强化模块;

4. 提供配置选项,允许客户定制模块的部分行为。

3.2如何提供更好的可移植性

可移植性是指让软件在不同平台上运行的难易程度,不需要任何修改就可以运行的就称为跨平台的。实际上真正跨平台的软件是不存在的,任何跨平台的软件必须有一个抽象的底层来支撑,这个支撑的部分是需要在不同的平台上重新实现的,也就是软件的需移植部分。认识到这一点,就可以看到,增加一个软件模块的可移植性,需要做两件事:分离不需要移植和需要移植的部分、减小需要移植部分的复杂度以方便移植。

要确定一个软件模块是否是可移植的,首先需要确定这个模块的目标平台。必须仔细分析所有目标平台的异同,才能够确定哪些是可以在所有平台上都支持的,这些就是不需要移植(可移植)的部分,而并非所有平台都支持(只要有一个不支持)的部分则是需要移植的。选择技术方案时,优先选择可移植方案。对模块中无可移植方案的部分,采用接口抽象出一个可移植层,在不同的平台上分别实现此接口,此接口的实现就是整个模块的需要移植部分,在做移植工作时,只要将关注点放在这里即可。

通常,采用C语言开发的软件,标准C库是很好的可移植库;采用C++开发的软件,选择STL也会获得很好的可移植性;对于网络编程,socket api 也是受绝大多数系统平台支持的,有很好的可移植性。不同的编译器之间也会存在差异,编码时采用标准C/C++语法,避免使用特定编译器的扩展语法,也会改进可移植性。采用一些跨平台第三方库一般也能带来较好的可移植性,但在采用之前需要考虑是否开放源代码、是否收费等因素。

总之,一个软件模块的可移植性好坏,也是取决于设计者对所有目标编译/运行平台的熟悉程度。增加对各个目标的平台了解,有助于设计出具有更好可移植性的模块。

3.3如何提供更清晰的接口定义

当一个模块不考虑可重用时,有时可能不会对接口考虑得非常仔细,接口说明可能就以口头约定或项目内部约定为准。这在单一项目内部一般不会造成很大问题,但一旦模块需要重用到其他项目,这种不太严谨的方法就会带来诸如语义含混、理解困难、功能定义不明确等问题。因此可重用模块的接口的定义需要比内部使用的模块更严格,一般需要考虑以下方面:

1. 该模块提供的具体服务的详细描述,清晰地阐明该模块提供了哪些服务,以及如何提供;

2. 每一个接口函数(操作)的语义说明,包括所有的参数的含义、传递方向、有效范围、异常处理、前提/后置条件等;

3. 在多任务环境下的并发访问安全性的说明,这对多任务开发非常重要;

4. 模块本身的适用范围需要详细描述,清晰界定模块可以工作的环境;

5. 提供完整的示例代码演示正确的使用方法,很多时候demo是最好的文档。

3.4如何提供更好的稳定性

稳定性体可细分了功能上的稳定性和设计上的稳定性。功能上的稳定性表现为模块多次运行不会出现错误;设计上的稳定性表现为多次复用不会需要修改。

功能上的稳定性可以通过单元测试等手段来达到。根据接口设计足够多的测试用例,可以在很大程度上保证功能。同时,注重编程规范、严格检查各种前提/后置条件、编写更多的保护性代码、采用更好的错误处理机制,这些手段都有利于提升模块的功能稳定。

四、模块化编程原则

  1. 单一职责原则:
    类的职能要单一:遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。

  2. 里氏替换原则:
    子类对象可以替换父类对象。子类不要增加父类没有的约束。这样会导致父类有些方法不能用。从而不能真正的实现 : 子类对象可以替换父类对象,如果子类重写了父类已实现的方法,那么子类调用的父类的方法就完全没用了,从而不是真正意义上的继承。

  3. 依赖倒置原则:
    高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

4.接口隔离原则:
在设计接口的时候,给每一个接口设计不多不少的方法,因为,如果设计的方法多了,当某个类通过接口来依赖某个类的时候,被依赖的那个类要实现的方法太多了,会造成那个类中大量的代码冗余,不可过少的原因是,接口太多,会让设计变复杂,且不便于管理。

5.迪米特原则:
低耦合,高内聚,即类A与类B,如果没必要依赖吗,则代码尽量不要耦合,如果这两个类要产生通信,则创建一个中间的通信类C去与这两个类进行交互。但是这样的通信类要适量。

6.开闭原则:
对实现封闭,对扩展开放。即当一个一个方法需要增加其他的功能,或者代码需要重构的时候,要扩展软件的行为,尽量不要去修改已有的代码。用抽象构建框架,方法的实现来扩展细节。

参考资料:代码中的软件工程 https://gitee.com/mengning997/se

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值