7.1 软件设计引论       “软件设计”一词的意思是指,把一个计算机程序的定义转变成可以运行程序的设计方法;设计是联系要求定义和编码与调试的活动的桥梁;它是一个启发的过程而不是一个确定的过程,需要创造性和深刻的理解力;设计活动的绝大部分活动都是针对当前某特定项目进行的。
7.1.1 大型和小型项目设计        一个大型项目可能有几个级别的设计工作—软件结构设计、高层次模块设计和实现细节设计;结构设计具有指导的意义,在小规模编码阶段往往也是很有帮助的。
7.1.2 设计的层次        层次1:划分成子系统
       在这一层次上,设计的主要成果是划分系统的主要子系统;这些子系统可能是很大的—数据库接口、用户接口、命令解释程序、报告格式程序等等;这一层次的主要设计活动是如何将系统划分成几个主要要素,并且定义这些要素间的接口;在这一层次上的划分工作主要是针对那些耗时在几天以上的项目。
        层次2:划分成模块
        这一层次的设计包括识别系统中的所有模块。
       层次3:划分成子程序
       这个层次的设计包括把每个模块划分成各种功能,一旦一个子程序被识别出来,那么就同时规定它的功能;由于模块与系统其它部分是相互作用的,而这一作用又是通过功能子程序进行的,所以,模块与系统其余部分的作用细节是在这一部分规定的。
        层次4:子程序内部的设计
        在子程序层次上的设计,包括设计单个子程序中的详细功能等;子程序内部设计往往是由程序员进行的;这一设计包括编写PDL,在参考书中寻找算法,在子程序中组织代码段落,编写编程语言代码等活动。
7.1.3 创建中的设计工作        内部子程序设计,划分成子程序,划分成模块,划分成子系统。

7.2 结构化设计        结构化设计是由以下部分组成的:1)系统组织;2)开发设计的策略;3)评估设计准则;4)关于问题的明确说明,这是解决问题的指导原则;5)表达设计的图形和语言工具,包括PDL和结构图。
7.2.1 选择需进行模块化的要素        自顶向下分解        把程序分解为子程序的一种流行方法是自顶向下分解,也称为自顶向下设计或逐步求精;其特点是从关于程序功能的粗略说明出发,逐步推进到程序要做的每一项特定的工作;从粗略的层次出发往往是指从程序中的“主要”子程序出发,通常,把这个子程序画在结构图的顶部。
        在进行自顶向下分解时要牢记的原则:1)设计高层次;2)避免特定语言细节;3)暂时不指出下一层次的设计细节;4)正规化每个层次;5)检验每个层次;6)转移到下一个层次,进行新的求精工作。
        自顶向下设计指导原则的依据是:人脑一次只能考虑有限数量的细节;这种方法也常称之为“分而治之”战术。

        自底向上合成        在进行自底向上合成时要牢记的原则:1)问自己,关于系统要做什么你都知道哪些?2)利用这一问题识别出某些低层次功能;3)识别出这些低层次功能共同的方面,将其组合到一起;4)向上一个层次,进行同样的工作,或回到顶端开始自顶向下。

 

《代码大全》学习笔记(7):高级结构设计_子程序


        其中自顶向下是从一般到特殊,自底向上是从特殊到一般。

        自顶向下与自底向上        自底向上与自顶向下策略的首要区别是前者是合成,而后者则是分解。
        自顶向下设计方法的特点是比较简单,人们往往擅长把大问题分解成小问题;自顶向下设计的另一个优点是你可以避开实现细节。这种设计方法也有它的缺点,其中之一是系统的总体功能可能是很难识别的;它的另一个缺点是:由于许多系统本身并不是层级结构的,因此是很难清晰地分解;这种设计方法的最大缺点就是它要求系统在顶层要有一个单一而又清楚的功能。
        自底向上设计方法的优点是它在早期就可以识别出有用的功能子程序,结果是坚实可靠的设计。这种方法的弱点是很难单独地使用它;它的另一个弱点是,有时从你识别出的细节出发,无法建造出整个程序,就像你无法用砖头造出一架飞机一样。

7.3 面向对象        面向对象设计方法的特点是通过对实际问题的分析,从中抽象出对象,然后再用程序语言来表现它,其过程主要是:识别对象中的子对象并识别出对于子对象的操作,然后再根据子对象的操作开发出一个系统;面向对象设计是在程序中设计对象或模块的一种方法;在较低的程度上说,它也是设计单个子程序的一种方法。
7.3.1 关键思想        面向对象设计是建立在如下主张之上的,即:一个程序模型越是真实地反映了实际问题,那么,由此产生出的程序质量越好。
        抽象        抽象所带来的主要好处是可以忽略掉无关紧要的细枝末节问题,而专注于重要的特性。
        封装        封装是对抽象不存在地方的补充;如果抽象对你说“你应该在较高层次上看一个对象”,而封装则会说“你只能在这个层次上看一个对象”。
        模块化        面向对象设计中的模块与结构化设计中模块的含义是一致的;相联系的数据和功能被放入模块,在理想情况下,模块是高度内聚而又松散耦合的。
        层次结构和继承性(inheritance)        定义这种对象间的共同和不同点称为“继承性”,继承策略的好处是它与抽象的概念是一致的,抽象在不同层次的细节上与对象打交道;在面向对象编程中,继承性简化了编程,因为你只要写一个通用子程序来处理对象间的共同特性,再编写几个专用子程序去处理它们间的不同特性就可以了。
        对象与类        对象是程序在运行时其中的任何一个实体,而类则是当你看程序清单时存在的一个静态实体;对象是在程序运行时具有特定值和属性的动态实体。
