瑞星卡卡安全论坛技术交流区系统软件 【转载】软件开发人员必备工具书 【代码大全】

«678910111213»   10  /  16  页   跳转

【转载】软件开发人员必备工具书 【代码大全】

function HighestPriorityEvent: Event;
function LowestPriorityEvnet:Event;
IMPLEMENTATION
...    ——文件中这部分的子程序数据,如果没有在上面INTERFACE 中说明
                    的话,则对其它文件来说是隐蔽的
end.{unit Events}
  属于Generic Pascal标准的Pascal实现并不直接支持模块化,不过你可以通过扩展它们来达
到模块化,这将在后面讨论。
C 的支持
  虽然用C语言编程的程序员们并不习惯在C中使用模块,但事实上C也直接支持模块化。
每一个C 源文件都可以同时含有数据和函数,可以把这些数据和函数说明为Static,这将使它
们只在源文件内部才能使用。也可以不把它们说明为Static,此时它们在源文件外也可以使用。
当每一个源文件都被当作模块时,C 就完全支持模块化了。
  由于源文件和模块并不完全相同,你需要为每一个源文件创建两个标题文件——一个作为
公用、模块标题文件,另一个作为专用的、源文件标题文件。在源文件的公用标题文件中,只
放入公用数据和函数说明,下面是一个例子:
/* File:Event.h 本文件仅包含公共的可用类型、数据和函数说明
Contains public declarations for the "Event" module. */
typedef int EVENT;
extern BOOL EventAvailable; /* true if an event is available */
EVENT HighestPriorityEvent(void);
EVENT LowestPriorityEvent(void);
而在源文件专用标题文件,只放入供内部使用的数据和函数说明。用#include命令把标题
文件只放入组成模块的源文件中,不要允许其它文件含有它。以下是一个例子:
/* File:_Event.h
Contains private declarations for the "Event" module. */
/* private declarations */ ——这里是专用类型、数据和函数
...

  C 源文件中,要使用#include 来把两个标题文件都包含在其中。在其它使用了Event模块
中的公用子程序模块中,用#include命令来只把公用的模块标题包含进去。
  如果在单独一个模块中,需要使用一个以上源文件,可能要为每一个源文件都加一个专用
标题文件;但对组成模块的子程序组,应该只加一个公共的模块标题文件。对于模块中的源
gototop
 

文件来说,利用#include来包含同一个模块中其它源文件的标题文件是可以的。
  Fortran 的支持
    Fortran90为模块提供了全部支持。而Fortran77如果在规定范围内使用,则只对模块提供
了有限的支持。它拥有创建一组对数据具有独占存取权的机制,这个机制就是多重入口点,
对这种机制的随便使用,往往会产生问题。而如果小心使用的话,它则提供了一种不必使数
据成为公用的,就可以使一组子程序对同数据进行存取的途径。
    可以说明数据为局部的、全局的或者是COMMON 的。这个特性又提供了使子程序对数
据进行受限制存取的方法,定义一组组成一个模块的子程序。Fortran 编译程序无论如何也不
会认为它们组成了一个模块,但是从逻辑上来说,它们的确组成了一个模块。对模块中每一
个允许对数据进行直接操作的子程序,都应该用COMMON 作为其前缀来命名。不要让模块
以外的子程序使用COMMON 作为前缀。利用编程标准来弥补程序语言不足这一办法,将在
后面讨论。
6.4.3  伪模块化
    在像通用Basic,通用Pascal和其它既不直接也不间接支持模块化的语言中,该如何进行模
块化呢?答案在前面已经提到过了,利用编程标准来代替语言的直接支持。即使你的编译程序
并不强制你采用好的编程应用,还可以采用能够达到这一目的的编码标准。以下的讨论涉及了
模块化所要求的每一方面。
把数据和子程序装入模块
    这个过程的难易程度取决于编程语言,即它是允许使用各种源文件的还是要求所有的代码
必须是在一个源文件中的?如果你需要用10 个模块,那就创建10 个源文件。如果环境要求所
有代码都要在一个源文件中,那就按模块把代码划分为几部分,同时用注释来区分每一个模块
的开头和结尾。
保证模块的内部子程序是专用的
    如果所采用的程序语言不支持限制内部子程序的可见性,使得所有的子程序对其它子程序
来说都是公用的,可以利用编码规定来限定只有标明公用的子程序才能被模块外的子程序使用。
不管是什么样的编译程序,下面都是你可以做的:
    通过在说明的地方加注释,来明确区分公用和专用子程序。明确区分与每个子程序相关的
