122分而治之 分而治之是指把一个复杂的问题分解成若干个简单的问题,然后逐个解决。这种朴素的 思想来源于人们生活与工作的经验,完全适合于技术领域。软件人员在执行分而治之的时候, 应该着重考虑:复杂问题分解后,每个问题能否用程序实现?所有程序最终能否集成为一个 软件系统并有效解决原始的复杂问题? 解决原始问题 被件之 复杂问题 系统 子问题1 程序1 分解 子问题2 程序2 子问题n 程序n 图1.6软件领域的分而治之策略 图1.6表示了软件领域的分而治之策略。诸如软件的体系结构设计、模块化设计都是分 而治之的具体表现。软件的分而治之不可以“硬分硬治”。不像为了吃一个西瓜或是一只鸡, 挥刀斩成n块,再把每块塞进嘴里粉碎搅拌,然后交由胃肠来消化吸收,象征复杂问题的西 瓜或是鸡也就此消失了。 123优化—折衷 软件的优化是指优化软件的各个质量因素,如提高运行速度,提高对内存资源的利用率 使用户界面更加友好,使三维图形的真实感更强等等。想做好优化工作,首先要让开发人员 都有正确的认识:优化工作不是可有可无的事情,而是必须要做的事情。当优化工作成为 种责任时,程序员才会不断改进软件中的算法,数据结构和程序组织,从而提高软件质量。 著名的3D游戏软件 Quake,能够在PC机上实时地绘制高度真实感的复杂场景。 Quake 的开发者能把很多成熟的图形技术发挥到极致,例如把 Bresenham画线、多边形裁剪、树遍 历等算法的速度提高近一个数量级。我第一次看到 Quake时不仅感到震动,而且深受打击。 这个PC游戏软件的技术水平己经远胜于我所见识到的国内领先的图形学相关科研成果。这 对我们日益盛行的点到完止的研发工作真是莫大的讽刺。所以当我们开发的软件表现出很多 不可救药的病症时,不要怨机器差。真的是我们自己没有把工作做好,写不好字却嫌笔钝。 就假设我们经过思想教育后,精神抖擞,随时准备为优化工作干上六天七夜。但愿意做 并不意味着就能把事情做好。优化工作的复杂之处是很多目标存在千丝万缕的关系,可谓数 不清理还乱。当不能够使所有的目标都得到优化时,就需要“折衷”策略。 软件中的折衷策略是指通过协调各个质量因素,实现整体质量的最优。就象党支部副书 记扮演和事佬的角色:“…为了使整个组织具有最好的战斗力,我们要重用几个人,照顾 些人,在万不得已的情况下委屈一批人”。 软件折衷的重要原则是不能使某一方损失关键的职能,更不可以象“舍鱼而取熊掌”那 样抛弃一方。例如3D动画软件的瓶颈通常是速度,但如果为了提高速度而在程序中取消光 照明计算,那么场景就会丧失真实感,3D动画也就不再有意义了(如果人类全是色盲,计 算机图形学将变得异常简单)。 人都有惰性,如果允许滥用折衷的话,那么一当碰到困难,人们就会用拆东墙补西墙的
1.2.2 分而治之 分而治之是指把一个复杂的问题分解成若干个简单的问题,然后逐个解决。这种朴素的 思想来源于人们生活与工作的经验,完全适合于技术领域。软件人员在执行分而治之的时候, 应该着重考虑:复杂问题分解后,每个问题能否用程序实现?所有程序最终能否集成为一个 软件系统并有效解决原始的复杂问题? 解决原始问题 分解 集成 复杂问题 子问题 1 子问题 2 子问题 n 程序 1 程序 2 程序 n 软件 系统 图 1.6 软件领域的分而治之策略 图 1.6 表示了软件领域的分而治之策略。诸如软件的体系结构设计、模块化设计都是分 而治之的具体表现。软件的分而治之不可以“硬分硬治”。不像为了吃一个西瓜或是一只鸡, 挥刀斩成 n 块,再把每块塞进嘴里粉碎搅拌,然后交由胃肠来消化吸收,象征复杂问题的西 瓜或是鸡也就此消失了。 1.2.3 优化——折衷 软件的优化是指优化软件的各个质量因素,如提高运行速度,提高对内存资源的利用率, 使用户界面更加友好,使三维图形的真实感更强等等。想做好优化工作,首先要让开发人员 都有正确的认识:优化工作不是可有可无的事情,而是必须要做的事情。当优化工作成为一 种责任时,程序员才会不断改进软件中的算法,数据结构和程序组织,从而提高软件质量。 著名的 3D 游戏软件 Quake,能够在 PC 机上实时地绘制高度真实感的复杂场景。Quake 的开发者能把很多成熟的图形技术发挥到极致,例如把 Bresenham 画线、多边形裁剪、树遍 历等算法的速度提高近一个数量级。我第一次看到 Quake 时不仅感到震动,而且深受打击。 这个 PC 游戏软件的技术水平已经远胜于我所见识到的国内领先的图形学相关科研成果。这 对我们日益盛行的点到完止的研发工作真是莫大的讽刺。所以当我们开发的软件表现出很多 不可救药的病症时,不要怨机器差。真的是我们自己没有把工作做好,写不好字却嫌笔钝。 就假设我们经过思想教育后,精神抖擞,随时准备为优化工作干上六天七夜。但愿意做 并不意味着就能把事情做好。优化工作的复杂之处是很多目标存在千丝万缕的关系,可谓数 不清理还乱。当不能够使所有的目标都得到优化时,就需要“折衷”策略。 软件中的折衷策略是指通过协调各个质量因素,实现整体质量的最优。就象党支部副书 记扮演和事佬的角色:“…为了使整个组织具有最好的战斗力,我们要重用几个人,照顾一 些人,在万不得已的情况下委屈一批人”。 软件折衷的重要原则是不能使某一方损失关键的职能,更不可以象“舍鱼而取熊掌”那 样抛弃一方。例如 3D 动画软件的瓶颈通常是速度,但如果为了提高速度而在程序中取消光 照明计算,那么场景就会丧失真实感,3D 动画也就不再有意义了(如果人类全是色盲,计 算机图形学将变得异常简单)。 人都有惰性,如果允许滥用折衷的话,那么一当碰到困难,人们就会用拆东墙补西墙的
方式去折衷,不再下苦功去做有意义的优化。所以我们有必要为折衷制定严正的立场:在保 证其它因素不差的前提下,使某些因素变得更好。 下面让我们用“优化——折衷”的策略解决“鱼和熊掌不可得兼”的难题。 问题提出:假设鱼每千克10元,熊掌每千克一万元。有个倔脾气的人只有20元钱,非 得要吃上一公斤美妙的“熊掌烧鱼”,怎么办? 解决方案:化9元9角9分钱买999克鱼肉,化10元钱买1克熊掌肉,可做一道“熊 掌戏鱼”菜。剩下的那一分钱还可建立奖励基金 1.3一些不正确的观念 本节例举并分析一些不正确的软件工程观念,可帮助初学者少犯相似的错误 观念之一:我们拥有一套讲述如何开发软件的书籍,书中充满了标准与示例,可以帮助我们 解决软件开发中遇到的任何问题。 客观情况:好的参考书无疑能指导我们的工作。充分利用书籍中的方法、技术和技巧,可以 有效地解决软件开发中大量常见的问题。但实践者并不能因此依赖于书籍,这是因为:(1) 现实的工作中,由于条件千差万别,即使是相当成熟的软件工程规范,常常也无法套用。(2) 软件技术日新月异,没有哪一种软件标准能长盛不衰。祖传秘方在某些领域很吃香,而在软 件领域则意味着落后。 观念之二:我们拥有最好的开发工具、最好的计算机,一定能做出优秀的软件。 客观情况:良好的开发环境只是产出成果的必要条件,而不是充分条件。如果拥有好环境的 是一群庸人,难保他们不干出南辕北辙的事情 观念之三:如果我们落后于计划,可以增加更多的程序员来解决。 客观情况:软件开发不同于传统的农业生产,人多不见得力量大。如果给落后于计划的项目 增添新手,可能会更加延误项目。因为:(1)新手会产生很多新的错误,使项目混乱。(2) 老手向新手解释工作以及交流思想都要花费时间,使实际开发时间更少。所以科学的项目计 划很重要,不在乎计划能提前多少,重在恰如其分。如果用“大跃进”的方式奔向共产主义, 只会产生倒退的后果。 观念之四ε既然需求分析很困难,不管三七二十一先把软件做了再说,反正软件是灵活的, 随时可以修改 客观情况:对需求把握得越准确,软件的修修补补就越少。有些需求在一开始时很难确定 在开发过程中要不断地加以改正。软件修改越早代价越少,修改越晚代价越大,就跟治病 样道理 14一些有争议的观念 本节探讨一些有争议的观念,目的不在于得出“正确”或“错误”的评断,而在于争议 会激发更多理性的思考。 争议之一:如果软件运行较慢,是换一台更快的计算机,还是设计一种更快的算法?
方式去折衷,不再下苦功去做有意义的优化。所以我们有必要为折衷制定严正的立场:在保 证其它因素不差的前提下,使某些因素变得更好。 下面让我们用“优化——折衷”的策略解决“鱼和熊掌不可得兼”的难题。 问题提出:假设鱼每千克 10 元,熊掌每千克一万元。有个倔脾气的人只有 20 元钱,非 得要吃上一公斤美妙的“熊掌烧鱼”,怎么办? 解决方案:化 9 元 9 角 9 分钱买 999 克鱼肉,化 10 元钱买 1 克熊掌肉,可做一道“熊 掌戏鱼”菜。剩下的那一分钱还可建立奖励基金。 1.3 一些不正确的观念 本节例举并分析一些不正确的软件工程观念,可帮助初学者少犯相似的错误。 观念之一:我们拥有一套讲述如何开发软件的书籍,书中充满了标准与示例,可以帮助我们 解决软件开发中遇到的任何问题。 客观情况:好的参考书无疑能指导我们的工作。充分利用书籍中的方法、技术和技巧,可以 有效地解决软件开发中大量常见的问题。但实践者并不能因此依赖于书籍,这是因为:(1) 现实的工作中,由于条件千差万别,即使是相当成熟的软件工程规范,常常也无法套用。(2) 软件技术日新月异,没有哪一种软件标准能长盛不衰。祖传秘方在某些领域很吃香,而在软 件领域则意味着落后。 观念之二:我们拥有最好的开发工具、最好的计算机,一定能做出优秀的软件。 客观情况:良好的开发环境只是产出成果的必要条件,而不是充分条件。如果拥有好环境的 是一群庸人,难保他们不干出南辕北辙的事情。 观念之三:如果我们落后于计划,可以增加更多的程序员来解决。 客观情况:软件开发不同于传统的农业生产,人多不见得力量大。如果给落后于计划的项目 增添新手,可能会更加延误项目。因为:(1)新手会产生很多新的错误,使项目混乱。(2) 老手向新手解释工作以及交流思想都要花费时间,使实际开发时间更少。所以科学的项目计 划很重要,不在乎计划能提前多少,重在恰如其分。如果用“大跃进”的方式奔向共产主义, 只会产生倒退的后果。 观念之四:既然需求分析很困难,不管三七二十一先把软件做了再说,反正软件是灵活的, 随时可以修改。 客观情况:对需求把握得越准确,软件的修修补补就越少。有些需求在一开始时很难确定, 在开发过程中要不断地加以改正。软件修改越早代价越少,修改越晚代价越大,就跟治病一 样道理。 1.4 一些有争议的观念 本节探讨一些有争议的观念,目的不在于得出“正确”或“错误”的评断,而在于争议 会激发更多理性的思考。 争议之一:如果软件运行较慢,是换一台更快的计算机,还是设计一种更快的算法?
作者观点:如果开发软件的目的是为了学习或是研究,那么应该设计一种更快的算法。如果 该软件已经用于商业,则需谨慎考虑:若换一台更快的计算机能解决问题,则是最快的解决 方案。改进算法虽然可以从根本上提高软件的运行速度,但可能引入错误以及延误进程。技 术狂毫无疑问会选择后者,因为他们觉得放弃任何可以优化的机会就等于犯罪 类似的争议还有:是买现成的程序,还是彻底自己开发?技术人员和商业人士常常会有 不同的选择。 争议之二:有最好的软件工程方法,最好的编程语言吗? 作者观点:在软件领域永远没有最好的,只有更好的。能解决问题的都是好方法或是好语言。 程序员在最初学习 Basic、 Fortran、 Pascal、C、C艹等语言时会感觉一个比一个好,不免有 喜新厌旧之举。而如今的 Visual basic、 Delphi、 isual c+、Java等语言各有所长,真的难 分优劣。开发人员应该根据客观条件,选择自己熟悉的方法和语言,才能保证合格的质量与 生产率 程序设计是自由与快乐的事情,不要发誓忠于某某主义而自寻烦恼。 争议之三:编程时是否应该多使用技巧? 作者观点:就软件开发而言,技巧的优点在于能另辟蹊径地解决一些问题,缺点是技巧并不 为人熟知。若在程序中用太多的技巧,可能会留下隐患,别人也难以理解程序。鉴于一个局 部的优点对整个系统而言是微不足道的,而一个错误则可能是致命的。作者建议用自然的方 式编程,少用技巧。 《狼三则》的故事告诉我们“失败的技巧通常是技俩”。当我们在编程时无法判断是用 了技巧还是用了技俩,那就少用。《卖油翁》的故事又告诉我们“熟能生巧”,表明技巧是自 然而然产生的,而不是卖弄出来的。卖油翁的绝技是可到中央电视台表演的,而他老人家却 谦虚地说:“没啥没啥,用熟了而已” 争议之四:软件中的错误是否可按严重程度分等级? 作者观点:在定量分析时,可以将错误分等级,以便于管理。微软的一些开发小组将错误分 成四个等级 Cusumano19,如表1.1所示。 级严重:错误导致软件崩溃。 级严重:错误导致一个特性不能运行并且没有替代方案。 三级严重:错误导致一个特性不能运行但有替代方案。 「四级严重:错误是表面化的或是微小的。 表1.1错误的四个等级 上述分类是非常技术性的,并不是普适的。假设某个财务软件有两个错误:错误A使 该软件死掉,错误B导致工资计算错误。按表1.1分类,错误A属一级严重,错误B属 级严重。但事实上B要比A严重。工资算多了或者算少了,将会使老板或员工遭受经济损 失。而错误A只使操作员感到厌烦,并没有造成经济损失。另一个示例是操作手册写错 按表1.1分类则属四级严重,但这种错误可能导致机毁人亡 开发人员应该意识到:所有的错误都是严重的,不存在微不足道的错误。这样才能少犯 错误
作者观点:如果开发软件的目的是为了学习或是研究,那么应该设计一种更快的算法。如果 该软件已经用于商业,则需谨慎考虑:若换一台更快的计算机能解决问题,则是最快的解决 方案。改进算法虽然可以从根本上提高软件的运行速度,但可能引入错误以及延误进程。技 术狂毫无疑问会选择后者,因为他们觉得放弃任何可以优化的机会就等于犯罪。 类似的争议还有:是买现成的程序,还是彻底自己开发?技术人员和商业人士常常会有 不同的选择。 争议之二:有最好的软件工程方法,最好的编程语言吗? 作者观点:在软件领域永远没有最好的,只有更好的。能解决问题的都是好方法或是好语言。 程序员在最初学习 Basic、Fortran、 Pascal、C、C++等语言时会感觉一个比一个好,不免有 喜新厌旧之举。而如今的 Visual Basic、Delphi、Visual C++、Java 等语言各有所长,真的难 分优劣。开发人员应该根据客观条件,选择自己熟悉的方法和语言,才能保证合格的质量与 生产率。 程序设计是自由与快乐的事情,不要发誓忠于某某主义而自寻烦恼。 争议之三:编程时是否应该多使用技巧? 作者观点:就软件开发而言,技巧的优点在于能另辟蹊径地解决一些问题,缺点是技巧并不 为人熟知。若在程序中用太多的技巧,可能会留下隐患,别人也难以理解程序。鉴于一个局 部的优点对整个系统而言是微不足道的,而一个错误则可能是致命的。作者建议用自然的方 式编程,少用技巧。 《狼三则》的故事告诉我们“失败的技巧通常是技俩”。当我们在编程时无法判断是用 了技巧还是用了技俩,那就少用。《卖油翁》的故事又告诉我们“熟能生巧”,表明技巧是自 然而然产生的,而不是卖弄出来的。卖油翁的绝技是可到中央电视台表演的,而他老人家却 谦虚地说:“没啥没啥,用熟了而已”。 争议之四:软件中的错误是否可按严重程度分等级? 作者观点:在定量分析时,可以将错误分等级,以便于管理。微软的一些开发小组将错误分 成四个等级 [Cusumano 1996],如表 1.1 所示。 一级严重:错误导致软件崩溃。 二级严重:错误导致一个特性不能运行并且没有替代方案。 三级严重:错误导致一个特性不能运行但有替代方案。 四级严重:错误是表面化的或是微小的。 表 1.1 错误的四个等级 上述分类是非常技术性的,并不是普适的。假设某个财务软件有两个错误:错误 A 使 该软件死掉,错误 B 导致工资计算错误。按表 1.1 分类,错误 A 属一级严重,错误 B 属二 级严重。但事实上 B 要比 A 严重。工资算多了或者算少了,将会使老板或员工遭受经济损 失。而错误 A 只使操作员感到厌烦,并没有造成经济损失。另一个示例是操作手册写错, 按表 1.1 分类则属四级严重,但这种错误可能导致机毁人亡。 开发人员应该意识到:所有的错误都是严重的,不存在微不足道的错误。这样才能少犯 错误
1.5小结 软件工程学科发展到今天,已经有了很多方法和规范,学之不尽。本章只在宏观上讨论 了软件工程的一些思想,更具体的内容将在后面的章节论述。无论是什么好方法,贵在理解 与灵活运用,而不可当成灵丹妙药,不象“吃了脑黄金或脑白金,就能使一亿人先聪明起来
1.5 小 结 软件工程学科发展到今天,已经有了很多方法和规范,学之不尽。本章只在宏观上讨论 了软件工程的一些思想,更具体的内容将在后面的章节论述。无论是什么好方法,贵在理解 与灵活运用,而不可当成灵丹妙药,不象“吃了脑黄金或脑白金,就能使一亿人先聪明起来
第二章程序员与程序经理 工作在第一线的软件开发人员是程序员和程序经理,他们决定着软件的命运。良好的程 序员队伍和出色的管理是软件项目成功的必要条件。管理不是管制,不是去卡住人家的脖子, 因为程序员不是一群野鸭子。管理的目的是让大家一起把工作做好,并且让各人获得各自的 快乐和满足。当一个组织被出色地领导时,雇员甚至不知道他们已被领导。在项目完成时 他们会自豪地说:“看看我们通过努力取得的成绩吧”。所以管理者不能老惦记着自己是 官,而应时刻意识到自己是责任的主要承担者。 我们经常会听到有经理头衔的人在高谈阔论:“编程我不会,做个项目还不easy?派个 人去搞系统分析,回头再叫几个程序员把需求译成程序,不就OK了吗?” 不懂英语的人准以为easy和OK是贬义词。要让软件项目失败很容易,只要符合下列 条件之一即可: (1)项目经理对软件一无所知 (2)技术负责人对编程不感兴趣 (3)真真编写代码的程序员是临时雇用的。 如果上述三个条件同时具备,就请放心失败好了。 让我们少幻想自己是比尔·盖茨,先当好程序员和程序经理再说。 21了解程序员 早期的程序员干活能从软件直通硬件,个个生猛无比。又因他们的作息时间、言行举止 与常人不太一样,久而久之就给人们留下了“神秘”、“孤僻”的印象。如今软件行业被炒得 热火朝天,有能耐的程序员即便躲在大山岙的军工厂里也能被挖出来。而更多原本不是程序 员的人操起几本“速成”、“二十一天通”等书籍也加入了这个行业。现在国内号称有上百万 程序员,这支大军鱼龙混杂,已搞不清那些是正规军,那些是民兵游击队了。 真正的程序员都有如下秉性: 实 程序员在学习与工作期间几乎天天与机器打交道,压根就没有受欺骗或欺骗人的机会。 勤奋的程序员在调试无穷多的程序Bug时,已经深深地接受了“诚实”的教育。不诚实的 人,他肯定不想做、也做不好程序员 有一名市场营销员和一名程序员都在新闻发布会上发言,将一项新技术的消息公布于 市场营销员说:“这项技术比电话、晶体管和原子弹三项发明加起来对世界文明的影响 都要大。” 程序员说:“这项技术在有限的领域内,在有限的程度上,解决了一些技术性的问题。” 看来为了让我们的民族更加诚实,学电脑真的要从娃娃抓起。 二、简阜—实用直 有人问一个数学家,一个物理学家和一名程序员:“一个盒子有几个面?” 数学家回答说:“有六个面,因为盒子是长方体。” 物理学家回答说:“有12个面,分为6个外表面和6个内表面 程序员回答说:“只有两个面,里面放电路板和硬盘,外面放显示器和键盘
第二章 程序员与程序经理 工作在第一线的软件开发人员是程序员和程序经理,他们决定着软件的命运。良好的程 序员队伍和出色的管理是软件项目成功的必要条件。管理不是管制,不是去卡住人家的脖子, 因为程序员不是一群野鸭子。管理的目的是让大家一起把工作做好,并且让各人获得各自的 快乐和满足。当一个组织被出色地领导时,雇员甚至不知道他们已被领导。在项目完成时, 他们会自豪地说:“看看我们通过努力取得的成绩吧”。所以管理者不能老惦记着自己是一个 官,而应时刻意识到自己是责任的主要承担者。 我们经常会听到有经理头衔的人在高谈阔论:“编程我不会,做个项目还不 easy?派个 人去搞系统分析,回头再叫几个程序员把需求译成程序,不就 OK 了吗?” 不懂英语的人准以为 easy 和 OK 是贬义词。要让软件项目失败很容易,只要符合下列 条件之一即可: (1)项目经理对软件一无所知; (2)技术负责人对编程不感兴趣; (3)真真编写代码的程序员是临时雇用的。 如果上述三个条件同时具备,就请放心失败好了。 让我们少幻想自己是比尔·盖茨,先当好程序员和程序经理再说。 2.1 了 解 程 序 员 早期的程序员干活能从软件直通硬件,个个生猛无比。又因他们的作息时间、言行举止 与常人不太一样,久而久之就给人们留下了“神秘”、“孤僻”的印象。如今软件行业被炒得 热火朝天,有能耐的程序员即便躲在大山岙的军工厂里也能被挖出来。而更多原本不是程序 员的人操起几本“速成”、“二十一天通”等书籍也加入了这个行业。现在国内号称有上百万 程序员,这支大军鱼龙混杂,已搞不清那些是正规军,那些是民兵游击队了。 真正的程序员都有如下秉性: 一、诚实 程序员在学习与工作期间几乎天天与机器打交道,压根就没有受欺骗或欺骗人的机会。 勤奋的程序员在调试无穷多的程序 Bug 时,已经深深地接受了“诚实”的教育。不诚实的 人,他肯定不想做、也做不好程序员。 有一名市场营销员和一名程序员都在新闻发布会上发言,将一项新技术的消息公布于 众。 市场营销员说:“这项技术比电话、晶体管和原子弹三项发明加起来对世界文明的影响 都要大。” 程序员说:“这项技术在有限的领域内,在有限的程度上,解决了一些技术性的问题。” 看来为了让我们的民族更加诚实,学电脑真的要从娃娃抓起。 二、简单——实用主义 有人问一个数学家,一个物理学家和一名程序员:“一个盒子有几个面?” 数学家回答说:“有六个面,因为盒子是长方体。” 物理学家回答说:“有 12 个面,分为 6 个外表面和 6 个内表面 。” 程序员回答说:“只有两个面,里面放电路板和硬盘,外面放显示器和键盘