耦合性是程序结构中各个模块之间相互关联的度量。它取决于各个模块之间接口的复杂程度、调用模块的方式以及哪些信息通过接口。
构成耦合性的七种类型
一般模块之间可能的连接方式有七种,构成耦合性的七种类型。它们之间的关系为(由弱到强)
这种耦合会引起下列问题:
1)所有公共耦合模块都与某一个公共数据环境内部各项的物理安排有关,若修改某个数据的大小,将会影响到所有的模块。
2)无法控制各个模块对公共数据的存取,严重影响软件模块的可靠性和适应性。
3)公共数据名的使用,明显降低了程序的可读性。[Page]
公共耦合的复杂程度随耦合模块的个数增加而显著增加。如图4.14所示,若只是两个模块之间有公共数据环境,则公共耦合有两种情况。
若一个模块只是往公共数据环境里传送数据,而另一个模块只是从公共数据环境中取数据,则这种公共耦合叫做松散公共耦合。若两个模块都从公共数据环境中取数据,又都向公共数据环境里送数据,则这种公共耦合叫做紧密公共耦合。只有在模块之间共享的数据很多,且通过参数表传递不方便时,才使用公共耦合。否则,还是使用模块独立性比较高的数据耦合好些。
1)一个模块直接访问另一个模块的内部数据;
2)一个模块不通过正常入口转到另一模块内部;
3)两个模块有一部分程序代码重叠(只可能出现在汇编语言中);
4)一个模块有多个入口。
在内容耦合的情形,所访问模块的任何变更,或者用不同的编译器对它再编译,都会造成程序出错。好在大多数高级程序设计语言已经设计成不允许出现内容耦合。它一般出现在汇编语言程序中。这种耦合是模块独立性最弱的耦合。
以上由Myers给出的七种耦合类型,只是从耦合的机制上所做的分类,按耦合的松紧程度的排列只是相对的关系。但它给设计人员在设计程序结构时提供了一个决策准则。实际上,开始时两个模块之间的耦合不只是一种类型,而是多种类型的混合。这就要求设计人员按照Myers提出的方法进行分析,比较和分析,逐步加以改进,以提高模块的独立性。
在模块调用时,传送的控制信息有两种:一种是传送地址,即调用模块直接转向所调用模块内部的某一地址。在这种情况,一个模块的改动对其他模块有直接影响。另一种是传送判定参数,调用模块把判定参数传送给所调用模块,决定所调用模块如何执行。在这种情况下,模块间的耦合程度也很高,所以应当尽量减少和避免传送控制信息。但另一方面,也不要盲目地追求松散的耦合。例如,一个程序有40种出错信息,若把它们集中放在一个错误处理模块中,通过调用模块传送错误类型到该模块的接口上,再进行处理,就形成“控制耦合”。这样做可以消去重复的信息,使所有错误信息格式标准化。所以,耦合类型的选择,应当根据实际情况,全面权衡,综合地进行考虑。
一般情况,在模块的调用序列中若出现大量的参数,就表明所调用模块要执行许多任务。通过把这个所调用模块分解成更小的模块,使得每个小模块只完成一个任务,就可以减少模块接口的参数个数,降低模块接口的复杂性,从而降低模块间的耦合程度。
模块的联系方式(即调用方式)有两种:call方式和“直接引用”。前者使用标准的过程调用方式,模块间接口的复杂性较低,模块间的耦合程度低。后者是一个模块直接访问另一个模块内部的数据或指令,模块间的耦合程度高。所以,应当尽可能用call方式代替“直接引用”,减少模块接口的复杂性。在参数类型上,尽量少使用指针、过程等类型的参数。
此外,在模块接口上传送的信息若能以标准的、直接的方式提供,则信息结构比较简单。若以非标准的、嵌套的方式提供,则信息结构比较复杂。例如,在模块中要调用画直线的命令LINE,若命令要求直接给它直线两个端点的坐标Xo,yo,x1,y1:
call LINE(zo,yo,X1,y1)
则接口复杂性比给origin(始点),end(终点)要低。因为后者还要定义origin和end的结构。
call LINE(origin,end)