模块。如果别人不得不通过查询子程序说明来使用子程序,要确保在说明中注释了它是公用的
还是专用的。
    不允许子程序调用其它模块的内部子程序。使用注释把属于同一个模块的子程序联系到一
起。
    采用命名约定来表明一个子程序是内部的还是外部的。可以让所有的内部子程序名称前面
都带有下划线(_)。虽然这种方法无法区分不同模块的内部子程序,但是绝大多数人还是可以
区分一个子程序是否是属于它们自己的模块。如果它不是自己模块中的子程序,那么显然它是
其余模块中的子程序。
gototop
 

采用表明它是内部的还是外部的命名规定。所采用约定的细节,往往取决于编程语言所赋
予你对子程序命名的灵活性。例如,一个DataRetrieval 模块的内部子程序名称可能会以dr_作
为前缀。而UserInterface模块内部子程序的名称前缀则可以是ui_。而属于同一模块的外部子程
序则分别会以DR_和UI_作为前缀,如果对名称的字节长度是有限制的(如,ANSI FORTRAN77
中的6个字母),那么命名的约定就会用掉其中相当一部分,这时,在制定命名约定时就要注意
这一长度限制。
保证子程序的内部数据是专用的。
保证模块层次上的内部数据的专用性与保证模块层次上子程序的专用性是相似的。通常,
要采用清楚表明只有特定数据才能在文件外部使用的编码标准。不管编译程序允许你做的是什
么,以下是一些可以采用的步骤:
首先,利用注释来说明数据是公用的还是专用的。明确区分模块所涉及到的每一个数据的
可存取性。
其次,不允许任何子程序使用其它模块中的专用数据,即使编译程序把此数据作为全局变
量也不可以。
第三,采用可以使你注意一个文件是专用还是公用的命名约定。为了保持连贯性,应该使
这一命名原则与子程序的命名原则类似。
第四,采用表明数据属于哪一个模块,即它是外部还是内部的命名约定。
6.4.4  检查表
模块的质量
· 模块是否有一个中心目的?
· 模块是否是围绕着一组公用数据进行组织的?
· 模块是否提供了一套相互联系的功能?
· 模块功能是否足够完备,从而使得其它模块不必干预其内部数据?
· 一个模块相对其它模块是否是独立的?它们之间是松散耦合的吗?
· 一个模块的实现细节,对其它模块来说,是隐含的吗?
· 模块的接口是否抽象到了不必关心其功能实现方式的地步?它是作为一个黑盒子来设
计的吗?
· 是否考虑过把模块再划分为单元模块?是否对其进行了充分的再划分工作?
· 如果用不完全支持模块的语言编程,你是否制定了编程约定以使这种语言支持模块?
6.5  小  结
· 不管调用哪一个,子程序与模块的不同是很重要的,要认真考虑子程序与模块的设计。
· 从模块数据是被几个子程序使用的这一角度来说,它与全局数据是相同的,但从可以
使用它的子程序是有限的,而且清楚地知道是哪些子程序可以使用它这一角度来说,
模块数据与全局数据又是不同的。因此,可以使用模块数据而没有全局数据的危险。
gototop
 

· 信息隐蔽总是有益的。其结果是可以产生可靠的易于改进的系统,它也是目前流行的
设计方法的核心。
· 创建模块的原因有许多是与创建子程序相同的。但模块概念的意义要比子程序深远得
多,因为它可以提供一整套而不是单独一个功能,因此,它是比子程序更高层次的设
计工具。
· 可以在任何语言中进行模块设计。如果所采用的语言不直接支持模块,可以用编程约
定对其加以扩展,以达到某种程度的模块化。
gototop
 

呵呵,继续


第七章  高级结构设计

目录
7.1  软件设计引论
7.2  结构化设计
7.3  面向对象
7.4  对目前流行设计方法的评论
7.5  往返设计
7.6  小结
相关章节
高质量子程序的特点:见第5 章
高质量模块的特点:见第6 章
软件结构设计:见3.4 节

有些人可能认为高层次设计不是真正的实现活动,但是在小规模项目中,许多活动都被认
为是实现活动,其中包括设计。在一些较大的项目中,一个正式的结构设计可能只是分解系统,
而其余大量的设计工作往往留在创建过程中进行。在其它的大型项目中,设计工作可能是非常
详细的,以致于编码不过是一项机械的工作而已,但是设计很少有这样详尽的。编码人员常常
要进行一些设计工作。
高层次设计是一个很大的主题,同时也由于它只部分地与本书主题有关系,因此,我们将
只论述其中的几个方面。模块设计和子程序设计的好坏在很大程度上取决于系统的结构设计好
不好,因此,要确保结构设计先决条件(如3.4 节所述)已经被满足了。也有许多设计工作是
在单个子程序和模块层次上进行的,这已在四、五、六章中论述过了。
如果已经对结构化设计和面向用户设计非常熟悉了,你可能想阅读下一部分的介绍,再跳
到7.4 节关于两种技术的比较,最后阅读7.5 节。

