时应重新设计子程序或子程序群,来降低耦合的紧密性。如果你把同一数据传给不同的子程序,
应当把这些子程序组织成一个模块,并把那些经常使用的数据当做模块数据。
考虑建一个关于输入、修改和输出参数的命名约定。如果发现区分输入,修改和输出参数
是非常重要的,则你可以建立一个关于命名的约定,以便区分它们,比如可以用i_,m_,o_作前
缀。要是你不觉得冗长的话,可以用INPUT,MODIFY 和OUTPUT 来作前缀。
仅传递子理序器要的那部分结构化变量。如同在5.4 节关于耦合中讨论过的那样:如果子
程序不是使用结构化变量中绝大部分的话,那么就只传递它所用得到的那一部分。如果你精确
规定了接口,在别的地方再调用这个子程序会容易些。精确的接口可以降低子程序间的耦合程
度,从而提高子程序的使用灵活性。
不过,当我们使用抽象数据类型(ADT)时,这一精确接口规则使不适用了。这种数据类
型要求我们跟踪结构化变量,但这时你最好不要过分注意结构内部,在这种情况下,应把抽象
数据类型子程序设计成将整个记录作为一个参数来接收的,这可以使你把这个记录当成ADT子
程序之外的一个目标,并把这个记录的抽象水平保持在与ADT 子程序的相同高度上,如果你通
过利用其中的每一个域来打开结构,那你就丧失了由ADT 所带来的抽象性。
不要对参数传递作出任何设想。有些程序员总是担心与参数传递有关的内部操作,并绕过
高级语言的参数传递机制,这样做是非常危险的,而且使得程序的可移植性变坏。参数一般是
通过系统堆栈传输的,但这决不是系统传递参数的唯一方式。即使是以堆栈为基础的传递机制,
这些参数的传递顺序也是不同的,而且每一个参数的字长都会有不同程度的改变。如果你直接
与参数打交道,事实上就已经注定了你的程序不可能在另一个机器上运行。
5.8 使用函数
像C、Pascal和Ada等先进的语言,都同时支持函数和过程,函数是返回一个值的子程序,
而过程则是不返回值的子程序。
5.8.1 什么时侯使用函数,什么时侯使用过程
激进者认为函数应该像数学中的函数一样,只返回一个值。这意味着函数应接受唯一的输
入数据并返回一个唯一的值。这种函数总是以它所返回的值来命名的,比如sin(),cos(),
CustomerID()等等,而过程对于输入、修改、输出参数的个数则没有限制。
公用编程法是指把一个函数当作过程来使用,并返回一个状态变量。从逻辑上说,它是一
个过程,但由于它只返回一个值,因此从名义上说,它又是函数。你可能在语句中使用过如下
一个称为Fotmatoutput()的过程:
if (Formatoutput(Input,Formatting,Output) = Success ) then ...
在这个例子中,从它输出参数的角度来看,是一个过程。但是从纯技术角度来说,因为程
序返回一个值,它又是一个函数。这是使用函数的合法方式吗?从保护这个方法的角度出发,
你可以认为这个函数返回一个值与这个子程序的主要目的——格式化输击无关。从这个观点来
看,虽然它名义上是一个函数,但它运行起来更像是过程。如果一贯使用这种技术的话,那么
用返回值来表示这个过程的成功与否并不会使人感到困惑。
一个替换的方案是建立一个用状态变量作为显式参数的子程序,从而产生了如下所示的