7.3.2 面向对象设计的步骤        面向对象设计的步骤是:1)识别对象及其属性,它往往是数据;2)确定对每个对象可以做些什么;3)确定每一个对象可以对其它对象做些什么;4)确定每个对象对其它对象来说是可见的部分—哪一部分是开放的,哪一部分是专用的;5)确定每个对象的公共接口。
       逐次迭代逼近对面向对象设计是与其它设计方法同样重要的,下面将分别论述这些步骤:1)识别对象及其属性;2)确定可以对一个对象做些什么;3)确定对象之间可以互相做些什么;4)确定每一个对象中对其它对象来说是可见的部分;5)定义每一个对象的接口。
7.3.3 典型面向对象设计的评论        一个面向对象系统通常有至少四类对象:1)问题域要素;2)用户接口要素;3)任务管理要素;4)数据管理要素。

7.4 对目前流行设计方法的评论        结构化设计和面向对象设计方法都包括两个主要部分:1)把一个系统分解成子系统的准则;2)解释分解的图形式语言符号;3)有些方法还包括第三个要素;4)防止你使用其它方法的规定。
7.4.1 何时使用结构化设计        结构化设计主要是一种把程序分解成子程序的方法;结构化设计并没有把子程序组成一个协同工作子程序组的概念,也没有子程序内部设计的概念,除非这个子程序的内部会影响到整个系统。
7.4.2 何时采用信息隐蔽        无论什么问题领域,都应该尽量采用信息隐蔽。
7.4.3 何时采用面向对象设计        面向对象设计主要是设计模块数据和对数据操作的集合,它非常适于从最顶层分解系统。
        面向对象设计适合于任何客观世界中的对象。

7.5 往返设计7.5.1 什么是往返       “往返设计”一词抓住了设计是个迭代过程这一特点:通常你不会只从A点走到B点,往往还需要再返回A点。
        在用不同的设计方法对各种设计方案进行尝试的进程中,将从高层次的总体上和低层次的细节上对问题进行观察。
7.5.2 设计是一个复杂的过程        设计是一个复杂的过程,因为你很难把正确答案与错误答案区分开来。
7.5.3 设计是一个“险恶”的过程        Horst Rittel和Melvin Webber把“烦人”的问题,定义成只有通过解决它或者部分解决它,才能给出明确定义的问题。
7.5.4 设计是一个启发的过程        进行有效设计的关键是要认识到它是个启发的过程。
        一种很有效的启发工具就是硬算;图示法是另一种有力的启发工具;往返设计的一个附加的启发能力是你在设计的头几次循环中,可以暂时对没有解决的细节问题弃之不管,你不必一次就对一切都做出决定,应记住还有一个问题有待做出决定,但同时要意识到,你目前还没有充分的信息来解决这个问题。
        最重要的设计原则之一是不要死抱着一种方法不放。
        怎样解决问题:1)理解问题,你必须理解要解决的问题;2)设计一个方案,找到已知数据和未知之间的联系,如果不能找出直接联系的话,你可能不得不考虑一些辅助问题,但最后,你应该找到一个解决方案;3)执行你的计划;4)回顾,检查一下答案。
7.5.5 受欢迎的设计特点        设计的挑战所在是在相互矛盾的对象之间做出合理的折衷。
        设计所独有的一些特点:1)智力上的可管理性;2)低复杂性;3)维护的方便性;4)最小的联系性(最小的联系性指的是按照保持子程序之间的联系最少的原则来设计);5)可扩充性(可扩充性指的是不必影响系统的内部结构,就可以对系统的功能进行强化);6)可重复使用性(指的是把系统设计成其中许多部分是可以被其它系统借用的);7)高扇入(高扇入指的是对于一个给定的子程序来说,应该有尽可能多的子程序调用它);8)低或中等程度扇出(低或中等扇出指的是对一个确定的子程序来说,它所调用的子程序应该尽可能地少);9)可移植性(指的是把系统设计成很容易转到另外的环境下运行);10)简练性(指的是把系统设计得没有任何多余部分);11)成层设计(指的是尽量分解的层次是成层的,这样你可以在每一个单独的层次上观察系统,同时也可以使观察的层次是连续的);12)标准化技求。
7.5.6 检查表      高层次设计。

7.6 小结(1) 设计是一个启发的过程;固执地坚持某一种方法只会抑制创造力,从而产生低质量的程序;坚持设计方法上有一些不屈不挠的精神是有益的,因为这可以迫使你对这种方法进行充分理解;但是,一定要确信你是在不屈不挠而不是顽固不化。
(2) 好的设计是通过迭代逼近得到的:你尝试过的设计方案越多,你最终所确定的设计方案也越好。
(3) 结构化设计比较适合于小规模的子程序组合,同时,它对于功能变化可能性比数据大的问题也是较适用的。
(4) 面向对象设计更适于子程序与数据的组合,通常在比结构化设计抽象程度更高些的层次上适用;它尤其适合于数据变动可能性大于功能变动可能性的问题。
(5) 设计方法仅是一种工具,你对工具运用的好坏决定了你所设计的程序的质量;利用不好的设计方法,也可能设计出高质量的程序;而即使是好的方法,如果运用不当的话,也只能设计出拙劣的程序;但不管怎样,选择正确的工具更容易设计出高质量的软件。

 

        本章小结:

        本章介绍了高级结构设计,其中面向对象是重点。

        任何设计都是思维的体现。为了体现出良好的设计水平,我们一定要培养严谨、全面的思维方式。