- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
林锐-软件工程思想
展开查看详情
1 .软 件 工 程 思 想 林 锐 著 董 军 审 讲 述 做 软 程 件 序 开 员 发 的 和 道 理
2 . 序 《软件工程思想》讲述“软件开发”和“做程序员”的道理,视野独特, 构 思 新 颖 ,内 容 风 趣 ,不 落 窠 臼 ,令 人 耳 目 一 新 。堪 称 难 得 ,以 至 回 味 无 穷 。 作 者 从 事 了 八 年 的 软 件 开 发 工 作 ,在 他 的 博 士 学 位 论 文 完 成 之 际 写 下 了 这 本“ 心 之 所 感 ”。虽 然 它 探 讨 的 是 软 件 工 程 最 常 见 的 内 容 ,但 他 将 亲 身 所 历 的 感悟写成活泼生动的文字,将软件工程的很多原则和方法融于笑谈之中,让 人 看 得 轻 松 ,时 有 共 鸣 。尽 管 很 薄 ,然 其 内 涵 不 逊 于 厚 近 千 页 的 有 关 教 科 书 。 每 次 回 浙 大 我 都 要 和 林 锐 相 聚 , 谈 学 术 、 论 社 会 , 直 面 人 生 ,“ 位 卑 未 敢 忘 忧 国 ”,每 每 至 凌 晨 。前 不 久 我 在 某 大 学 计 算 机 系 作 讲 座 ,最 后 冒 昧 谈 了 几 句 题 外 话 , 其 中 之 一 是 “ 学 问 与 明 理 ”。 古 人 云 :“ 读 书 明 理 ”, 意 即 读 书 要 明 白做人的道理。我以为其中的重要内涵,是要有积极的人生观,以贡献社会 为己任。这也是我们的共识。林锐曾立誓做一名“真实、正直、优秀的科技 人 员 ”。他 在 自 己 困 难 的 时 候 依 然 资 助 数 名 贫 困 中 学 生 和 大 学 生 ;常 常 躬 身 拾 捡被乱扔于地的废纸、塑料袋,以示后生。这都会使很多的学人汗颜有加。 简 言 之 ,林 锐 对 软 件 工 程 实 践 的 积 极 思 考 、轻 快 而 不 失 深 邃 的 文 笔 及 其 言 行,都是出色之处。 正 由 于 此 ,而 不 仅 因 为 是 同 行 ,我 才 不 惭 浅 陋 ,接 受 他 的 要 求 ,荣 幸 地 成 为本书的第一位读者,并在本来应是名人大家留文的地方谈林说森。 董 军 , 20 00 年 2 月 于 朝夕室
3 . 前 言 在 60 年代计算机发展初期,程序设计是少数聪明人干的事。他们的智力与技能超群, 编写的程序既能控制弱智的计算机,又能让别人看不懂、不会用。那个时期编程就跟捏泥巴 一样随心所欲,于是他们很过分地把程序的集合称为软件,以便自己开心或伤心时再把程序 捏个面目全非。人们就在这种美滋滋的感觉下热情地编程,结果产生了一堆问题:程序质量 低下,错误频出,进度延误,费用剧增……。这些问题导致了“软件危机” 。 在 1968 年,一群程序员、计算机科学家与工业界人士聚集一起共商对策。通过借鉴传 统工业的成功做法,他们主张通过工程化的方法开发软件来解决软件危机,并冠以“软件工 程”这一术语。三十年余年来,尽管软件的一些毛病如人类的感冒一样无法根治,但软件的 发展速度超过了任何传统工业,期间并未出现真真的软件危机。这的确是前人的先见之明。 如今软件工程成了一门学科。 软件工程主要讲述软件开发的道理,基本上是软件实践者的成功经验和失败教训的总 结。软件工程的观念、方法、策略和规范都是朴实无华的,平凡之人皆可领会,关键在于运 用。我们不可以把软件工程方法看成是诸葛亮的锦囊妙计─—在出了问题后才打开看看,而 应该事先掌握,预料将要出现的问题,控制每个实践环节,并防患于未然。研究软件工程永 远做不到理论家那么潇洒:定理证明了,就完事。 我在读大学的十年里有八年从事软件开发,尽管编写了几十万行 C++/C 程序,也经历 了若干次小不点儿大的成功和失败,可老感觉只学了些皮毛,心里慌兮兮的。在博士研究生 毕业前的半年里,我告戒自己不应该再稀里糊涂地在程序堆里滚爬下去了,于是就面壁反省, 做了一阵子木讷的和尚。在“打坐”时,每有心得体会便记录下来,不知不觉凑成了八章经, 我就给此经书起名为《软件工程思想》。 经典的软件工程书籍厚得象砖头,或让人望而却步,或让人看了心事重重。请宽恕我的 幼稚,我试图用三个问题:是什么、为什么、怎么办,来解释软件工程的道理。所以本书薄 得象饺子皮─—用来包“思想”这种有味道的“馅”。本书的八章经分别为: 第一章“软件工程基本观念”; 第二章“程序员与程序经理”; 第三章“项目计划与质量管理”; 第四章“可行性分析与需求分析”; 第五章“系统设计” ; 第六章“C++ 面向对象程序设计”; 第七章“测试与改错” ; 第八章“维护与再生工程” 。 附录“大学十年”可以充当饭后的水果。 我偶尔也担心此书写得太肤浅,内容少得可怜。就象一只鸡在水里扑腾了几下,并不能 产生美味的鸡汤。但是如果您化了几分钟时间翻阅本书的任意章节,您马上就愿意再化几个 小时一口气读完全书,并且乐得直拍桌子: “好!很好!非常好! ” 您可以把这本科技书当小说看,但在看书时请不要吃东西,免得喷了别人或者呛着自己。 如果您买了本书后觉得不值得,我一定赔偿您的损失。
4 . 致 谢 本书并不属于我博士学位论文的研究范畴,但却是我读博士学位三年来写的最有意思的 作品。 首先要感谢我的导师,浙江大学计算机辅助设计与图形学(CAD&CG)国家重点实验 室的石教英教授。在其他师兄弟正儿八经地“攻读”博士学位时,我“不务正业”地开了一 家软件公司。当我摔了一个大跟头灰溜溜地回到陌生的实验室时,石老师仍然热情地帮助我 “修成正果”。临近毕业,我心中惭愧,三年来我从来都没给石老师干过活,我这个博士生 他算是白招了。我很希望大学里多一些象石老师那样开明而大度的导师。 董军博士是本书的第一位读者。我们是“君子之交”却不“淡如水”,除了漆夜长谈科 技、艺术、哲学外,还不忘“吃喝玩乐”享受生活。他在品阅的同时完成了审稿工作。 北京因特国风网络软件公司的周鸿一是个真正的软件高手。他在我开发软件产品失败时 给予了最多的帮助,并指正我在软件设计中存在的根深蒂固的方法错误,使我能尽早地逐步 改正。我平时能说会道,但在他面前我哑口无言只有听的份,因为他的才华已全方位地超过 了我。我真希望多结识象他这样的朋友。 高振华老先生是个糊涂而可爱的民营企业家,我们是忘年交。我把他干的糊涂事(投资 软件公司)写进书里,作为可行性分析的案例。高先生给予我经济上的帮助,使我能够在舒 适的环境中开展最后一年博士学位论文工作。尽管我读书的工资每月只有 300 元,但日子过 得象神仙一样舒服。 浙江大学计算机系的杨孟洲、周昆、曾震宇、杨建、白云、金锋等同学和我合作开发软 件,给了我很多技术上的帮助。我对他们深表感谢。 特别感谢父母给我起了很好听的名字。读了十年大学,现在我差不多名副其实了。 林锐,2000 年 2 月 于浙江大学 CAD&CG 国家重点实验室
5 . 目 录 第一章 软件工程基本观念 1.1 软件工程的目标与常用模型 1.2 软件开发的基本策略 1.2.1 复用 1.2.2 分而治之 1.2.3 优化——折衷 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.4 质量检查 3.5 小结 第四章 可行性分析与需求分析 4.1 可行性分析的要素 4.1.1 经济 一、成本——收益分析 二、短期——长远利益分析 4.1.2 技术
6 . 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 体系结构设计 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.2 用户界面设计 5.5.3 支持协同工作的网络通讯开发系统 CNC 1.0 5.5.3.1 CNC 客户程序的 API 设计 5.5.3.2 CNC Server 的设计 5.5.4 应用示例 5.6 小结
7 .第六章 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.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 小结 参考文献 附录: 大学十年 后记
8 . 第一章 软件工程基本观念 本章讲述软件工程的基本观念,是关于软件工程宏观上的探讨。如果你是软件公司的老 板,用不着在第一线工作,那么看这一章就够了。但你一定要让员工们相信不停地工作是人 生最大的快乐,并且让他们把本书看完。 1.1 节讲述软件工程的目标和常用的软件工程模型。1.2 节讲述软件开发的基本策略: “复 用”、 “分而治之”、 “优化——折衷”,有助于指导实践者选择方法和产生新方法。1.3 节例举 一些不正确的观念,取材于早期软件人员比较幼稚的想法,初学者可以引以为戒。1.4 节探 讨一些有争议的观念。 看完本章,要树立这样的信念:软件开发过程中的坎坎坷坷,仿佛只是人脸的凹凸不平, 用热水毛巾一把就可抹平。让我们高举程序主义、软件工程思想的伟大旗帜,紧密团结在以 Microsoft 为核心的软件公司周围,沿着比尔·盖茨的生财之道,不分白天黑夜地编程,把 建设有中国特色的软件产业的伟大事业全面推向 21 世纪。 1.1 软件工程的目标与常用模型 软件工程的目标是提高软件的质量与生产率,最终实现软件的工业化生产。质量是软件 需求方最关心的问题,用户即使不图物美价廉,也要求个货真价实。生产率是软件供应方最 关心的问题,老板和员工都想用更少的时间挣更多的钱。质量与生产率之间有着内在的联系, 高生产率必须以质量合格为前提。如果质量不合格,对供需双方都是坏事情。从短期效益看, 追求高质量会延长软件开发时间并且增大费用,似乎降低了生产率。从长期效益看,高质量 将保证软件开发的全过程更加规范流畅,大大降低了软件的维护代价,实质上是提高了生产 率,同时可获得很好的信誉。质量与生产率之间不存在根本的对立,好的软件工程方法可以 同时提高质量与生产率。 软件供需双方的代表能在餐桌上谈笑风生,归功于第一线开发人员的辛勤工作。质量与 生产率的提高就指望程序员与程序经理。对开发人员而言,如果非得在质量与生产率之间分 个主次不可,那么应该是质量第一,生产率第二。这是因为:(1)质量直接体现在软件的每 段程序中,高质量自然是开发人员的技术追求,也是职业道德的要求。 (2)高质量对所有的 用户都有价值,而高生产率只对开发方有意义。(3)如果一开始就追求高生产率,容易使人 急功近利,留下隐患。宁可进度慢些,也要保证每个环节的质量,以图长远利益。 软件的质量因素很多,如正确性,性能、可靠性、容错性、易用性、灵活性、可扩充性、 可理解性、可维护性等等。有些因素相互重叠,有些则相抵触,真要提高质量可不容易啊! 软件工程的主要环节有:人员管理、项目管理、可行性与需求分析、系统设计、程序设 计、测试、维护等,如图 1.1 所示。
9 . 人员管理 项目管理 可行性与 系统 程序 测 维 需求分析 设计 设计 试 护 图 1.1 软件工程的主要环节 软件工程模型建议用一定的流程将各个环节连接起来,并可用规范的方式操作全过程, 如同工厂的生产线。常见的软件工程模型有:线性模型(图 1.2),渐增式模型(图 1.3) ,螺 旋模型,快速原型模型,形式化描述模型等等 [Pressmam 1999, Sommerville 1992]。 可行性与 系统 程序 测 维 需求分析 设计 设计 试 护 图 1.2 软件工程的线性模型 时间 可行性与 系统 程序 测 维 需求分析 设计 设计 试 护 可行性与 系统 程序 测 维 需求分析 设计 设计 试 护 进度 图 1.3 软件工程的渐增式模型 最早出现的软件工程模型是线性模型(又称瀑布模型)。线性模型太理想化,太单纯, 已不再适合现代的软件开发模式,几乎被业界抛弃。偶而被人提起,都属于被贬对象,未被 留一丝惋惜。但我们应该认识到,“线性”是人们最容易掌握并能熟练应用的思想方法。当 人们碰到一个复杂的“非线性”问题时,总是千方百计地将其分解或转化为一系列简单的线 性问题,然后逐个解决。一个软件系统的整体可能是复杂的,而单个子程序总是简单的,可 以用线性的方式来实现,否则干活就太累了。线性是一种简洁,简洁就是美。当我们领会了 线性的精神,就不要再呆板地套用线性模型的外表,而应该用活它。例如渐增式模型实质就 是分段的线性模型,如图 1.3 所示。螺旋模型则是接连的弯曲了的线性模型。在其它模型中 都能够找到线性模型的影子。 套用固定的模型不是程序员的聪明之举。比如“程序设计”与“测试”之间的关系,习
10 .惯上总以为程序设计在先,测试在后,如图 1.4(a)所示。而对于一些复杂的程序,将测试 分为同步测试与总测试更有效,如图 1.4(b)所示。 程序设计 程序设计 测 试 总测试 同步测试 (a) (b) 图 1.4 (a)程序设计在先测试在后 (b)测试分为同步测试与总测试 不论是什么软件工程模型,总是少不了图 1.1 中的各个环节。本书擗开具体的软件工程 模型,顺序讲述人员管理、项目管理、可行性与需求分析、系统设计、程序设计、测试,以 及维护与再生工程。其中程序设计部分以 C++/C 语言为例。 1.2 软件开发的基本策略 人们都有自己的世界观和方法论,能自然而然地运用于生活和工作中。同样,程序员脑 子里的软件工程观念会无形地支配其怎么去做事情。软件工程三十年的发展,已经积累了相 当多的方法,但这些方法不是严密的理论。实践人员不应该教条地套用方法,更重要的是学 会“选择合适的方法”和“产生新方法”。有谋略才会有好的战术。几千年前,我们的祖先 就在打闹之际写下了很多心得体会,被现代人很好地运用于工业和商业。本节讲述软件开发 中的三种基本策略:“复用”、 “分而治之”、 “优化——折衷”。 1.2.1 复用 复用就是指“利用现成的东西”,文人称之为“拿来主义”。被复用的对象可以是有形的 物体,也可以是无形的成果。复用不是人类懒惰的表现而是智慧的表现。因为人类总是在继 承了前人的成果,不断加以利用、改进或创新后才会进步。所以当我们欢度国庆时,要搞清 楚祖国远不止 50 岁,我们今天享用到的财富还有上下五千年人民的贡献。进步只是应该的, 不进步则就可耻了。 复用的内涵包括了提高质量与生产率两者。由经验可知,在一个新系统中,大部分的内 容是成熟的,只有小部分内容是创新的。一般地可以相信成熟的东西总是比较可靠的(即具 有高质量),而大量成熟的工作可以通过复用来快速实现(即具有高生产率)。勤劳并且聪明 的人们应该把大部分的时间用在小比例的创新工作上,而把小部分的时间用在大比例的成熟 工作中,这样才能把工作做得又快又好。 把复用的思想用于软件开发,称为软件复用。据统计,世上已有 1000 亿多行程序,无 数功能被重写了成千上万次,真是浪费哪。面向对象(Object Oriented)学者的口头禅就是 “请不要再发明相同的车轮子了” 。 将具有一定集成度并可以重复使用的软件组成单元称为软构件(Software Component)。 软件复用可以表述为:构造新的软件系统可以不必每次从零做起,直接使用已有的软构件, 即可组装(或加以合理修改)成新的系统。复用方法合理化并简化了软件开发过程,减少了 总的开发工作量与维护代价,既降低了软件的成本又提高了生产率。另一方面,由于软构件 是经过反复使用验证的,自身具有较高的质量。因此由软构件组成的新系统也具有较高的质 量。利用软构件生产应用软件的过程如图 1.5 所示。
11 . 软件复用不仅要使自己拿来方便,还要让别人拿去方便,是“拿来拿去主义” 。面向对 象方法,Microsoft 公司的 COM 规范 [Rogerson 1999],都能很好地用于实现大规模的软件复 用。 应用 定义 用构 软件 所需 查询软构 存在 提取构件 件建 系统 构件 件库 造新 分解 集合 软件 创建新构件 构件不存在 图 1.5 利用软构件生产应用软件的过程 1.2.2 分而治之 分而治之是指把一个复杂的问题分解成若干个简单的问题,然后逐个解决。这种朴素的 思想来源于人们生活与工作的经验,完全适合于技术领域。软件人员在执行分而治之的时候, 应该着重考虑:复杂问题分解后,每个问题能否用程序实现?所有程序最终能否集成为一个 软件系统并有效解决原始的复杂问题? 解决原始问题 软件 复杂问题 系统 子问题 1 程序 1 分解 集成 子问题 2 程序 2 子问题 n 程序 n 图 1.6 软件领域的分而治之策略 图 1.6 表示了软件领域的分而治之策略。诸如软件的体系结构设计、模块化设计都是分 而治之的具体表现。软件的分而治之不可以“硬分硬治” 。不像为了吃一个西瓜或是一只鸡, 挥刀斩成 n 块,再把每块塞进嘴里粉碎搅拌,然后交由胃肠来消化吸收,象征复杂问题的西 瓜或是鸡也就此消失了。 1.2.3 优化——折衷 软件的优化是指优化软件的各个质量因素,如提高运行速度, 提高对内存资源的利用率, 使用户界面更加友好,使三维图形的真实感更强等等。想做好优化工作,首先要让开发人员 都有正确的认识:优化工作不是可有可无的事情,而是必须要做的事情。当优化工作成为一 种责任时,程序员才会不断改进软件中的算法,数据结构和程序组织,从而提高软件质量。 著名的 3D 游戏软件 Quake,能够在 PC 机上实时地绘制高度真实感的复杂场景。Quake 的开发者能把很多成熟的图形技术发挥到极致,例如把 Bresenham 画线、多边形裁剪、树遍 历等算法的速度提高近一个数量级。我第一次看到 Quake 时不仅感到震动,而且深受打击。 这个 PC 游戏软件的技术水平已经远胜于我所见识到的国内领先的图形学相关科研成果。这
12 .对我们日益盛行的点到完止的研发工作真是莫大的讽刺。所以当我们开发的软件表现出很多 不可救药的病症时,不要怨机器差。真的是我们自己没有把工作做好,写不好字却嫌笔钝。 就假设我们经过思想教育后,精神抖擞,随时准备为优化工作干上六天七夜。但愿意做 并不意味着就能把事情做好。优化工作的复杂之处是很多目标存在千丝万缕的关系,可谓数 不清理还乱。当不能够使所有的目标都得到优化时,就需要“折衷”策略。 软件中的折衷策略是指通过协调各个质量因素,实现整体质量的最优。就象党支部副书 记扮演和事佬的角色:“…为了使整个组织具有最好的战斗力,我们要重用几个人,照顾一 些人,在万不得已的情况下委屈一批人”。 软件折衷的重要原则是不能使某一方损失关键的职能,更不可以象“舍鱼而取熊掌”那 样抛弃一方。例如 3D 动画软件的瓶颈通常是速度,但如果为了提高速度而在程序中取消光 照明计算,那么场景就会丧失真实感,3D 动画也就不再有意义了(如果人类全是色盲,计 算机图形学将变得异常简单)。 人都有惰性,如果允许滥用折衷的话,那么一当碰到困难,人们就会用拆东墙补西墙的 方式去折衷,不再下苦功去做有意义的优化。所以我们有必要为折衷制定严正的立场:在保 证其它因素不差的前提下,使某些因素变得更好。 下面让我们用“优化——折衷”的策略解决“鱼和熊掌不可得兼”的难题。 问题提出:假设鱼每千克 10 元,熊掌每千克一万元。有个倔脾气的人只有 20 元钱,非 得要吃上一公斤美妙的“熊掌烧鱼” ,怎么办? 解决方案:化 9 元 9 角 9 分钱买 999 克鱼肉,化 10 元钱买 1 克熊掌肉,可做一道“熊 掌戏鱼”菜。剩下的那一分钱还可建立奖励基金。 1.3 一些不正确的观念 本节例举并分析一些不正确的软件工程观念,可帮助初学者少犯相似的错误。 观念之一:我们拥有一套讲述如何开发软件的书籍,书中充满了标准与示例,可以帮助我们 解决软件开发中遇到的任何问题。 客观情况:好的参考书无疑能指导我们的工作。充分利用书籍中的方法、技术和技巧,可以 有效地解决软件开发中大量常见的问题。但实践者并不能因此依赖于书籍,这是因为:(1) 现实的工作中,由于条件千差万别,即使是相当成熟的软件工程规范,常常也无法套用。 (2) 软件技术日新月异,没有哪一种软件标准能长盛不衰。祖传秘方在某些领域很吃香,而在软 件领域则意味着落后。 观念之二:我们拥有最好的开发工具、最好的计算机,一定能做出优秀的软件。 客观情况:良好的开发环境只是产出成果的必要条件,而不是充分条件。如果拥有好环境的 是一群庸人,难保他们不干出南辕北辙的事情。 观念之三:如果我们落后于计划,可以增加更多的程序员来解决。 客观情况:软件开发不同于传统的农业生产,人多不见得力量大。如果给落后于计划的项目 增添新手,可能会更加延误项目。因为:(1)新手会产生很多新的错误,使项目混乱。(2) 老手向新手解释工作以及交流思想都要花费时间,使实际开发时间更少。所以科学的项目计 划很重要,不在乎计划能提前多少,重在恰如其分。如果用“大跃进”的方式奔向共产主义, 只会产生倒退的后果。
13 .观念之四:既然需求分析很困难,不管三七二十一先把软件做了再说,反正软件是灵活的, 随时可以修改。 客观情况:对需求把握得越准确,软件的修修补补就越少。有些需求在一开始时很难确定, 在开发过程中要不断地加以改正。软件修改越早代价越少,修改越晚代价越大,就跟治病一 样道理。 1.4 一些有争议的观念 本节探讨一些有争议的观念,目的不在于得出“正确”或“错误”的评断,而在于争议 会激发更多理性的思考。 争议之一:如果软件运行较慢,是换一台更快的计算机,还是设计一种更快的算法? 作者观点:如果开发软件的目的是为了学习或是研究,那么应该设计一种更快的算法。如果 该软件已经用于商业,则需谨慎考虑:若换一台更快的计算机能解决问题,则是最快的解决 方案。改进算法虽然可以从根本上提高软件的运行速度,但可能引入错误以及延误进程。技 术狂毫无疑问会选择后者,因为他们觉得放弃任何可以优化的机会就等于犯罪。 类似的争议还有:是买现成的程序,还是彻底自己开发?技术人员和商业人士常常会有 不同的选择。 争议之二:有最好的软件工程方法,最好的编程语言吗? 作者观点:在软件领域永远没有最好的,只有更好的。能解决问题的都是好方法或是好语言。 程序员在最初学习 Basic、Fortran、 Pascal、C、C++等语言时会感觉一个比一个好,不免有 喜新厌旧之举。而如今的 Visual Basic、Delphi、Visual C++、Java 等语言各有所长,真的难 分优劣。开发人员应该根据客观条件,选择自己熟悉的方法和语言,才能保证合格的质量与 生产率。 程序设计是自由与快乐的事情,不要发誓忠于某某主义而自寻烦恼。 争议之三:编程时是否应该多使用技巧? 作者观点:就软件开发而言,技巧的优点在于能另辟蹊径地解决一些问题,缺点是技巧并不 为人熟知。若在程序中用太多的技巧,可能会留下隐患,别人也难以理解程序。鉴于一个局 部的优点对整个系统而言是微不足道的,而一个错误则可能是致命的。作者建议用自然的方 式编程,少用技巧。 《狼三则》的故事告诉我们“失败的技巧通常是技俩”。当我们在编程时无法判断是用 了技巧还是用了技俩,那就少用。《卖油翁》的故事又告诉我们“熟能生巧” ,表明技巧是自 然而然产生的,而不是卖弄出来的。卖油翁的绝技是可到中央电视台表演的,而他老人家却 谦虚地说:“没啥没啥,用熟了而已”。 争议之四:软件中的错误是否可按严重程度分等级? 作者观点:在定量分析时,可以将错误分等级,以便于管理。微软的一些开发小组将错误分 成四个等级 [Cusumano 1996],如表 1.1 所示。
14 .一级严重:错误导致软件崩溃。 二级严重:错误导致一个特性不能运行并且没有替代方案。 三级严重:错误导致一个特性不能运行但有替代方案。 四级严重:错误是表面化的或是微小的。 表 1.1 错误的四个等级 上述分类是非常技术性的,并不是普适的。假设某个财务软件有两个错误:错误 A 使 该软件死掉,错误 B 导致工资计算错误。按表 1.1 分类,错误 A 属一级严重,错误 B 属二 级严重。但事实上 B 要比 A 严重。工资算多了或者算少了,将会使老板或员工遭受经济损 失。而错误 A 只使操作员感到厌烦,并没有造成经济损失。另一个示例是操作手册写错, 按表 1.1 分类则属四级严重,但这种错误可能导致机毁人亡。 开发人员应该意识到:所有的错误都是严重的,不存在微不足道的错误。这样才能少犯 错误。 1.5 小 结 软件工程学科发展到今天,已经有了很多方法和规范,学之不尽。本章只在宏观上讨论 了软件工程的一些思想,更具体的内容将在后面的章节论述。无论是什么好方法,贵在理解 与灵活运用,而不可当成灵丹妙药,不象“吃了脑黄金或脑白金,就能使一亿人先聪明起来” 。
15 . 第二章 程序员与程序经理 工作在第一线的软件开发人员是程序员和程序经理,他们决定着软件的命运。良好的程 序员队伍和出色的管理是软件项目成功的必要条件。管理不是管制,不是去卡住人家的脖子, 因为程序员不是一群野鸭子。管理的目的是让大家一起把工作做好,并且让各人获得各自的 快乐和满足。当一个组织被出色地领导时,雇员甚至不知道他们已被领导。在项目完成时, 他们会自豪地说: “看看我们通过努力取得的成绩吧”。所以管理者不能老惦记着自己是一个 官,而应时刻意识到自己是责任的主要承担者。 我们经常会听到有经理头衔的人在高谈阔论: “编程我不会,做个项目还不 easy?派个 人去搞系统分析,回头再叫几个程序员把需求译成程序,不就 OK 了吗?” 不懂英语的人准以为 easy 和 OK 是贬义词。要让软件项目失败很容易,只要符合下列 条件之一即可: (1)项目经理对软件一无所知; (2)技术负责人对编程不感兴趣; (3)真真编写代码的程序员是临时雇用的。 如果上述三个条件同时具备,就请放心失败好了。 让我们少幻想自己是比尔·盖茨,先当好程序员和程序经理再说。 2.1 了 解 程 序 员 早期的程序员干活能从软件直通硬件,个个生猛无比。又因他们的作息时间、言行举止 与常人不太一样,久而久之就给人们留下了“神秘”、 “孤僻”的印象。如今软件行业被炒得 热火朝天,有能耐的程序员即便躲在大山岙的军工厂里也能被挖出来。而更多原本不是程序 员的人操起几本“速成”、 “二十一天通”等书籍也加入了这个行业。现在国内号称有上百万 程序员,这支大军鱼龙混杂,已搞不清那些是正规军,那些是民兵游击队了。 真正的程序员都有如下秉性: 一、诚实 程序员在学习与工作期间几乎天天与机器打交道,压根就没有受欺骗或欺骗人的机会。 勤奋的程序员在调试无穷多的程序 Bug 时,已经深深地接受了“诚实”的教育。不诚实的 人,他肯定不想做、也做不好程序员。 有一名市场营销员和一名程序员都在新闻发布会上发言,将一项新技术的消息公布于 众。 市场营销员说:“这项技术比电话、晶体管和原子弹三项发明加起来对世界文明的影响 都要大。” 程序员说:“这项技术在有限的领域内,在有限的程度上,解决了一些技术性的问题。” 看来为了让我们的民族更加诚实,学电脑真的要从娃娃抓起。 二、简单——实用主义 有人问一个数学家,一个物理学家和一名程序员: “一个盒子有几个面?” 数学家回答说:“有六个面,因为盒子是长方体。 ” 物理学家回答说:“有 12 个面,分为 6 个外表面和 6 个内表面 。 ” 程序员回答说:“只有两个面,里面放电路板和硬盘,外面放显示器和键盘。”
16 . 目前即使最先进的计算机也不具备智能,程序员的基本工作就是把复杂的问题转化为计 算机能处理的简单的程序。如果一个问题复杂到连程序员自己都不能理解,他就无法编出程 序让更笨的计算机来处理。所以程序员信奉“简单——实用”主义。 也有不少做计算机“学问”的人颠倒行事。本来几句话、几行程序就能说明白的事,非 得要抬高到理论创新的程度,写成玄乎的文章去评教授或者弄个博士学位。所幸在第一线工 作的程序员大多是实干的。 三、爱憎分明 程序员大都喜欢技术挑战,不喜欢搞测试与维护。高水平的程序员喜欢与高水平的程序 员一起工作,因为他们怕“与臭棋佬下棋,棋越下越臭”。程序员大都厌恶拉帮结派、耍政 治手腕。不信,数一数你认识的程序员,有几个是党派人士? 四、工作单调但不乏味 有人问编程大师:“程序设计的真正含义是什么 ?” 大师回答说: “饿了的时候就吃,困的时候就睡,只要时机恰当就进行程序设计。” 其实程序员的生活和工作已融为一体,尽管单调却不乏味,还能独享孤独。有诗为证: 我编程三日 两耳不闻人声 只有硬盘在歌唱 结论:优秀的程序员没有理由不让人喜欢,他们远比怪僻来得可爱。 2.2 了 解 程 序 经 理 这里程序经理是指一支程序员队伍的领导者,不管他的职务是开发组长,项目经理,还 是部门经理。程序经理是技术性的基层或中层干部,是软件企业得以发展的生力军。程序经 理的选拔是不容草率的事。不象有些事业单位,只要政治口号喊得勤快、能左右逢缘不犯错 误就可混个领导当当。也不象一些官僚机构,只有两个人的办公室也要设正主任和副主任。 如果碰巧正主任姓傅,副主任姓郑,还会斗个没完没了。 在一个管理混乱的软件公司里,如果某个程序员能大喊大叫并且干劲十足,那他就能成 为一名程序经理。微软公司在选择经理人员时,总是把他们的技术知识和运用技术去赚钱的 能力放在首位。程序经理一般就是程序员队伍中最聪明的那个家伙。比尔·盖茨曾这样描述 聪明人[Cusumano1996]: 聪明人一定反应敏捷,善于接受新事物。他能迅速进入一个新领域,给你一个头头是道 的解释。他提出的问题往往一针见血、击中要害。他能及时掌握所学知识,并且博闻强 记,他能把本来认为互不相干的领域联系在一起使问题得到解决。他富有创新精神与合 作精神…… 好的程序经理应该具备以下几个条件: 一、技术水平是程序员队伍中的最高级别 每个程序员骨子里头都有一股傲气,如果你不能技压群雄,他们就不会听你指挥。一个 技术水平较差的人被任命为程序经理真是个悲剧,就象一个略有权势的太监,表面上有人对 他点头哈腰,背后却被人鄙视。 二、能做最多且最难的工作 程序经理编程要快且好。别人要干一天的活,他半天就能做完,这样才会有精力去搞管 理。程序经理应负责系统分析、系统设计这类最难的开发工作,并指导不同水平的程序员把
17 .各自的工作做好。如果人手不够,程序经理要能同时干几个人的活。 三、有人格魅力 软件开发是智力创作过程,你不能指望仅通过执行规章制度来产生好的作品。很多软件 公司的程序经理都不是管理专业出身的,他们也不可能为了搞好管理而成天玩弄心机。技术 出色的程序经理一般少有心术不正的,所以管理的重点应是“以身作则”、“公正待人” 。如 果程序经理在上班时趴在桌上睡觉,其他程序员也会这样干。如果程序经理发现有两个程序 员趴在机器旁睡觉,不能只对其中一个大声吼叫:“你一编程就想睡觉,看看人家,在睡觉 时都想着编程。” 如果管理者没有人格魅力,就没有人信服你,团队就不会有凝聚力,乌合之众不可能开 发出优秀的软件。 结论:一个有活力的软件公司的各级经理都不会这样感叹,“因为我啥也不会干,所以 只好当领导。 ” 2.3 程序员升为经理后是否还要编程 让我们先看看 Microsoft 公司的系统软件部门与应用软件部门的领导是怎样看待这个问 题的[Cusumano1996]。Windows NT 3.0 项目的软件经理娄·帕雷罗里让他手下的经理们像他 一样每天花一半的时间编写代码: 我在组内制定了许多规则,其中最重要的一条是每个人都得编程,谁也别想坐在那儿发 号施令……我发现管理者很容易失去目标,他们总是无法认识到问题的本质并且反应迟 缓。如果你始终不放弃编写代码,你就能对项目的进展情况了如指掌,及时发现并解决 问题……我大概每天花一半的时间编写代码并寻找项目的缺陷。 作为应用软件领域的经理,克里斯·彼得斯也持同样的看法。在他任 Word 项目总经理 时就认为: 在一些大公司内部,各部门经理把具体操作的层次向下移。你一旦当上开发部门经理, 很快就会以自己身居高位、日理万机为由放弃编程;同样地,开发小组的组长会以自己重任 在肩而不愿编程;至于程序员也会觉得自己十分繁忙、分身无术而不再多编写程序。虽然我 是 270 名员工的领导,似乎不再需要做什么具体的工作了,但我还是为 Word 新版本编写了 一个特性。 程序员升为经理后一定要编程,这个道理已经说得很清楚了。最怕的是“虚心接受,坚 决不做”;或者仅是做个样子,每天花一分钟时间编程,编译器还没运行完就关掉了。 2.4 经理与技术队伍的建设 如果是经营一个加工厂或一个饭店,经理们可以不必懂技术。因为他们的常识,以及通 过耳闻目睹或者咨询都能解决实践中的问题。在软件领域,技术的力量是无穷的,一天之内 就可使整个产业发生巨变。也许你在商业上很精明,但无法保证自己在技术浪潮中安然无恙。 软件公司的各级经理最好既精通技术又懂管理。
18 . 一个出色的领导,加上一支技术过硬的队伍,才有可能创造业绩。不能光指望请来孙子 或诸葛亮当教练,就能让弱不禁风的男足去捧世界杯。不少人总喜欢自吹中国人很聪明,最 适合搞软件开发。可至今也没有做出几个很光彩的软件来,这与十三亿人口不呼应啊。新中 国历来喜欢与可怜的印度相比较来展现丰富多彩的优越性,可是软件产业没法与人家比。工 作在第一线的程序员与程序经理应该意识到:好兵好将都不是天生的,是后天练出来的;既 要学会冷静地分析问题,又要充满激情地去工作。 软件公司总希望能物色到既精通技术又善长商业的优秀人才做经理。但已经出名了的优 秀人才难以请到,也难以留住。所以把公司中的普通员工培养成为优秀人才是重要的举措。 公司的老板不要对程序员抱有偏见,以为他们只配与机器打交道。一个高水平的程序员既然 能学好数字逻辑,能理得清楚软件中很多象“嵌套”这类“鸡生蛋并且蛋又生了鸡”的错综 复杂的关系,从理论上讲当个县长也不成问题。 现在很多女士不会烧菜,却能把菜的营养讲得头头是道。虽然这是个值得哀叹的社会问 题,但我们应该有信心期待:如果她们非得天天烧菜不可,那么不久就能把菜烧得又好吃又 有营养。许多程序员不懂商业,不是智力上的原因,主要是个人兴趣和环境所致。软件公司 的老板应该这样鼓励有灵气的员工: “你能把技术做得那么棒,还怕搞不好管理?放心干吧!” 的确,很多技术人员是在工作中领悟如何管理的,他们经过挫折与磨练,逐渐升为组长、项 目经理,乃至成为公司重要的决策者。 优秀的程序员喜欢与优秀的程序员一起工作,这是一种理想的愿望。一个普通的软件公 司不可能有非常多的优秀程序员,即便有,他们也不可能天天聚在一起干同一件事并且和睦 得无法形容。中国自封建社会起就有喜好内斗的风俗习惯,几千年下来早已渗透到社会各个 角落,那怕黄河水流断了,估计这民风也会延袭下去。要使程序员队伍稳健,必须有合理的 等级制度来维护。等级制度并不限制自由和民主,它能让自以为聪明绝顶、谁也不服的人们 懂得如何合作与奋斗。就象有了一架梯子,每个人才有机会爬上墙头摘下那向往已久的野花。 当梯子散成一堆木棍时,只可能造就几个卖炭翁。 下面我们尝试着建立一个程序员队伍的等级制度。 把技术水平分为四级,第一级最低,第四级最高。第一级技术水平的程序员主要考核编 程基本功,要求质量合格(他们主要来自刚毕业的大学生)。第二级技术水平的程序员编程 质量要高,做过几个软件项目,有数年的工作经验,并能指导新手的工作。第三级技术水平 的程序员主要考核系统分析与系统设计的能力,要求其技术有足够的深度和广度。第四级技 术水平的程序员是成功的软件产品的设计师,他不仅技术超群,并且能使技术转化为有价值 的商品。 把管理(这里仅指软件业务的管理,不考虑行政事务)水平也分成四级。第零级最低, 第三级最高。第零级管理水平的人没有管理职务,就是普通员工。第一级管理水平的人是开 发小组的组长,可带领几名程序员工作。第二级管理水平的人是项目经理。第三级管理水平 的人决定某些产品是否要开发,以及如何去占领市场。 每个程序员都有明确的技术级别和管理级别。技术级别与管理级别有一定的联系。一般 地,第一级技术水平的人只能做普通员工;第二级技术水平的人可以当一名组长;第三级技 术水平的人可以当一名项目经理;第四级技术水平的人可成为公司产品的决策者。如图 2.1 所示。本书作者目前的技术水平当属第二级,管理水平符合组长的要求。作者在读中学和大 学时就曾美滋滋地当过课代表,也就是组长级别。
19 . 技术级别 管理级别 四级 决策者 三级 项目经理 二级 开发组长 一级 普通员工 图 2.1 技术级别与管理级别 2.5 向错误与失败学习 不管是生活或工作,人们都应该向错误与失败学习,目的是让我们在短暂的健康年华中 少犯错误、少失败,多做几件正确的对社会有贡献的事。 导致软件项目失败的因素很多,如果不去找借口的话,就会发现错误的根源在自己身上: 知识贫乏、才能低下、经验不足、骄傲自负……。我们必须正视自身的不足与缺点,才会学 到经验教训。可人们常有太多的虚荣,为了克服心理障碍,白白浪费了很多本该用于创造的 精力。 假设犯错误的人是诚实的并且是勤奋的。他愿意不带虚荣地改进自己。当这个人突然面 对失败时,可能觉得自己一无是处,也许会不知所措,也许会病急乱投医。程序员都有一种 共同的体会:在调试程序时,时常碰到只有十几行的程序竟会产生上百个编译错误;最后发 现这么多的错误其实是由某一行程序错误引发的。当我们在工作中碰到挫折时,先要冷静地 分析问题(事出有因哪),找出问题的内因与外因。内因是最主要的,应该予以最先解决。 前几年,中国出现了一个叫“法轮功”的邪教,教徒达数百万之多,人民群众深受其害。 不久前,全国的主要媒体对“法轮功”进行连续数月的声讨与揭露。目睹了很多受害人的哭 诉后,相信人们能够明白“法轮功”是邪恶的、反动的。但在愤怒与心痛之余,我们不禁要 反思:为什么那么多人轻信邪教?人们是否接受了教训? 在电视上看到很多人的确作了深刻的检讨:“我真是后悔啊,跟错了李洪志(法轮功的 头头)这个坏蛋,我对不起社会……。以后我一定要听党组织的话,党叫我干什么我就干什 么,决不上坏人的当。” 我觉得这些受害人一点都没有醒悟:他只知道法轮功是个邪教,并不知道自己为什么信 了邪教。有些事情只要用脑袋去想一想就能分辨是非,可人们就是不去思考,却渴望能跟对 “福星”,甘愿把自己的脑袋拴在别人的裤带上。难道这就是人民的纯朴与可爱吗?回顾一 下历史,在“文革”时期,亿万人民跟着合法的党组织大干伤天害理的事,一干就是十多年 哪!可见世界上哪个人哪个组织都不能确保绝对的英明。 所以说“迷信”是傻子碰到骗子的结果。傻是内因,被骗是外因。傻子碰到好人未必能 做出好事,傻子碰到另一个骗子就会做出另一件傻事。为了不让自己“傻”,善良的人们应 该用脑子去多学一些知识,努力让自己来把握命运,不要急着把一生托给某个人或某个组织。 软件人员在遭受项目失败并开始反省时,不要只是就事论事地仅把眼光锁在特定的项目 上,吃一堑应该长好几个智才对。本书作者刚刚失败过,乐意乘热讲讲感受。
20 . 我在读本科和硕士研究生时,一直信奉“创造性的事业要靠激情来推动”。我把这个口 号贴在办公室里,并扔掉物理学专业天天编程。在读硕士研究生的第一年,我卖出了第一份 软件。到我读博士研究生的第一年,我心想事成地获得了全国大学生电脑大赛软件展示第一 名。那时候我自以为翅膀已经硬了,再回顾前些年的艰苦,不禁有“媳妇熬成婆”的悲壮感 觉。于是我在杭州这个小地方略作宣传,在 1997 年 10 月份开了一家软件公司。 我开始把“振兴民族软件产业”列入日程,并且提前担忧将来钱挣得太多用不完该怎么 办。半年之后,我开始为软件产品作宣传,可并没有出现订单如潮、接应不暇的形势(事实 上压根就没有反应)。我已经意识到市场没找对,但仍觉得软件中的技术很有价值,准备再 开创“东方不亮西方亮”的新局面。于是我向只有一面之缘尚在北大方正工作的一位朋友求 助。他是真真的软件高手,当我小心翼翼地展示约 10 万行 C++代码的软件时,他竞在十几 分钟内就指出多处重大的设计错误,使我目瞪口呆地意识到整个软件系统的价值为零。那种 心痛啊,就象眼睁睁看着孩子被狼吃掉一样。 1998 年 10 月,这位朋友再一次从北京飞到杭州,三下五除二替我把只活了一年的公司 给关闭掉。他放心不下,觉得我“恶病需用猛药补” ,于是意尤未尽地把我捉到北大方正插 在他管辖的部门,让我学习怎样做事情。北京寒冷的冬天可以营造一种凄凉的气氛,冲去一 切可以自我原谅的借口。我并不是太爱虚荣的人,知道这次失败是我的毛病积累到一定水准 忍不住喷发出来的结果。我绝不能以年纪尚轻不太懂市场与管理为理由轻率地敷衍过去。我 把自己察觉到的数十个毛病列出来,日后一个一个克服掉。……本书的大部分内容取自我在 一年前的教训录。 改错之后,现在我不仅不难过而且挺快乐。觉得第一次失败很浪漫,值得怀念。刚开始 写这本书时,我那位北京的朋友把脚伸到杭州来散步,顺手又给了我几帖药,可以用到我毕 业。看来缺点是改不完的,补短和扬长要一起来。 2.6 提高综合素责 前面给软件开发人员加了过多的赞誉。一个技术出色的程序员可以自豪,但不可以目空 一切。上天不可能赋于一个人太多的优点,以致于他没有表示谦虚的余地。 我们在求学时可能太功利太挑剔,导致知识结构非常单薄,只怕到了晚年也成不了大器。 当程序员擅长技术时,还要时刻留意弥补自己并不擅长的非技术才能。扬长补短才能提高综 合素质。 假如能回到中学时代,我希望能把文科学好。那时侯盛传“学好数理化,走遍天下都不 怕”。我读中学时很无知,鄙视一切文科,现在后悔莫及。高考语文成绩 54 分(只比我的期 望值低 6 分) 。写作文的最高目标就是不逃题,考试前我总是反复祈祷:我没干过坏事,保 佑我作文不逃题吧!上大学的第一天我竟然无法用普通话说出“去洗澡怎么走” ,只好晃动 澡票与辅导员打哑语。中学的历史、地理课也被我糟踏了,考试时只会填写任课老师某年某 月某日在我家乡英勇就义,比谁的成绩更接近零分。更让我沮丧的是,这些行径都不是我发 明的,我顶多是个跟屁虫而已,一点回忆的自豪感都没有。 扔掉文科只学理科并不等同于“放下包袱,轻装前进”,倒象是摘掉了控制系统的机车, 开不了多远就翻车了。我搞了八年的软件开发,没做出象样的软件来。倒是有同行意外发现 我的文笔不错,是当作家的料。我发现自己在不该开花的地方结了一颗瘦涩的果子。曹操之 子曹彰曾建议:“大丈夫当学卫青、霍去病,立功沙漠,长驱数十万众,纵横天下,何能为 博士耶?”要后悔的事情太多了,只能现在做得勤快些。明知自己不成大器,但愿意亡羊补 牢,力求学得更深更广。 不要让人觉得程序员只管钻研技术,可以不懂世事并且应该自由散漫。程序员不该因为
21 .幼稚而显得单纯,应该是成熟了才变得单纯,才配得上这个充满活力的职业。 2.7 小 结 本章讲述做好程序员和程序经理的一些道理,为了剥去阻碍我们进步的那些虚伪,多唠 叨了几个故事。 中国经历了很多打斗、整人的革命,却没有一次赶上工业革命。在如今计算机横行的形 势下,我们不能再掉队了。90 年代初期,中国出现了一些程序员英雄,曾让我们激动过、 崇拜过。但这些孤胆英雄们很快地几乎全消亡了,他们只留下故事,没留下更多的价值。再 一次让我们意识到“振兴民族软件产业”不能依靠几个人一朝一夕的辉煌。软件人员勤奋学 习和工作,不该只图将来能做成几件事情的快意,而应力求事业长盛不衰,才能推动整个民 族软件产业持久稳健地发展。
22 . 第三章 项目计划与质量管理 在可行性分析之后,项目计划与质量管理将贯穿需求分析、系统设计、程序设计、测试、 维护等软件工程环节。 项目计划是要提供一份合理的进程表,让所有开发人员任务明确、步调一致,最终共同 准时地完成项目。项目计划是要付诸实施的,不象用嘴巴喊政治口号,可以很夸张。软件的 项目计划重在“准确”而非“快速”。 提高质量是软件工程的主要目标。但由于软件开发是一种智力创作活动,很难象传统工 业那样通过执行严格的操作规范来保证软件产品的质量。世上最小心翼翼、最老实巴脚的程 序员未必就能开发出高质量的软件来。程序员必须了解软件质量的方方面面(称为质量因 素),如正确性、性能、易用性、灵活性、可复用性、可理解性等等,才能在进行系统设计、 程序设计时将高质量内建其中。软件的高质量并不是“管理”出来的,实质上是设计出来的, 质量的管理只是一种预防和认证的手段而已。 3.1 项 目 计 划 做项目计划,如同给一个待出生的婴儿写传记那样困难。如果允许项目结束后再写计划, 那就轻松多了,并且可以 100% 地准确。 历史教训让我们明白一个道理:如果一万年以后才会有一条阳光大道通向共产主义,那 么现在就不要忙着砸锅炼钢赶英超美,免得在跑步奔向共产主义时把自己累死饿死。在做软 件的项目计划时,应屏弃一切浮夸作风。只有“知已知彼”才能做出合理的项目计划。这里 “知彼”是指要了解项目的规模、难度与时间限制。“知已”是指要了解有多少可用资源, 如可调用的程序员有几个?他们的水平如何?软硬件设施如何? 3.1.1 知己知彼 首先要了解项目的规模、难度与时间限制,才可以确定应该投入多少人力、物力去做这 个项目。在可行性分析阶段就要考虑这个问题。但不幸的是,人们在陷入项目不能自拨之前 总难以准确地估计项目的规模与难度。这里经验起到了最重要的作用。 项目的时间限制有两类。第一类,项目应该完成的日期写在合同中,如果延期了,则开 发方要作出相应的赔偿。第二类是开发自己的软件产品,虽然只确定了该产品大致的发行日 期并允许有延误,但如果拖延太久则会失去商机造成损失。 项目的资源分为三类: “人”、 “可复用的软构件”和“软硬件环境” ,如图 3.1 所示。 (1) 人是最有价值的资源。项目计划的制定者要确定开发人员的名单,要根据他们的专长进行分 工。 (2)可复用的软构件是次有价值的资源。1.2.1 节论述了复用软构件可提高软件的质量与 生产率。软构件并非一定要用自己的,可以向专业的软件供应商购买。 (3)软硬件环境虽然不是最重要的资源,却是必需的资源。原则上软硬件环境只要符合项 目的开发要求即可。有些项目可能要用到特殊的设备,则要事先作好准备,以免用时找不到 而担搁了进程。
23 . 1. 人 2. 可复用的软构件 3. 软 硬 件 环 境 图 3.1 项目的资源 3.1.2 进度安排 有一位程序员忙着编写程序,经理问他还需要多久才能完成。 “明天就可以完成。”程序员立即回答。 “我想这是不切实际的,实话实说,到底还要多少时间?”经理说。 “我还想加进一些新的功能,这需要花两个星期。 ”程序员想了一会儿说。 “即使这样也期望过高了,只要你编完程序时告诉我一声,我也就满足了。 ”经理说。 几年以后,经理要退休了。在他去退休午餐会时,发现那位程序员正趴在机器旁睡觉: 可怜的家伙整个晚上都在忙于编写那个程序。[James 1999] 程序员也期望每天早晨能在 7:00 准时起床,可老是一觉醒来就到中午了。项目落后于 进度表乃是家常便饭,不必大惊小怪。以下一些事件经常会导致项目被延误: (1)上级领导主管臆断,制定了不现实的期限。项目经理与程序员们被迫按照不合理的进 度表开展工作。 (2)客户的需求发生了变化,但没有对进度表作出相应的修改。 (3)低估了项目的规模与难度,导致投入的人力和物力不足。 (4)并未预见到存在难以克服的技术障碍。 (5)并未预见到开发人员会发生问题,如生病,辞职等等。 (6)开发人员之间不能很好的交流、协作,导致各阶段任务难以如期完成。 所以写进程表不能象小学生写决心书那样充满幻想。以下是一些有益的建议: (1)制定进度表的人最好就是项目负责人,他最了解项目和开发人员。进度表要经过开发 小组的讨论,在得到大部数人的支持后才能实施。避免出现一厢情愿的局面。 (2)进度安排并不见得一定要符合逻辑顺序。应尽可能地先做技术难度高的事,后做难度 低的事。也就是辛苦在前,轻松在后。 小时候我对一位老先生吃饭很感兴趣:他总是先把一大盒的米饭吃光了,然后再幸福地 品尝一小盒菜。父母告诉我这是中国的传统美德,叫“先苦后甜”。从此我铭记在心,按此 道理去学习和工作。可如今在饭店里,人们总是先把菜吃完了,最后才吃点米饭。天哪,生 活真是太复杂了,我究竟该“先吃饭” 还是“先吃菜”? (3)开发一个大的软件项目,应该将进度表分为若干个里程碑。一个里程碑之内的多个任 务可以同步进行。程序员极容易沉迷于技术,要么乐不思蜀,要么焦头烂额。里程碑就象心 灵的灯塔,使忙碌的人群不混乱,不迷失方向。 (4)进度表中必须留有缓冲时间,并将缓冲时间用到不确定的事情上。因为人们对即将要 做的事情知之甚少,所以要留一些时间以防不测。Microsoft 公司的一些开发小组甚至制定 了“50% 缓冲规则”[Cusumano 1996]。对许多项目经理而言,容忍进度表中存在缓冲时间, 不啻为观念上的一个飞跃。 (5)如果发现项目应交付的期限非常不合理,就要跟领导或跟客户据理力争,请求放宽期 限、调整进度。当客户的需求发生变化时,就要对进度表作出相应的修正。不要觉得修改进 度表很困难很麻烦,不修改才会产生真真的麻烦。很多人认为戒烟很困难,但马克·吐温曾 说:“戒烟很容易,我一年就戒几十次。 ”
24 . 3.2 零缺陷质量管理的观念 “零缺陷”质量管理的观念来源于一些国际上著名的硬件生产厂商。尽管软件的开发与 硬件生产有极大的差别,但我们仍可以从“零缺陷”质量管理中得到启迪。“零缺陷”质量 管理至少有两个核心内容:一是高目标,二是可执行的规范。 3.2.1 高目标 人在做一件事情时,由于存在很多不确定的因素,一般不可能 100% 地达到目标。假 设平常人做事能完成目标的 80%。如果某个人的目标是 100 分,那么他最终成绩可达 80 分。 如果某个人的目标只是 60 分,那么他最终成绩只有 48 分。我们在考场上身经百战,很清楚 那些只想混及格的学生通常都不会及格,那些想得高分的学生也常为自己的失误而捶胸顿 足。 做一个项目通常需要多个人的协作。假设项目的总质量(最高为 1)是十个开发人员的 工作质量之积。如果每个人的质量目标是 0.95,那么十个人的累积质量不会超过 0.19。如果 每个人的质量目标是 0.9 分,那么十个人的累积质量不会超过 0.03。只有每个人都做到 1, 项目总质量才会是 1。 如果没有高目标,人的堕落就很快。如果没有“零缺陷”的质量目标,也许缺陷就会成 堆。 3.2.2 可执行的规范 实现 100 分显然比实现 80 分要付出更多的努力。 “零缺陷”质量目标不是随心所欲提出 来的,做得到才有意义。实现高目标需要一套可执行的规范来保证。 50 年代末,全国掀起了“浮夸风” 。为了实现亩产数万斤推广各种方法,害得全国闹饥 荒。想不到有数千年种粮经验的几亿中国农民就这么整齐地栽倒了。 好规范必须是本企业有能力执行的。一个普通企业照搬一流企业的规范未必行得通。软 件工程的规范很容易从书籍中找到,但有了这些规范并不表明就能把软件做好。国内很多软 件公司根本没有条件去执行业界推荐的软件工程规范。社会主义初级阶段的“草”与发达资 本主义国家的“苗”的确有不同的培育方式。 软件是如此的灵活,如果没有规范来制约,就容易因无序的喜好而导致混沌;但规范如 果太严密了,就会扼杀程序员生机勃勃的创造力。制定软件规范是进退两难的事。程序员必 须深入了解软件多方面的质量因素,把那些能提高软件质量因素的各种规范植入脑中,才能 在各个实践环节自然而然地把高质量设计到软件中。 3.3 软件的质量因素 “运行正确”的程序就是高质量的程序吗? 不贪污的官就是好官吗? 时下老百姓对一些腐败的地方政府深痛恶绝,对“官”不再有质量期望。只要当官的不 贪污,哪怕毫无政绩,也算是“好官”。也有一些精明的老百姓打出旗号:宁要贪污犯,不 要大笨蛋。相比之下,程序员是够幸福的了。因为我们能通过努力,由自己来把握软件的命
25 .运。那么就不要轻易放弃提高软件质量的权利了。 “运行正确”的程序不见得就是高质量的程序。这个程序也许运行速度很低并且浪费内 存;也许代码写得一塌糊涂,除了开发者本人谁也看不懂也不会使用。正确性只是反映软件 质量的一个因素而已。 软件的质量因素很多,如正确性、精确性、可靠性、容错性、性能、效率、易用性、可 理解性、简洁性、可复用性、可扩充性、兼容性等等(还可以列出十几个)。这些质量因素 之间“你中有我,我中有他”,非常缠绵。如果程序员每天要面对那么多质量因素咬文嚼字, 不久就会迂腐得象孔乙已,并且有找不到女朋友的危险。 为了便于理解,可以参照武侠小说中的武学分类,将质量因素粗略地分成几大派。你想 那武学源源流长,相互渗透,谁能数得清有多少江湖派别。但想在道上混,总得知道六大门 派:“少林派” 、“武当派” 、“峨嵋派”、 “华山派”、“昆仑派”和“崆峒派”。软件质量因素的 分类如图 3.2 所示。其中“正确性与精确性”排在首位,地位如同“少林派”与“武当派” ; 而“性能与效率” , “易用性”, “可理解性与简洁性”和“可复用性与可扩充性”亦是举足轻 重的质量因素,地位仿佛“峨嵋派” ,“华山派”,“昆仑派”和“崆峒派” 。其它的质量因素 总可以在图 3.2 中找到合适的亲缘关系,本节不再一一细表。 正确性与精确性 少林派、武当派 性 易 可理 可复 峨 华 昆 崆 能 用 解性 用性 嵋 山 仑 峒 与 性 与简 与 派 派 派 派 效 洁性 可扩 率 充性 图 3.2 软件质量因素分类和武学分类 3.3.1 正确性与精确性 正确性与精确性之所以排在质量因素的第一位,是因为如果软件运行不正确或者不精 确,就会给用户造成不便甚至造成损失。机器不会主动欺骗人,软件运行不正确或者不精确 一般都是人造成的。即使一个软件能 100% 地按需求规格执行,但是如果需求分析错了, 那么对客户而言这个软件也存在错误。即使需求分析完全符合客户的要求,但是如果软件没 有 100% 地按需求规格执行,那么这个软件也存在错误。开发一个大的软件项目,程序员 要为“正确” 、“精确”四个字竭尽精力。 与正确性、精确性相关的质量因素是容错性和可靠性。 容错性首先承认软件系统存在不正确与不精确的因素,为了防止潜在的不正确与不精确 因素引发灾难,系统为此设计了安全措施。在一些高风险的软件系统,如航空航天、武器、 金融等系统中,容错性设计非常重要。 可靠性是指在一定的环境下,在给定的时间内,系统不发生故障的概率。可靠性本来是 硬件领域的术语。比如某个电子设备,一开始工作很正常,但由于工作中器件的物理性质会 发生变化(如发热),慢慢地系统就会失常。所以一个设计完全正确的硬件系统,在工作中 未必就是可靠的。软件在运行时不会发生物理性质的变化,人们常以为如果软件的某个功能 是正确的,那么它一辈子都是正确的。可是我们无法对软件进行彻底地测试,无法根除软件 中潜在的错误。平时软件运行得好好的,说不准哪一天就不正常了,如“2000 年”问题。
26 .因此把可靠性引入软件领域是有意义的。我曾买了一本关于软件可靠性的著作,此书充满了 数学公式。我发现以我目前的学历实在难以看懂书上讲了些什么。请宽恕我的愚昧,我把此 书给“供”起来,没敢用笔画一处记号。 3.3.2 性能与效率 用户都希望软件的运行速度高些(高性能) ,并且占用资源少些(高效率)。旧社会地主 就是这么对待长工的:干活要快点,吃得要少点。程序员可以通过优化算法、数据结构和代 码组织来提高软件系统的性能与效率。优化的关键工作是找出限制性能与效率的“瓶颈”, 不要在无关痛痒的地方瞎忙乎。如果你想职称升得快,光靠增加课时能顶屁用;你就该一年 写它几十篇文章,争取破格升教授。 3.3.3 易用性 易用性是指用户感觉使用软件的难易程度。用户可能是操作软件的最终用户,也可能是 那些要使用源代码的程序员。现代人的生活节奏快,干啥事都想图个方便。所以把易用性作 为重要的质量因素无可非议。 导致软件易用性差的根本原因是开发人员犯了“错位”的毛病:他以为只要自己用起来 方便,用户也一定会满意。俗话说“王婆卖瓜,自卖自夸”。当程序员向用户展示软件时, 常会得意地讲: “这个软件非常好用,我操作给你看,……是很好用吧!”软件的易用性要让 用户来评价。当用户真的感到软件很好用时,一股温暖的感觉油然而生,于是就用“友好” 来评价易用性。 3.3.4 可理解性与简洁性 可理解性表达了人们一种质朴的愿望:我化钱买了它,总得让我明白它是什么东西。我 小时候的一个伙伴在读中学时,就因无法理解电荷之分正负,觉得很烦恼,便早早地缀学当 工人。 可理解性也是对用户而言的。开发人员只有在自己思路清晰时才可能写出让别人能理解 的程序。编程时还要注意不可滥用技巧,应该用自然的方式编程。我们的确不知道自己的得 意之举究竟是锦上添花,还是画蛇添足。就象蒸出一笼馒头,在上面插一朵鲜花,本想弄点 诗情画意,却让人误以为那是一堆热气腾腾的牛粪。 简洁是一种美,不管是自己还是用户都会有同感。在生活中,与简洁对立的是“罗里罗 嗦”。中国小说中最“婆婆妈妈”的男人是唐僧。有一项民意调查:如果世上只有唐僧、孙 悟空、猪八戒和沙僧这四类男人,你要嫁给哪一类?请列出优先级。调查结果表明,现代女 性毫不例外地把唐僧摆在老末。 一个原始的应用问题可能很复杂,但高水平的人就能够把软件系统设计得很简洁。如果 软件系统臃肿不堪,它迟早会出问题。简洁是人们对工作“精益求精”的结果。 废话大师有句名言:“如果我令你过于轻松地明白了,那你一定是误解了我说的话。”我 最近有一种奇怪的体会:如果把学术文章写得很简洁,让人很容易理解,它往往中不了;只 有加上一些玄乎的东西,把本来简单的弄成复杂的,才会增加投稿的命中率。事实上,我可 以在 5 分钟之内说清楚三年来读博所做的工作,根本用不着写 100 多页的博士论文。我是在 临近毕业时,才发觉自己完全不适合读博士学位。将来工作后,我一定要好好编程,重新做 人。 3.3.5 可复用性与可扩充性 复用的一种方式是原封不动地使用现成的软构件, 另一种方式是对现成的软构件进行必
27 .要的扩充后再使用。可复用性好的程序一般也具有良好的可扩充性。本书第六章将论述如何 设计可复用、可扩充的 C++程序。 3.4 质 量 检 查 检查是人们不信任自己和别人的一种行为。当某些事情涉及到利益分配时,更需要有检 查活动来保证公平。估计即使进入了共产主义社会,也少不了检查。 质量检查并不是要等到项目结束时才执行唯一的一次,应该在每个实践环节都要执行。 对应于进度表,在每个里程碑到达时执行质量检查比较合理。质量检查的内容有二:一是作 出评审,是合格还是不合格?能打多少分?二是作出建议,对质量为什么好为什么差进行分 析,以便“改差为好”、“好上加好” 。 以下是人们经常采用的软件质量检查措施[Pressman 1999]: (1)事先把检查的主要内容制成一张表,使检查活动集中在主要问题上。 (2)只评审工作,不评审开发者。评审的气氛应该是融洽的。存在的错误应该被有礼貌地 指出来,任何人的意见都不应被阻挠或小看。 (3)建立一个议事日程并遵循它。检查过程不能放任自由,必须排照既定的方向和日程进 行。 (4)不要化太多的时间争论和辩驳。 (5)说清楚问题所在,但不要企图当场解决所有问题。 (6)对检查人员进行适当的培训。 …… 做好检查工作并不是件容易的事。自古以来“上有政策,下有对策”。 虚假的质量检查 还不如不检查,下面讲两个故事作为解释。 故事一 不久前我回到西北那所读了六年多的大学,惊奇地发现校园里房前屋后长满了待收割的 小麦!这所大学是从事电子科技的,种小麦干啥呀?朱总理曾讲过:“目前国家粮食充足, 再来三年自然灾害也不怕。”现在国泰民安,似乎用不着“深挖洞,广积粮” 。我素知学校提 创勤俭节约、自力更生,但与其种小麦还不如种蔬菜呢。老同学告诉我,种小麦是为了应付 “211”工程(为 21 世纪选拔 100 所重点大学)的检查团,因为“211”工程有较高的绿化 指标。偏偏检查赶在冬天,那时的西北极难长草。我那所大学本来就人多地少,地上一长草 马上就会被谈恋爱的学生给折磨死。一到冬天,整个校园就光秃秃一片。用小麦绿化校园可 谓千古绝笔,检查团的那些权贵人士早已五谷不分,岂知所见的“草坪”乃是麦田。 检查工作要预防被检查者弄虚作假。 故事二 我上高中时,班里举行一次入团评审。侯选人中有几位是好学生,有几位是坏学生。我 心想“伸张正义”的机会到了,绝不能让坏蛋混进纯洁的团里。可天知道团支部书记是聪明 绝顶还是蠢笨之极。他竟说:“班里还有一些同学没有入团,现在他们申请入团,有不同意 的请举手。”我们都不知道该怎么办了。书记接着说: “既然没有人举手反对,就表示全部同 意,请大家鼓掌欢迎。”这次入团评审不到一分钟就结束了,从此后我再也没想过争取入党。 检查工作要有科学的评审方式。
28 . 3.5 小 结 不知为什么,国内很多大的企业都喊着要进世界 500 强。如果真的实现了,世界 500 强还不全被中国霸占了。软件的项目计划和质量管理都不是用来喊叫的口号。做项目计划时 切忌“冒进”,不要指望在项目陷入困境后靠增加人手来解救。软件的高质量主要是设计出 来的,不是“管”出来的,更不能依赖质量检查。为此程序员要充分了解软件的质量因素, 只有提高设计水平,才能开发出高质量的软件。
29 . 第四章 可行性分析与需求分析 可行性分析是要决定“做还是不做”。 需求分析是要决定“做什么,不做什么”。 即使可行性分析是客观的、科学的,但决策仍有可能是错误的。因为决策者是人,人会 冲动,有赌博心态。如果可行性分析表明做某件事的成功率是 10%,失败率是 90%,倘若 该事情的意义非常大,决策者也许会一拍脑袋:“豁出去,干!”于是这世界就多了一份极喜 与极悲。4.1 节讲述可行性分析的四大要素:经济、技术、社会环境和人。 目前国内很多软件公司做系统集成项目,如果谈谈系统集成项目的可行性分析将很有意 思。可是那些系统集成项目大多是政府机构的,由于软件行业尚不规范并且客户方存在腐败 现象,所以业内流传“没有做不了的系统集成项目” 。软件公司的注意力几乎全集中在“如 何拿到项目订单”以及“拿到订单后如何蒙混过关”上,使我丧失了卖弄“可行性分析”的 机会。既然不能正面指点一个人如何做好事,那么就规劝他不要做坏事吧。 4.2 节讲述可行性分析案例——投资软件公司失败的教训。作者本来没有资格谈论投资, 但事有凑巧:近一年来我关闭了一个亏损 30 万元的软件公司(我自己的);休克一个年亏损 200 万元的软件公司(朋友的) ;扼杀一个 200 万元的投资方案(陌生人的) ;踩灭一个处于 萌芽状态的 100 万元的投资设想(熟人的) 。鉴于现在比较富有的民营企业渴望投资软件行 业的越来越多,值得谈谈这方面的可行性分析。我将讲述亲身经历后的感受,提一些建议。 不论是为客户做软件项目还是为自己做软件产品,都要进行需求分析。需求分析最恼人 之处是难以在项目刚启动时搞清楚需求,如果在项目做了一大半时需求发生了变化,那将使 项目陷入困境。4.3 节解释需求分析为什么困难,4.4 节讲述如何进行需求分析。本章的需求 分析均不涉及编程,所以不考虑结构化、面向对象等分析方法。 4.1 可行性分析的要素 做可行性分析不能以偏盖全,也不可以什么鸡毛蒜皮的细节都加以权衡。可行性分析必 须为决策提供有价值的证据。 联想集团领导人柳传志曾说:“没钱赚的事我们不干;有钱赚但投不起钱的事不干;有 钱赚也投得起钱但没有可靠的人选,这样的事也不干。”柳传志为决策立了上述准则,同时 也为可以行性分析指明了重点。 一般地,软件领域的可行性分析主要考虑四个要素:经济、技术、社会环境和人。本节 只是泛泛地解释这四个要素,旨在建立全局分析的观念。4.2 节将结合案例围绕上述要素进 行重点分析与评注。 4.1.1 经济 经济可行性分析主要包括:“成本——收益”分析和“短期——长远利益”分析。 一、成本——收益分析 成本——收益分析最容易理解,如果成本高于收益则表明亏损了,如果成本大大高于收 益那就亏大了。商人都不喜欢做吃亏的事情。有些商店成天贴着“最后一天跳楼大拍卖”的 标语,意思是:我准备吃大亏让你占便宜,同志,你快上钩吧。