7.1  软件设计引论

“软件设计”一词的意思是指,把一个计算机程序的定义转变成可以运行程序的设计方法。
设计是联系要求定义和编码与调试的活动的桥梁。 它是一个启发的过程而不是一个确定的过
程,需要创造性和深刻的理解力。设计活动的绝大部分活动都是针对当前某特定项目进行的。
7.1. 1  大型和小型项目设计
在大型的、正规的项目中,设计通常是与需求分析、编码等活动分立的,它们甚至可能是
由不同人分别完成的。一个大型项目可能有几个级别的设计工作——软件结构设计、高层次模
块设计和实现细节设计。结构设计具有指导的意义,在小规模编码阶段往往也是很有帮助的。如
gototop
 

果进行了通用或高层次设计,那么其指导方针则在大规模编码阶段是非常有意义的。不管是出
于什么原因,即使名义上设计工作已经结束了,但事实上它远没有停止。
在小型的、非正式的项目中,大量的设计工作都是由程序员们坐在键盘前面完成的。“设计”
可能只是用程序语言编程,用PDL来编写子程序。也可能是在编写子程序之前画一下流程图。
不管是怎样进行的,小型项目与大型项目一样,都会从良好的设计工作中受到大量好处。而使
得设计活动明显化,则会极大地扩展这一好处。
7.1. 2  设计的层次
软件系统中,设计是在几个不同层次的细节上进行的。有些技术适用于所有的层次,而另
外一些,则往往只会适合其中的一或两个层次,下面是这些层次:

层次1:划分成子系统:
   
在这一层次上,设计的主要成果是划分系统的主要子系统。这些子系统可能是很大的——
数据库接口、用户接口、命令解释程序、报告格式程序等等。这一层次的主要设计活动是如何
将系统划分成几个主要要素,并且定义这些要素间的接口。在这一层次上的划分工作主要是针
对那些耗时在几天以上的项目。在图7-1中,设计是由三个主要元素和它们的交互作用组成的。

     
其中程序划分为系统(l),子系统更进一步划分为模块(2),一些模块划分为程序(3),
(4)为每个子程序内部设计。
“子程序”和“模块”的特定意义已经在前几章中引入了。“Subprogram”一词将在本章中
使用,我们可以称它为“亚程序”,它是指小于整个程序的任何程序,其中也包括子程序和模块。

层次2:划分成模块:

    这一层次的设计包括识别系统中的所有模块。在大型系统中,在程序分区层次上划分出来

附件附件:

下载次数:222
文件类型:application/octet-stream
文件大小:
上传时间:2006-8-25 16:28:14
描述:



gototop
 

的子系统往往太大,难以直接翻译成代码。例如,一个数据库接口子系统可能非常复杂,需要
有十几个子程序来实现。如果出现这种情况,那么还需要将这个子系统再划分为模块:如数据
存储、数据恢复、问题解释等模块。如果分解出来的模块还是太复杂,那么将对它再次划分。
在许多程序的设计中,在层次1 中分解出来的子系统将直接转变成层次2 中的模块,而不再区
分这两个阶段。
在定义模块时,同时也要定义程序中每个模块之间的相互作用方式。例如,将定义属于某
一模块的数据存取函数。总之,这一层次的主要设计活动是确保所有的子系统都被分解成为可
以用单个模块来实现它的每一部分。
与把一个系统分解成子系统一样,把子系统分解成模块也是主要针对耗时在几天以上的项
目的。如果项目很大,这一层次的分解活动是与上一层次严格区分的。如果项目较小,层次1
与层次2 可能是同时进行的。在图7-1 中,分解为模块的活动已经包含于每个元素中了。正如
图中所示的那样,对于系统不同部分的设计方法是也不同的。对某些模块之间关系的设计可能
是以网络思想为基础的,也可能是以面向对象思想为基础的。如同图中左面两个子系统那样。
而其它模块的设计则可能是分级的。如图中右侧的子系统那样。
层次3:划分成子程序:
    这个层次的设计包括把每个模块划分成各种功能,一旦一个子程序被识别出来,那么就同
时规定它的功能。由于模块与系统其它部分是相互作用的,而这一作用又是通过功能子程序进
行的,所以,模块与系统其余部分的作用细节是在这一部分规定的。例如,将严格定义如何调
用解释程序。
    这一层次的分解和设计工作对于任何耗时超过几个小时的项目都是需要的,它并不一定需
