软件工程概论

原文链接

现代软件工程讲义 1 软件工程概论

几乎所有程序员都知道“数据结构+算法 = 程序 ” 这句名言。但是在实际的学习和工作中,也有不少人产生了疑问。例如:

\1. 我写了二叉树的周游算法实现,在这里,二叉树是数据结构,周游的实现细节是算法。我写的C 程序就是结果。但是我这个程序有什么用呢?在Java 和其他一些语言中,似乎没有指针,那我可以不必了解二叉树么?

\2. 我找到了工作,成了一名程序员, 但是我发现所有的算法别人已经实现了,我只要调用就可以了。似乎我公司的软件和数据结构,算法的关系都不大。那我当初辛辛苦苦学习的数据结构和算法有用么? 如何区分一个好的程序员和不好的程序员呢?

\3. 我来到软件公司上班后,发现公司以前同事写的程序真是垃圾,根本无法维护。我要推翻重写!后来一个老员工笑嘻嘻地告诉我,我们现在看到的程序,就是去年的新员工愤怒地推翻重写之后的结果,大家反映还没有以前的版本好用呢。

那么我们软件行业赖以生存的“软件”, 我们程序员用来安生立命的“程序” 是什么?

举一个生活中的例子, 移山公司程序员二柱的小孩上了小学四年级, 老师让家长每天出30道四则运算题目给小学生做。二柱立马就想到写一个小程序来做这件事。 这个事情可以用很多语言或者工具来实现:

Excel, C/C++, C#, VB, Unix Shell, Emacs, Powershell/Vbscript, Javascript, Perl, Python, …

请大家估计写好这个程序需要的时间.

我想程序员用自己最擅长的工具, 一袋烟的功夫就搞定了。

二柱一下打印出好多份不同的题目, 让孩子做了。老师看了作业之后, 对二柱赞许有加。 别的老师闻讯, 问二柱能否扩大他的影响力, 编个软件, 给二年级到四年级都用, 多了一些小小的要求:

· 题目避免重复

· 可定制(数量/打印方式)

· 可以控制下列参数:

o 是否有乘除法

o 是否有括号

o 数值范围

o 加减有无负数

o 除法有无余数

o 是否支持分数 (真分数, 假分数, …)

o 是否支持小数 (精确到多少位)

o 打印中每行的间隔可调整

小同学兴高采烈地拿着需求回来了, 跟老爸说 – “老师明天就想要!” 现在大家估计做好这个软件需要多长时间。

我们假设二柱熬夜做出了这个软件的一个初始版本, 交给老师了。 过几天老师又问: 能否把这个程序放到学校的网站去, 再多一点点要求, 支持二元一次方程, 能开根号, 并且让所有人可以通过网页订制各种类型的四则运算作业. 二柱同志可能会想– 这是多复杂的一个工程哪! 他花了两个周末, 做出了一个版本.

学校老师又有要求, 既然已经做得这么好了, 再多一点点要求, 让同学直接在上面做题好了。

不久学校说:干脆我们推广到全国, 老师给学生布置作业, 学生做作业, 老师批阅, 家长通过手机获得学生的进展… 都在网上搞定!

现在请大家估计做好这个软件服务需要多长时间。

说完这两个例子, 我们来看看一些概念:

程序,在这里指的是源程序,就是一行一行的代码。仔细看过去,它们的确是建立在数据结构上的一些算法。但是光有代码还是不行的,这些一行一行的代码不会自己运行,得有人编译成机器能懂的目标代码,而编译不仅仅是 cc 和 link 命令,对于一个复杂的软件,我们不但要有合理的软件架构(Software Architecture), 软件设计和实现 (Software Design & Implementation), 我们还要用各种文件来描述各个程序文件之间的依赖关系,编译参数,链接参数,等等。这些都是软件的构建

软件团队的各个人员每天都在不断地修改各种源代码,怎么保证软件在不断的修改中能保证质量,不至于崩溃? 有些时候,我们要为某个需求写一些特殊功能,然后不久要把这些功能再合并回主要版本。有些程序还有32 位版本, 64位版本, 等等。 这是源代码管理 (Source Code Control) 的问题 – 有时候也叫配置管理 (Software Configuration Management)。我们还有一系列的工具和程序来保证程序的正确性,这些工具和程序本身应该更正确,才能保证别的软件的质量,对么? 这质量保证的工作叫Quality Assurance, 也叫软件测试 (Testing).

