1、 软件工程思想 林锐 序序 软件工程思想讲述“软件开发”和 “做程序员”的道理,视野独特,构思新颖,内容风趣,不落窠臼,令人耳目一新。堪称难得,以至回味无穷。 作者从事了八年的软件开发工作,在他的博士学位论文完成之际写下了这本“心之所感”。虽然它探讨的是软件工程最常见的内容,但他将亲身所历的感悟写成活泼生动的文字,将软件工程的很多原则和方法融于笑谈之中,让人看得轻松,时有共鸣。尽管很薄,然其内涵不逊于厚近千页的有关教科书。 每次回浙大我都要和林锐相聚,谈学术、论社会,直面人生, “位卑未敢忘忧国”,每每至凌晨。前不久我在某大学计算机系作讲座,最后冒昧谈了几句题外话,其中之一是“学问与明理”。古
2、人云:“读书明理”,意即读书要明白做人的道理。我以为其中的重要内涵,是要有积极的人生观,以贡献社会为己任。这也是我们的共识。林锐曾立誓做一名“真实、正直、优秀的科技人员” 。他在自己困难的时候依然资助数名贫困中学生和大学生;常常躬身拾捡被乱扔于地的废纸、塑料袋,以示后生。这都会使很多的学人汗颜有加。 简言之,林锐对软件工程实践的积极思考、轻快而不失深邃的文笔及其言行,都是出色之处。 正由于此,而不仅因为是同行,我才不惭浅陋,接受他的要求,荣幸地成为本书的第一位读者,并在本来应是名人大家留文的地方谈林说森。 董军 , 2000 年 2 月于 朝夕室 前前 言言 在 60 年代计算机发展初期,程序
3、设计是少数聪明人干的事。他们的智力与技能超群,编写的程序既能控制弱智的计算机,又能让别人看不懂、不会用。那个时期编程就跟捏泥巴一样随心所欲,于是他们很过分地把程序的集合称为软件,以便自己开心或伤心时再把程序捏个面目全非。人们就在这种美滋滋的感觉下热情地编程,结果产生了一堆问题:程序质量低下,错误频出,进度延误,费用剧增。这些问题导致了“软件危机”。 在 1968 年,一群程序员、计算机科学家与工业界人士聚集一起共商对策。通过借鉴传统工业的成功做法,他们主张通过工程化的方法开发软件来解决软件危机,并冠以“软件工程”这一术语。三十年余年来,尽管软件的一些毛病如人类的感冒一样无法根治,但软件的发展速
4、度超过了任何传统工业,期间并未出现真真的软件危机。这的确是前人的先见之明。如今软件工程成了一门学科。 软件工程主要讲述软件开发的道理,基本上是软件实践者的成功经验和失败教训的总结。软件工程的观念、方法、策略和规范都是朴实无华的,平凡之人皆可领会,关键在于运用。我们不可以把软件工程方法看成是诸葛亮的锦囊妙计在出了问题后才打开看看,而应该事先掌握,预料将要出现的问题,控制每个实践环节,并防患于未然。研究软件工程永远做不到理论家那么潇洒:定理证明了,就完事。 我在读大学的十年里有八年从事软件开发,尽管编写了几十万行 C+/C 程序,也经历了若干次小不点儿大的成功和失败,可老感觉只学了些皮毛,心里慌兮
5、兮的。在博士研究生毕业前的半年里,我告戒自己不应该再稀里糊涂地在程序堆里滚爬下去了,于是就面壁反省,做了一阵子木讷的和尚。在“打坐”时,每有心得体会便记录下来,不知不觉凑成了八章经,我就给此经书起名为软件工程思想。 经典的软件工程书籍厚得象砖头,或让人望而却步,或让人看了心事重重。请宽恕我的幼稚,我试图用三个问题:是什么、为什么、怎么办,来解释软件工程的道理。所以本书薄得象饺子皮用来包“思想”这种有味道的“馅”。本书的八章经分别为: 第一章“软件工程基本观念”; 第二章“程序员与程序经理”; 第三章“项目计划与质量管理”; 第四章“可行性分析与需求分析”; 第五章“系统设计”; 第六章“C+
6、面向对象程序设计”; 第七章“测试与改错”; 第八章“维护与再生工程”。 附录“大学十年”可以充当饭后的水果。 我偶尔也担心此书写得太肤浅,内容少得可怜。就象一只鸡在水里扑腾了几下,并不能产生美味的鸡汤。但是如果您化了几分钟时间翻阅本书的任意章节,您马上就愿意再化几个小时一口气读完全书,并且乐得直拍桌子:“好!很好!非常好!” 您可以把这本科技书当小说看,但在看书时请不要吃东西,免得喷了别人或者呛着自己。 如果您买了本书后觉得不值得,我一定赔偿您的损失。 致致 谢谢 本书并不属于我博士学位论文的研究范畴,但却是我读博士学位三年来写的最有意思的作品。 首先要感谢我的导师,浙江大学计算机辅助设计与
7、图形学(CAD&CG )国家重点实验室的石教英教授。在其他师兄弟正儿八经地“攻读”博士学位时,我“不务正业”地开了一家软件公司。当我摔了一个大跟头灰溜溜地回到陌生的实验室时,石老师仍然热情地帮助我“修成正果”。临近毕业,我心中惭愧,三年来我从来都没给石老师干过活,我这个博士生他算是白招了。我很希望大学里多一些象石老师那样开明而大度的导师。 董军博士是本书的第一位读者。我们是“君子之交”却不“淡如水”,除了漆夜长谈科技、艺术、哲学外,还不忘“吃喝玩乐”享受生活。他在品阅的同时完成了审稿工作。 彭小澎好学上进,尽管她执教的是艺术课程,却很想再学点自然科学。她常听我聊侃软件工程,不知不觉成了本书的第
8、二位读者。她看书时只会“哼”“哈”,从未有沉思状,估计啥也没看懂。小澎是个天真未泯的大孩子,和我称兄道弟,给我带来了很多快乐。有一天中午,我们把浙江大学校门口草坪上的垃圾捡得干干净净,俩人无上光荣。我希望小澎早日“荣升”讲师,再恭敬地叫她彭老师。 北京因特国风网络软件公司的周鸿一是个真正的软件高手。他在我开发软件产品失败时给予了最多的帮助,并指正我在软件设计中存在的根深蒂固的方法错误,使我能尽早地逐步改正。我平时能说会道,但在他面前我哑口无言只有听的份,因为他的才华已全方位地超过了我。我真希望多结识象他这样的朋友。 高振华老先生是个糊涂而可爱的民营企业家,我们是忘年交。我把他干的糊涂事(投资软
9、件公司)写进书里,作为可行性分析的案例。高先生给予我经济上的帮助,使我能够在舒适的环境中开展最后一年博士学位论文工作。尽管我读书的工资每月只有 300 元,但日子过得象神仙一样舒服。 浙江大学计算机系的杨孟洲、周昆、曾震宇、杨建、白云、金锋等同学和我合作开发软件,给了我很多技术上的帮助。我对他们深表感谢。 特别感谢父母给我起了很好听的名字。读了十年大学,现在我差不多名副其实了。 林锐,2000 年 2 月 于浙江大学 CAD&CG 国家重点实验室 目 录 第一章 软件工程基本观念 1.1 软件工程的目标与常用模型 1.2 软件开发的基本策略 1.2.1 复用 1.2.2 分而治之 1.2.3
10、优化折衷 1.3 一些不正确的观念 1.4 一些有争议的观念 1.5 小结 第二章 程序员与程序经理 2.1 了解程序员 2.2 了解程序经理 2.3 程序员升为经理后是否还要编程 2.4 经理与技术队伍的建设 2.5 向错误与失败学习 2.6 提高综合素责 2.7 小结 第三章 项目计划与质量管理 3.1 项目计划 3.1.1 知己知彼 3.1.2 进度安排 3.2 零缺陷质量管理的观念 3.2.1 高目标 3.2.2 可执行的规范 3.3 软件的质量因素 3.3.1 正确性与精确性 3.3.2 性能与效率 3.3.3 易用性 3.3.4 可理解性与简洁性 3.3.5 可复用性与可扩充性 3
11、.4 质量检查 3.5 小结 第四章 可行性分析与需求分析 4.1 可行性分析的要素 4.1.1 经济 一、成本收益分析 二、短期长远利益分析 4.1.2 技术 4.1.3 社会环境 4.1.4 人 4.2 可行性分析案例投资软件公司失败的教训 4.2.1 可行性分析案例之一 4.2.2 可行性分析案例之二 4.2.2 可行性分析案例之三 4.3 需求分析为什么困难 4.3.1 客户说不清楚需求 4.3.2 需求自身经常变动 4.3.3 分析人员或客户理解有误 4.4 如何进行需求分析 4.4.1 应该了解什么 4.4.2 通过什么方式去了解 4.5 小结 第五章 系统设计 5.1 体系结构设
12、计 5.1.1 层次结构 一、上下级关系的层次结构 二、顺序相邻关系的层次结构 三、其它的层次结构 5.1.2 Client/Server 结构 5.2 模块设计 5.2.1 信息隐藏 5.2.2 内聚与耦合 5.2.3 封闭开放性 5.3 数据结构与算法设计 5.4 用户界面设计 5.4.1 界面设计中美的需求与导向作用 5.4.2 界面美的内涵 一、界面的合适性 二、界面的风格 三、界面的广义美 5.5 系统设计示例支持协同工作的交互式三维图形软件开发系统 5.5.1 设计背景 5.5.2 通用交互式三维图形软件开发工具 Intra3D 2.0 5.5.2.1 主要模块和功能 5.5.2.
13、2 用户界面设计 5.5.3 支持协同工作的网络通讯开发系统 CNC 1.0 5.5.3.1 CNC 客户程序的 API 设计 5.5.3.2 CNC Server 的设计 5.5.4 应用示例 5.6 小结 第六章 C+ 面向对象程序设计 6.1 C+面向对象程序设计的重要概念 6.1.1 类与对象 6.1.2 继承与组合 6.1.3 虚函数与多态 6.2 良好的编程风格 6.2.1 命名约定 6.2.2 使用断言 6.2.3 new、delete 与指针 6.2.4 使用 const 6.2.5 其它建议 6.3 小结 第七章 测试与改错 7.1 对测试的理解 7.1.1 测试的目的 7.
14、1.2 测试的心理要求 7.1.3 测试的真理 7.1.4 测试与质量的关系 7.2 测试人员的选择 7.2.1 Microsoft 公司的经验教训 7.2.2 测试人员的分工 7.3 测试的主要内容与常用方法 7.3.1 正确性与精确性测试 7.3.2 容错性测试 7.3.3 性能与效率测试 7.3.4 易用性测试 7.3.5 文档测试 7.4 改错 7.5 小结 第八章 维护与再生工程 8.1 软件维护的常识 8.2 维护的代价及其主要因素 8.3 再生工程 8.3.1 重构 8.3.2 逆向工程 8.3.3 前向工程 8.4 小结 参考文献 附录: 大学十年 后记 第一章 软件工程基本观
15、念 本章讲述软件工程的基本观念, 是关于软件工程宏观上的探讨。 如果你是软件公司的老板, 用不着在第一线工作, 那么看这一章就够了。 但你一定要让员工们相信不停地工作是人生最大的快乐,并且让他们把本书看完。 1.1 节讲 述软件 工 程 的目标 和 常 用的软 件 工 程模型 。 1.2 节 讲 述软件开 发 的基本策 略 :“复用” 、 “ 分而治 之” 、 “优化 折衷” , 有 助 于指导 实践 者选择 方法 和产生 新方 法。 1.3节例举一些不正确的观念, 取材于早期软件人员比较幼稚的想法, 初学者可以引以为戒。 1.4节探讨一些有争议的观念。 看完本章, 要树立这样的信念: 软件开
16、发过程中的坎坎坷坷, 仿佛只是人脸的凹凸不平 ,用热水毛巾一把就可抹平。 让我们高举程序主义、 软件工程思想的伟大旗帜, 紧密团结在以Microsoft 为 核心的 软件 公司周 围, 沿着比 尔 盖茨的 生财 之道, 不分 白天黑 夜地 编程, 把建设有中国特色的软件产业的伟大事业全面推向 21 世纪。 1.1 软件工程的目标与常用模型 软件工程的目标是提高软件的质量与生产率, 最终实现软件的工业化生产。 质量是软件需求方最关心的问题, 用户即使不图物美价廉, 也要求个货真价实。 生产率是软件供应方最关心的问题, 老板和员工都想用更少的时间挣更多的钱。 质量与生产率之间有着内在的联系,高生产
17、率必须以质量合格为前提。 如果质量不合格, 对供需双方都是坏事情。 从短期效益看,追求高质量会延长软件开发时间并且增大费用, 似乎降低了生产率。 从长期效益看, 高质量将保证软件开发的全过程更加规范流畅, 大大降低了软件的维护代价, 实质上是提高了生产率, 同时可获得很好的信誉。 质量与生产率之间不存在根本的对立, 好的软件工程方法可以同时提高质量与生产率。 软件供需双方的代表能在餐桌上谈笑风生, 归功于第一线开发人员的辛勤工作。 质量与生产率的提高就指望程序员与程序经理。 对开发人员而言, 如果非得在质量与生产率之间分个主次不可, 那么应该是质量第一, 生产率第二。 这是因为: ( 1) 质
18、 量直接体现在软件的 每段程序中, 高质量自然是开发人员的技术追求, 也是职业道德的要求。 ( 2) 高质量 对所有的用户都有价值, 而高生产率只对开发方有意义。 ( 3) 如果一 开始就追求高生产率, 容易使人急功近利,留下隐患。宁可进度慢些,也要保证每个环节的质量,以图长远利益。 软件的质量因素很多, 如正确性, 性能、 可靠性、 容错性、 易用性、 灵活性、 可扩充性、可理解性、可维护性等等。有些因素相互重叠,有些则相抵触,真要提高质量可不容易啊! 软件工程的主要环节有: 人员管理、 项目管理、 可行性与需求分析、 系 统设计、 程 序 设计、测试、维护等,如图 1.1 所示。 可行性与
19、 需求分析 系统 设计 程序设计测 试 维 护 项目管理 人员管理 图 1.1 软件工程的主要环节 软件工程模型建议用一定的流程将各个环节连接起来,并可用规范的方式操作全过程,如同工厂的生产线。 常见的软件工程模型有: 线性模型 (图 1.2) , 渐 增式模型 (图 1.3) ,螺旋模型,快速原型模型,形式化描述模型等等 Pressmam 1999, Sommerville 1992。 图 1.2 软件工程的线性模型 时间 进度 图 1.3 软件工程的渐增式模型 最早出现的 软件工程模 型是线性模 型(又称瀑 布模型) 。线性模型太理 想化,太单 纯,已不再适合现代的软件开发模式, 几乎被业
20、界抛弃。 偶而被人提起, 都属于被贬对象, 未 被留一丝惋惜 。但我们应 该认识到, “ 线性”是人 们最容易掌 握并能熟练 应用的思想 方法。当人们碰到一个复杂的 “非线性” 问题时, 总是千方百计地将其分解或转化为一系列简单的线性问题, 然后逐个解决。 一个软件系统的整体可能是复杂的, 而单个子程序总是简单的, 可以用线性的方式来实现, 否则干活就太累了。 线性是一种简洁, 简洁就是美。 当我们领会 了线性的精神, 就不要再呆板地套用线性模型的外表, 而应该用活它。 例如渐增式模型实质就是分段的线性模型, 如图 1.3 所示。 螺旋模型则是接连的弯曲了的线性模型。 在其它模型中都能够找到线
21、性模型的影子。 套用固定的模型不是程序员的聪明之举。 比如 “程序设计” 与 “测试” 之间的关系, 习惯上总以为程序设计在先, 测试在后, 如图 1.4( a) 所 示 。 而对于一些复杂的程序, 将测试分为同步测试与总测试更有效,如图 1.4( b) 所示。 程序设计 测 试 程序设计同步测试总测试 可行性与求 分 析需 系统设计程序设计测试维 护 可行性与需求分析系统设计 程序设计测试维护维 护 测 试 程序设计系统 设计 可行性与 需求分析 ( a) ( b) 图 1.4 ( a)程序设计在先测试在后 ( b)测试分为同步测试与总测试 不论是什么软件工程模型, 总是少不了图 1.1 中
22、 的各个环节。 本书擗开具体的软件工程模型, 顺序讲述人员管理、 项目管理、 可行性与需求分析、 系统设计、 程序设计、 测试, 以及维护与再生工程。其中程序设计部分以 C+/C 语言为例 。 1.2 软件开发的基本策略 人们都有自己的世界观和方法论, 能自然而然地运用于生活和工作中。子里的软件工程观念会无形地支配其怎么去做事情。 软件工程三十年的发展,当多的方法, 但这些方法不是严密的理论。 实践人员不应该教条地套用方法,会“选择合 适的方法” 和“产生新 方法” 。有谋 略才会有好就在打闹之际写下了很多心得体会, 被现代人很好地运用于工业和商业。中的三种基本策略: “复 用” 、 “分而
23、治之” 、 “优 化折衷”1.2.1 复用 复用就是指 “利用现成的东西” , 文人称之为 “拿来主义”物体, 也可以是无形的成果。 复用不是人类懒惰的表现而是智慧的表现。承了前人的成果, 不断加以利用、 改进或创新后才会进步。楚祖国远不止 50 岁, 我 们今天享用到的财富还有上下五千年人民的贡献。不进步则就可耻了。 复用的内涵包括了提高质量与生产率两者。 由经验可知,容是成熟的, 只有小部分内容是创新的。 一般地可以相信成熟的东西总是比较可靠的有高质量) , 而大量成熟的工作可以通过复用来快速实现 (即具有高生产率)的人们应该把大部分的时间用在小比例的创新工作上, 而把小部分的时间用在大比
24、例的成熟工作中,这样才能把工作做得又快又好。 把复用的思想用于软件开发,称为软件复用。据统计,世上已有数功能被重写了成千上万次,真是浪费哪。面向对象( Ob“请不要再发明相同的车轮子了” 。 将具有一 定 集成度并 可 以重复使 用 的软件组 成 单元称为软件复用可以表述为:构造新的软件系统可以不必每次从零做起,直接使用已有的软构件,即可组装 (或加以合理修改) 成新的系统。 复用方法合理化并简化了软件开发过程,总的开发工作量与维护代价, 既降低了软件的成本又提高了生产率。是经过反复使用验证的, 自身具有较高的质量。 因此由软构件组成的新系统也具有较高的质量。利用软构件生产应用软件的过程如图
25、1.5 所示 。 软件复用不 仅要使自己 拿来方便, 还要让别人 拿去方便,象方法, Microsoft 公司的 COM 规范 Rogerson 1999,都能很好用。 存在 构件不存在 查询软构件库 定义 所需 构件 集合 应用 软件 系统 分解 图 1.5 利用软构件生产应用软件的过程同 样 , 程序员 脑已经积累了相更重要的是学的战术。几 千年前,我 们的祖先本节讲述软件开发。 。 被复用的对象可以是有形的因为人类总是在继所以当我们欢度国庆时, 要搞 清进步只是应该的,在一 个新系统中, 大部分的 内(即具。 勤 劳 并且聪明1000 亿多行程序,无ject Oriented)学者的口头禅就是软 构 件 (Software Component)。减少 了另一方面, 由于软构件是“拿来拿 去主义” 。面向对地用于实现大规模的软件复用构 件建 造新 软件 创建新构件提取构件