要被正式地进行,但起码是要在心中进行。在图7-1 中,在左上角的一组中的一个模块中,给
出了划分成子程序的工作活动。当你揭开黑盒子的盖子时,如同图7-l 中标有3 的模块,你可
以发现由模块提供的功能是由层次组织的子程序组成的。这并不是意味着每个黑盒子中都含有
层次结构,事实上只有某些黑盒子中才有。其余组织形式的子程序可能没有或很少有层次结构。
层次4:子程序内部的设计:
在子程序层次上的设计,包括设计单个子程序中的详细功能等。子程序内部设计往往是由
程序员进行的。这一设计包括编写PDL,在参考书中寻找算法,在子程序中组织代码段落,编
写编程语言代码等活动。这种层次的工作在任何一个项目中都是要进行的,无论是有意识的还
是无意识的,是作得好还是作得坏。如果缺少了这一层次的工作,任何程序都不可能产生。在
图7-1 中,在标有(4)的一组中,表现了这个层次的工作。
7.1.3  创建中的设计工作
    对于设计层次的讨论,是论述本章其余部分内容的前提,当人们在提到“设计”一词时,
他们事实指的可能是许多不同的活动。这是一个非常重大的主题,也是非常重要的。以下是关
于这一活动,但这次是按照从细节到总体的顺序进行的。
gototop
 


内部子程序设计
在第四章中间明确讨论过内部子程序设计问题,在第五章“高质量子程序的特点”中,对
这一问题又作了进一步的讨论。在第五章关于数据和数据控制部分中,从个别程序语句和子程
序中模块的层次,对这一问题进行了讨论。在本章中,这一问题的讨论主要分布在各个部分中。
划分成子程序
在结构化设计方法中,“设计”往往是指设计程序的结构,而不指单个子程序内部的设计。
关于程序结构问题,完全可以写一本专著,本章中论述的只是构造简单程序集合的技术总结,
这些子程序集合将是你在设计中经常要实现的。
划分成模块
    在面向对象设计中,“设计”指的是设计一个系统中的不同模块。模块定义也是一个很大的
足以写成一部书的主题,在第六章中已经论述过了。
划分成子系统
对于中小型程序来说(一般是10000条语句左右),定义模块和子程序的技术往往隐含在整
个程序的设计中,在更大一些程序中,往往需要特殊的设计方法,这对于本书来说(本书重点
是实现)是难以详尽论述的。在许多情况下,特别是在一些小项目中,设计工作是键盘上完成
的,因此事实上是一种实现活动,虽然它应该在早期就完成了。本书之所以涉及了模块和子程
序设计,是因为它们处在实现的边缘上。而关于程序划分的其它讨论,则不在本书之列。
7.2  结构化设计
结构化设计这一概念是1974年在《IBM系统日报》(IBM System Journal)一篇论文中出现
的。在后来由Ed Yourdon和Larry Constantine写进《Structured Design:Fundamentals of a Discipline
of Computer Program and Systems Design》书中(1971),对其作了全面补充与扩展。Constantine
是最初那篇论文的作者之一,而“自顶向下设计”一词则是指一种非正式的结构化设计,类似
的词还有“逐步求精”和“分解”等,指的基本都是同一意思。结构化设计是与其它结构化设
计方法一道使用的。
结构化设计是由以下部分组成的:
•  系统组织,系统将被设计成几个黑盒子,明确定义的子程序和模块、接口的实现细节对
  其它子程序来说都是隐含的。
•  开发设计的策略。
•  评估设计准则。
•  关于问题的明确说明,这是解决问题的指导原则。
•  表达设计的图形和语言工具,包括PDL 和结构图。
在下面的内容中,将对这些内容作比较详细的论述。
gototop
 

7.2.1    选择需进行模块化的要素
    在前面几章论述了程序和模块相关好坏的标准,并提供了确定子程序和模块质量的检查表,
但并没有给出识别子程序和模块的方法,在本节中,将论述这一问题的指导原则。
自顶向下分解
    把程序分解为子程序的一种流行方法是自顶向下分解,也称为自顶向下设计或逐步求精。
其特点是从关于程序功能的粗略说明出发,逐步推进到程序要做的每一项特定的工作。从粗略
的层次出发往往是指从程序中的“主要”子程序出发,通常,把这个子程序画在结构图的顶部。
    以下是几项在进行自顶向下分解时要牢记的原则:
•  设计高层次。
•  避免特定语言细节。从设计中,不应该看出打算在程序中使用什么语言,或者说当在设
      计中更换要用的语言时,不会产生任何麻烦。