一个软件要有人买,就得先找到顾客,顾客有各种需求,有些靠谱,有些不靠谱,我们要把这些靠谱的需求都实现了,一群人要从需求分析 (Requirement Analysis) 开始,忙碌各种事情, 例如设计(软件架构),实现(写数据结构和算法),测试,到最后发布软件, 软件在运行过程中还会出这样那样的问题, 也许我们要时不时给软件打一个补丁, 这叫软件的维护(Software Maintenance)。这一系列过程就是软件的生命周期 (Software Life Cycle, SLC), 有人得负责软件项目的管理 (Software Project Management)

一个好的软件,即使功能和同类软件区别不大,但是会让人感觉到非常好用。这就是软件的“用户体验” (User Experience) 特别好。用户体验和数据结构,算法没什么关系,但是很多非常成功的软件就赢在这个方面。

有了软件,我们就要卖出去赚钱,有很多种赚钱的方式

· 有立马交钱买断,

· 有“先试用再交钱”,

· 有送硬件, 赚软件的钱;

· 有送软件, 赚硬件的钱;

· 也有“免费用,看广告”;

· 也有“免费用,程序也不是我写的,如果有问题,付我钱,我就来咨询…”

当然还有在用户不知道的情况下就安装了软件,然后用户怎么也摆脱不掉。最近还出现了 A公司要挟用户必须卸载 B公司的软件, 然后才能运行… 等等。这些都是软件赚钱的商业模式。有些做法是合情合理也合法, 有些看似合情合理, 但是不怎么合法. 有些做法不合理, 但是还没有相关法律。 在相关法律完善之前, 软件行业还有一个行规, 软件工程师应该有一个职业道德来约束 IT 人的行为。有学生提到, 在大学公开选课的时候, 是否可以写一个 “刷课机” 的程序, 利用学校选课系统的弱点或漏洞, 帮助某些用户选到自己想要的课程。这个程序/软件合法么? 符合道德规范么? 值得探讨。

上面的这些和软件开发活动(构建管理,源代码管理,软件设计**, 软件测试,项目管理**)是软件工程的核心部分。广泛意义上的软件工程也包用户体验 (User Experience), 用户界面设计 (User Interface Design) 等。所以,我觉得:

软件 = 程序 + 软件工程

一个扩展的推论是:

软件企业 = 软件 + 商业模式

当然, 软件企业还要加上人员的招聘, 绩效评估, 升迁, 淘汰等人力资源方面的工作.

弄清楚这些问题,是进行所有和程序,软件,企业等相关讨论的基础。

不消说,商业模式也会影响软件的需求,例如有人要开发社会网络软件,同时提供丰富的API 让别人能在上面开发,这个对API的支持会成为这个软件一个重要的特征。

回到本文开头的疑惑,答案就很清楚了 - 程序是基本功,但是除了程序之外,软件工程决定了软件的命运

出此之外, 软件的商业模式决定一个软件企业的成败。软件从业人员和软件企业的道德操守会极大地影响软件用户和社会。这两点不会在这门课里深入探讨。

软件产业还是一个相对年轻的产业,软件工程的概念是1969年第一次提出来的。下面用历史更长的航空产业做一个比较。

玩具阶段**:**

100个小孩里有99 个叠过纸飞机,像下面这样:

image

“设计/制造纸飞机” 的过程, 看起来技术含量不高, 但是也有很多窍门。 有些小孩在飞行前, 会用嘴对着纸飞机哈一口气, 这里面也许有深奥的道理, 也许只是迷信。 在跟着这些飞机奔跑,欢呼的时候,这些小孩心里一定有“我长大了要在天上飞”的想法。纸飞机,航模飞机和真飞机一样,都体现了某些基本的理论。我不懂这些理论,我就不多谈“空气动力学”之类的了.

业余爱好阶段**:**

image

多年以后,很多人还有“在天上飞”的想法。有人居然就实现了:

这是美联社的报道

这位哥们说 – 当你夏天躺在草地上的时候,你看白云飘过,你有没有幻想能跳到云朵上面?

所以他有一天忍不住就要实现他的幻想。

探索阶段**:**

image

和有些人看似“疯狂”的想法比起来,有些人不但疯狂,而且疯狂了好几年。在1903 年冬天,莱特(Wright) 兄弟经过几年的努力,在寒风凛冽的海滩上试飞了他们的飞机。它飞了36.5 米,历时12秒。试飞之后,大家还来不及在飞机面前合影留念,一阵狂风吹来,把飞机吹了几个跟头,大部分重要部件都毁坏了。

