所有的程序都需要经过严谨的设计。没有人可以坐在电脑前凭空将一些复杂的逻辑写成程序。软件工程这门学科就是研究程序结构的正确性,能否正常工作以及书写规范的。软件工程师的工作就是使用已被证明正确的方法去分析问题,然后设计一个程序来解决这个问题。
在19世纪70至80年代间,结构化编程是主要的程序设计方法。结构化编程的大体思路是:将待解决的问题分解成几个小问题,然后再对小问题进行分解,直到问题可以直接解决为止。这就是自上而下的编程方法。
自上而下的程序设计方法很常用,具备一定价值,但却有待完善。比如,用这种方法编程基本上只写解决某一问题的必要指令。不久人们就发现,数据结构和子程序设计及流程控制同样重要。自上而下程序设计并没有充分考虑对数据的操作。
这种方法的另一个弊端就是代码难以复用。从分解问题的方法出发,自上而下编程倾向于针对特定问题来设计。这样,你就很难在别的大型工程中复用这些代码,即使勉强可以使用, 也要进行大量修改。写高质量的程序代码费时费力,所以程序员和工程师都尽可能的复用以前的工作。
所以,在实际的程序开发中,自上而下的程序设计通常与自下而上的设计相结合。在自下而上的设计方法中,如果你对某个问题已经有了已知的解决方法,或者手头有可复用的工作,就可以从这里开始,逐步向上工作,来解决整个问题。
复用部分的组件应该尽可能的模块化。一个模块能够和系统的其他部分进行交互,并遵循简洁,规范的设计原则。就像是模块通过「插头」插入系统,模块内部是如何运作的,对系统来说并不重要,只要这个模块的功能运作良好就行了。这就是信息隐藏,在软件工程中是一中重要的思想。
软件模块都要包含一些数据,以及这些数据的处理方法。例如,一个邮件列表模块就得包含一些名字、地址的信息,和这些信息的处理方法,像是添加新名字,显示地址之类的方法等等。在这样的模块中,数据对模块外是不可见的,以保证只有模块中的方法可以以正确的方式处理这些数据。这也使得对模块编程的时候更加方便,只要调用这些方法就可以了,并不需要知道实现的细节。
支持模块的信息隐藏的编程语言从80年代开始流行。那时候起,一种类似的更加先进的编程方法统治了软件开发行业——面向对象编程(object-priented programming,缩写 OOP)。
面向对象编程概念的核心是对象,对象就是内含数据和数据的处理方法的模块。在面向对象的概念中,对象是一个自我实现的实体,有一个内部状态(就是存储的数据),能够对外界的信息作出回应(调用内部的方法)。用邮件列表对象举例,它内部有个包含了名字、地址信息的状态,如果你向它发送信息,要添加一个名字,他就会通过修改自身的状态来回应你。如果你发送打印自己的信息,它就会打印内部保存的名字和地址。
面向对象的程序设计就是通过修改一个对象开始,使它能对传入的信息作出正确回应来解决问题。编程的最终工作结果是一个对象集合,每一个都存有一些数据及方法,对象之间通过传送信息来交互。这种编程的大规模设计上自上而下的思想并不是很多。习惯了传统编程方法的人对这种面向对象编程会不适应。但是,使用面向对象编程的人完全可以这样宣称:这种编程方法更加符合自然规律——事物自己工作。更不用说这种编程方法更易写、易懂、正确率高。
你可以这样想:对象就是知道对于不同的信息做出怎样的回应。对相同的信息来说,不同的对象可能做出不同的回应。例如,不同的对象对于「打印」信息做出的回应可能截然不同。不同的对象对相同的信息做出不同的回应,这种特性就叫做多态。
一个对象可以和其他对象相似。存储的信息类型相同,对于相同的信息能做出相同的回应的对象属于同一个类。(在实际的编程工作中,类的概念是主要的。这是因为,我们首先创建了类,然后在以这个类为模板创建了对象。)但是不属于同一个类的对象可以相似。
例如,假设有一个程序可以让用户在评不上画直线、三角、椭圆、多边形和曲线。在这个程序中,每一个可视的物体都有一个对应的对象。那么在这个程序中就会存在5个类,用以产生5个不同的可视对象。所有的直线对象属于同一个类,三角形属于另一个类,以此类推。显然,所有的这些类都是相关的,都代表了可绘制对象,都会对「绘制图形」的信息做出回应。另一种分组方式,建立在他们保存的数据所代表的图形上,这些关系不很明显,但是在编程中很有用:可以将多边形和曲线作为「多点对象」一组,直线、矩形、椭圆作为「两点对象」一组。(这是因为,直线通过两个点可以确定,矩形通过两对点可以确定,椭圆通过两个焦点可以确定。这里所说的矩形指的是所有边都垂直或者水平的矩形,编程中用到的矩形大多都是这样的。)我们可以用下面这个图标来表示他们的关系。
DrawableObject、MultipointObject、TwoPointObject 在程序中属于不同的类。MultipointObject 和 TwoPointObject 属于 DrawableObject 的子类。Line 属于 TwoPointObject 和 DrawableObject(非直接)的子类。子类继承了父类的特性,子类也可以写入新的特性来覆盖掉原来父类的特性(通过定义一个对信息的不同回应方式)。不过,Line Rectangle 这些对象都是可绘制对象,DrawableObject 对象表达了这一关系。
继承在程序设计中大有用处,因为这涉及到代码复用。而类就是代码复用的最终形式。如果已经有一个类满足你的需求,就可以直接来使用这个类。如果有和你的需求类似的类,你就可以通过定义一个子类,稍作修改来使用。
综上,面向对象不仅是一种先进的编程方式,还是复用代码的一种手段。在接下来的章节中,对象、类和面向对象编程将会成为重要主题。下一章你将会开始在 Java 语言中使用对象。在第五章中你将会创建自己的类和对象。
原文链接: math.hws.edu 翻译:ImportNew.com -赖 信涛
译文链接:[]