•  暂时不指出下一层次的设计细节(与信息隐含类似)。
•  正规化每个层次。
•  检验每个层次。
•  转移到下一个层次,进行新的求精工作。
自顶向下设计指导原则的依据是:人脑一次只能考虑有限数量的细节。如果你从一个较简
略的子程序开始,逐步把它分解成更加详细的子程序,就不必每次考虑过多的细节。这种方法
也常称之为“分而治之”战术。它对于分层结构往往是最有效的。如图7-2 所示。
从两个方面来看,这种分而治之战术是一个逐次迭代逼近的过程,首先,这是由于往往在
一次分解之后你并不会马上停止,还要进行下几个层次的分解。其次,是由于分解并不是一蹴
而就的,采用某种方法分解一个程序,再看一下效果,然后,又用另外一种方法来分解这个程
序,看效果是否会好些,在几次尝试之后,就有了一个很好的办法,同时也知道为什么这样做。
需要把一个程序分解到什么程度呢?要持续不断地分解,直到看起来下一步进行编码要比
再分解要容易为止,或者到你认为设计已经非常明了详细,对再分解已经感到不耐烦为止,到
这时,可以认为分解已经完成了。由于你比任何人都熟悉这个问题,而且也比任何人都清楚,
因此,你要确保其解决方案是很容易理解的,如果连你都对解决方案有些困惑的话,那么,试
想一下,又有谁会理解它呢?
自底向上合成
    有时候,自顶向下方法过于抽象以至于让人不知从何下手。如果想要进行一些具体的工作,
那么可以试一下自底向上的设计方法,如图7-2 所示。你可以问自己,“这个系统需要做什么?”
毫无疑问,你能够回答这个问题。你可以识别出系统需要具备的较低层次的功能,例如,你可
能知道这个系统需要进行报告格式化、计算报告总数、用不同颜色在屏幕上显示字母等等。当
你识别出某些低层次功能后,再从事较高层设计可能会有把握些。
    以下是一些在进行自底向上合成时要牢记的原则:
•  问自己,关于系统要做什么你都知道哪些?
•  利用这一问题识别出某些低层次功能。
gototop
 


•  识别出这些低层次功能共同的方面,将其组合到一起。
•  向上一个层次,进行同样的工作,或回到顶端开始自顶向下。



其中自顶向下是从一般到特珠,自底向上是从特殊到一般。
自顶向下与自底向上
自底向上与自顶向下策略的首要区别是前者是合成,而后者则是分解。一个是从可控制的
零散问题出发,把它们合成到一起从而获得一个总体解决方案,而另一个则从总体问题出发,
将其分解成可控制的零散问题。两种方法各有优缺点。在实际使用时要详加比较。
自顶向下设计方法的特点是比较简单,人们往往擅长把大问题分解成小问题,而程序员们
则更是擅长这点。当一个问题是用层次结构模型化的时候,自上而下的分解方法恰好与其相符。
自顶向下设计的另一个优点是你可以避开实现细节。由于系统常常受到实现细节变动的干
扰(比如文件结构或报告格式的变化),因此把这些细节隐含在层级结构的底部,而不是让它在
顶部起支配作用,是非常有益的。
这种设计方法也有它的缺点。其中之一是系统的总体功能可能是很难识别的。关于系统所
作的最重要决定之一就是如何进行第一步分解工作,而在自上向下设计中,刚开始接触系统,
对其了解还很少时,便不得不做出这一决定,这是很危险的。它的另一个缺点是:由于许多系
统本身并不是层级结构的,因此是很难清晰地分解。或许这种设计方法的最大缺点就是它要求
系统在顶层要有一个单一而又清楚的功能,而对于现代事件驱动系统来说,这是很难想象的。
自底向上设计方法的优点是它在早期就可以识别出有用的功能子程序,结果是坚实可靠的
设计。如果已经开发了相似的系统,那么可以参阅一下旧系统,看看有什么可以借用的。
这种文件的弱点是很难单独地使用它。因为大多数人都不善于从小的概念出发形成综合         
的设想。这就像一个自己组装的玩具,我想我已经组装完了,怎么盒子中还有零件呢?好在,
你不必单独使用它。
它的另一个弱点是,有时从你识别出的细节出发,无法建造出整个程序,就像你无法用砖头
造出一架飞机一样。而且当你知道在底部需要什么功能时,你可能已经不得不进行顶层设计了。

附件附件:

下载次数:219
文件类型:application/octet-stream
文件大小:
上传时间:2006-8-25 16:30:02
描述:



gototop
 
«678910111213»   10  /  16  页   跳转
页面顶部
Powered by Discuz!NT