过了一百年, 现代人想在同一地点重复这一实验, 但是他们却失败了。

成熟的产业阶段**:**

image

现在,航空业已经成为了一个几百亿美元市场的工业,上百万的人每天在这个行业工作 (飞机设计, 制造, 销售, 辅助设备的设计, 制造, 销售, 民用航空的服务, 安全, 地勤, 飞机场的设计, 建设, 维护, 还有订飞机票的一大堆事儿),更多的人每天都享受到它带来的便利,当然还有种种苦恼。

从纸飞机扯到了波音787, 讲了这么多,这个和程序,软件,软件工程有什么关系呢,我们可以做一个类比:

航空 软件 影响(如果成功**/**失败会如何) 如何控制过程 (怎么一步步提高做事情的质量?)
玩具**, 基本知识**:纸飞机/航模 写程序练习数据结构/算法 影响自己,如果失败, 会减少对这类知识的兴趣。这类知识也有比赛,如航模比赛,程序算法比赛,但是比赛之后,这些算法高手写的程序的可维护性怎样? 有人会拿着程序去发布为商业软件么? 对飞机头哈气, 再哈气… 看别的小孩怎么做飞机, 上航模课外小组…
爱好者的尝试:气球+沙滩椅升空 用Javascript, Asp.Net, Ruby 写写网站 气球升空成功, 当地晚报会报道。程序能跑起来,自己博客写写。失败之后呢? 没关系,爱好者很快会捡起新的爱好。 研究各种工具, 做小实验。
先行者的探索:莱特兄弟飞行 软件业的创新 即使第一个版本的飞机只飞了36米,明白人还是看到了划时代的意义。很多软件原型也是这样。如果探索失败之后,会怎么样? 对于大部分创业者来说, 如果还有钱/机会的话,还要继续创新。 研究理论, 不断尝试
成熟的工业:飞机制造业民航 Taobao, Ali-pay, Win7 软件的发布会影响一个公司,一个行业,波及到相关的行业和人员。如果一个公司失败了, 很多人会失去饭碗。 有完整和严格的过程控制理论和实践。

在成熟的航空工业中,一个飞机发动机从构思到最后运行,不知道要经历过多少人, 多少工序,多少流程,多少相关知识的验证。我们无法想象,如果最后某个商用型号的发动机在飞行时发现问题,最初的设计师会自己爬到引擎中敲敲打打,然后钻出来说,“继续飞吧,我搞定了”。然而, 在软件行业中, 很多软件工程师往往以做这样的事而自豪。

我们平时在博客和论坛上讨论各种和程序相关的问题,是上面表格中哪一个层次上谈论“程序”呢? IT 专业的大学毕业生去找工作的时候说, 我懂软件工程, 我画了很多图, 写了很多文档, 最后得了很高的分数… 这些同学是真的懂软件工程?

软件工程和机械工程,航空工程, 等等工程学科一样, 其中也有工程理论, 控制论的原理。软件工程师开发/维护软件的行动, 或多或少和泰勒环 (Plan - do - study - improve) 类似。

说到商用软件和爱好者写的程序的区别, 我们还可以看这个例子:

如果一个民用飞机上有一个功能, 用户使用它的概率是百万分之一, 你还要做这个功能么? 你会选择:

a) 根本不考虑

b) 如果没时间就算了

c) 做了, 但是不用告诉用户

d) 做了, 而且不厌其烦地告诉用户如何使用

你会如何选择呢?

当然, 我们要看这个功能究竟是什么:

image

对, 就是飞机的安全功能。坐飞机的时候, 你会看到乘务人员不厌其烦地给你介绍如果氧气罩自动掉下来的时候, 应该怎么做. 走道上有灯, 会指导你逃生. 你也许注意到你身下的坐垫是可以漂浮的, 飞机还可以在水面上降落… 但是, 大家有几个人真正使用过这些 “功能”? 如果你买了一张特便宜的机票, 上飞机的时候, 乘务员告诉你:

为了节约成本, 本次航班没有那些安全设备**, 没关系的**, 反正大家也不会用到**…”

这个飞机你还敢坐么?

下面是一个最近的例子, 飞机发生故障后, 机长把飞机降落在河面上, 所有乘客安然无恙.

image

资料来源: http://en.wikipedia.org/wiki/US_Airways_Flight_1549

另一个例子, Qantas 航空公司的一架飞机在高空中被炸开一个洞, 飞机紧急降落了,机上所有乘客安全离开。 试想这样的事发生在我们的程序中, 程序正在高速运行, 突然发生 了一个异常, 我们的程序能否正常工作, 安然退出, 并保证用户的数据不受损失?

image

相关资料: http://articles.sfgate.com/2008-07-27/news/17173697_1_metal-fatigue-oxygen-canisters-cargo

软件工程是什么呢?

软件工程的 bug

和软件打交道的专业人士都知道软件有 “bug” (缺陷), 软件团队的很多人都整天和 bug 打交道, bug 的多少可以直接衡量一个软件的开发效率, 用户满意度, 可靠性, 和可维护性。例如:

软件的开发效率 – 开发过程中bug 太多了, 导致软件无法按时交付;

用户满意度 – 用户使用时报告了很多bug, 纷纷表示对生活影响很大;

可靠性 – 这个软件经常会崩溃,这个操作系统会死机;

可维护性 – 这个软件太难维护了, 按下葫芦起了瓢, 修复了一个问题, 另一个问题又出来了。也没有足够的文档, 维护人员纷纷表示要把原作者找出来打一顿。

Bug 这个词的来历

很多人说计算机系统的第一个bug 是一个蛾子(有图为证),因此大家把软件的缺陷叫做bug. 其实不少工程师在那之前都用“bug”来统称系统中的问题. [http://en.wikipedia.org/wiki/Software_bug#Etymology]

什么是bug 呢? 简单的说, 软件的行为和用户的期望值不一样的话, 就叫bug.

例如, 某聊天软件启动的时候就崩溃了, 用户期望这个聊天软件不能崩溃.

又例如, 某聊天软件不支持视频聊天,用户期望这个聊天软件支持视频聊天。但是开发这个软件的开发人员说, 这个版本根本没打算支持视频聊天。这还是一个bug 么?

是否是bug, 取决于用户和开发者的不同角度, 我们看一个经典小说中的例子:

另一个例子:

很多人认为bug 就是质量不合格, 没有bug, 就是质量完美, 其实这也未必. 我们在大街上看到很多小汽车, 这些汽车出厂的时候, 它们都通过了各自的质量检测。但是你问路人那些车的“质量好”, 很多人会告诉你有些车的质量大大好于另外一些车. 那为什么还有人买那些质量 “不够好” 的汽车呢? 对于某些顾客来说, 某一类的汽车满足了他们的需求, 他们就会买。 如果汽车的销售人员不经调研, 在自己汽车不适合的市场去卖车, 他们未必能卖出去很多。

下面这些汽车的 ”质量” 一样么?

image

回到软件上去, 有实际用处的, 完美的软件在世界上是不存在的. 没有实际用处的完美的软件也几乎没有, 有人会说一个打印 “hello world!” 的程序似乎可以称为 “完美”,但是我不知道这个程序是否可以算做一个软件。那市面上充满这么多不完美的产品, 软件团队为什么要把这些不完美的软件发布出来呢? 为什么不能等到它们完美之后再发布? 软件工程的一个重要任务就是要决定一个软件在什么时候能“足够好”, 没有严重的“bug”,可以发布。

软件工程和计算机科学的关系

中国大陆的很多高校有下面三种讲计算机软件的机构: 计算机科学与技术系/学院, 软件学院, 软件工程系/学院。 很多同学在报名的时候不知道它们的区别, 进去之后发现除了收费高低不同, 似乎区别也不大。 (我在参加全国软件学院评审的时候就听到某专家评论 - 某某学校的软件学院和计算机学院是一套老师, 两块牌子, 收费不同, 徒生烦恼, 不如合并算了! )

它们的区别还是挺大的, 援引这篇文章的讲法, 下图红线上面部分是软件工程, 下面部分的议题属于是计算机科学:

img

[图片来源]

文章认为, 可以从形式上证明的, 多属于计算机科学; 和人的行为相关, 和计算机系统的具体实现相关, 则属于软件工程。中国大陆高校的“计算机科学”院系中 , 大部分老师做的是偏工程方面的研究, 大部分学生毕业后也投身于解决具体的工程问题, 这和软件学院,软件工程系的研究和培养方向非常雷同。