软件工程思维到底有多重要

软件工程的重要性

自我介绍

本人是西洋汇公司的CEO,同时也是一名有着18年编程经验的 PHP 程序员。

在18年的摸爬打滚里面,我越来越意识到,软件程序员里面所谓的高手,并没有太多神妙(神奇的,玄妙的)。

什么是高手

  • 对代码的 review
  • 有着符合实际业务的逻辑
  • 程序逻辑优化与扩展
  • 出色的编程能力

万丈高楼平地起

软件无法做得跟得上,业务和世界的变化导致:

  1. 重写
  2. 重写后问题依然存在
  3. 再推倒重写

开始重新重视软件工程,包括但不仅限于:文件目录的编排,类、方法、变量的命名,方法和类的长短,还有解耦与分层等等。

重新捧起《代码简洁之道》一书,激起无限共鸣,与恍然大悟。

分享

这是我的成长历程。无独有偶,最近听音频学习,听到这一篇,挺想分享给大家,以作讨论。

下文,转载自“得到APP”万维钢精英日课第三季:《计算机思维4:工程的复杂》

这一讲我们要说一个特别厉害的技能,叫做“软件工程”。以我之见,软件工程,可以说是工程管理和综合治理手段的极限。我希望你能从这一讲体会一下如何治理最复杂的系统。

可能你是一个产品经理,主导开发过一款APP。可能你是个企业家,管理一个几万人的大工厂。可能你是个土木工程师,设计过一座跨海大桥。你非常厉害,咱们中国有很多这样的厉害人物。中国是手机 APP 开发大国,中国有很多超大型企业,中国有全世界最长的跨海大桥 ——可是为什么中国就没有属于自己的计算机操作系统呢?为啥国产芯片不行呢?

因为那些事儿,跟现代软件工程相比,还只能算是简单的事儿。

程序员、CEO、计算机科学家,如果是拍一个超级英雄电影的话,这些人都可以是前台的英雄人物。但是躲在幕后操纵世界的,则将是一位、或者几位,软件工程大师。有句话叫“在计算机科学里,软件工程这一部分,对计算机科学家来说太难了。”

不了解软件工程,你就不知道什么叫“大”,什么叫“复杂”。

1. 小和大

编程是个非常适合自学成才的项目。很多人不是科班出身,自学编程技术,也容易找到一个程序员的职位,甚至还可以自己开发一个小软件。

但仅限于小软件。比如你可以自己写一个电子邮件客户端程序,或者写一个视频编辑工具。可是如果要开发一个超大型软件,其中涉及到的学问,可就不是自学所能达到的了,那是需要在重大项目的实践中去领悟和提高的。自学也许可以让你成为一个优秀的侠客,而伟大的将帅,则只能用千万士兵的鲜血铸就。

这里面的关键是一个尺度问题。大,是不一样的。

计算机刚刚出来的时候,程序员都是身上有修士气质的手艺人。编程者经常是孤独的,能说天书一样的语言,想法高深莫测,写出来的代码仿佛有一种暴力美学,他们的眼睛跟显示器一起在黑暗中闪闪发光。编程,是一项神秘的技能。

那时候的程序都是完全自由的 —— 计算机很贵,而程序不要钱。程序员们就好像十九世纪的艺术家一样,偶尔弄个俱乐部或者小作坊,彼此欣赏。

不过这个艺术时代并没有持续多长时间,程序员们很快就陷入了极度的悲观情绪之中。因为……错误。

写代码太容易出错了!代码越写越长,出错的频率不成比例地增加。可能你今天费了很大力气好不容易运行通过了,过了几天、遇到一个没想到的情况,发现还有一个隐藏的错误。有个程序员甚至说,他意识到,也许他的余生,都要在纠正自己的错误中度过……

程序员们终于明白,他们需要工程师思维。

我们之前讲了一些计算机科学的思维,而工程师思维和科学家思维至少有三个重大区别。

第一,科学家是寻找事物的规律,而工程师是去设计一个东西。
科学家只要觉得这个规律有意思就可以发表,而工程师得负责任。他得确保这个东西不但要有用,而且还得安全不出事,还得考虑成本,讲究可行性,让人用得上还用得起才行。

第二是对知识的态度。
科学家面对知识,是把自己当成一个没有利益攸关的旁观者,感觉看懂了、能总结出规律就行。而工程师,则是参与者。他不能仅仅“懂”这个知识,他是要拿来用的。

第三是对模型的使用。
科学家喜欢简化的模型,能抓住实质就行 —— 爱因斯坦有句名言说“什么东西都要越简单越好,要简单到不能再简单为止”。而工程师必须考虑所有的细节,“魔鬼在细节中”是工程师的座右铭。

要把写程序上升到工程的高度,跟以前那种兴趣爱好式的编程可就完全不同了。更进一步,软件工程和传统的工程也不一样。

比如你要修个桥,工程过程中哪里犯个小错误,通常也就是小错误 —— 最多也就是让大桥的质量降级。这座大桥总共有15个桥墩,其中第五个桥墩有个地方没建好,这座桥大致上还能用。但软件就不一样了,程序中的一个小错误很可能就会导致整个系统的崩溃。

这是为啥呢?因为软件不但各处的关联非常密集,而且是个“活”的东西。比如发射火箭,软件是要控制火箭做动作的!哪个动作不对,火箭立即失控。

所以软件不但是个工程,而且比传统工程难得多。那怎么应对这种复杂呢?

2.小思维

早期的软件开发者想出了很多工程化的办法,起到了一定的效果。比如以前都是用汇编语言,后来发明了高级编程语言,程序员就不容易出错……当然,这时候也不需要程序员个个都有修士的气质了。

最重要的一个方法,是把常用、好用的代码封装起来,重复使用。如果这段代码总是被用到,已经被大家测试过很多次了,证明没有毛病,那就不要再改来改去搞定制了,我们应该把它封装成一个“库函数”。库函数具有标准化的输入和输出,程序员下次再用的时候只需要照顾好输入输出,而不必关心函数内部是什么情形 —— 这就能大大降低出错的概率和提高编程的效率。

封装这个思想可以用在软件的各个方面。数据结构、面向对象的编程、文件系统,这些都是封装和分层。这一层的编程不用考虑底下一层的逻辑。

操作系统的内核也是一个类似的智慧。操作系统把最常用的操作计算机的动作,都事先在内核中预备好,而内核经过千锤百炼,不容易出错。等到别人写应用软件的时候,用到相关的动作,就只要调用内核就行,而不必自己直接操作计算机。这就相当于把专业的事儿交给专业的人,也就不那么容易出错了。

所有这些思想都要求对软件开发有个宏观的设计,而不只是吭哧吭哧写代码。然后你还得考虑多个人一起开发一个软件的情形,比如最起码得有个版本控制之类。

到这一步,软件业才算正式成了一个行业。在上世纪五十年代,就已经有公司专门开发软件卖钱。

……可惜这些还远远不够。

软件业从一开始就不是一个做事漂亮的行业。项目总是再延期。好不容易交付了,软件卖出去之后又总是被人发现各种毛病和错误。客户不满意,可是如果真要搞什么售后服务,到现场去给人解决问题,那几乎就是不可完成的任务……而且还有黑客攻击、还有计算机病毒!

我很早以前听过一个笑话,说一个软件工程师嘲笑一个汽车工程师,说“如果汽车行业像计算机行业一样发展,现在汽车应该一毛钱一辆。”但是汽车工程师不以为然,说“可是谁会要一辆动不动就抛锚的汽车呢?”

而早期的软件公司,对此只有两个不是办法的办法:

  • 尽量去找那些经验丰富、头脑聪明的高水平程序员
  • 销售软件的时候干脆附带一个免责声明:如果因为这个软件的毛病给您造成了损失,我们概不负责。

社会对计算机的美好幻想被打破了,软件行业陷入了危机。

3.大思维

软件工程的问题不是你每年能培养多少高水平程序员的问题,而是复杂性问题。

小软件和大软件的根本区别在于尺度。以前一个小软件只有几千行代码,现在一个大软件要有几百万行代码。以前的软件是给一个人用,现在是多个用户共同使用一个软件。更重要的一点是,以前的软件是一个人或者几个人开发的,现在则是大型团队一起开发。

计算机思想家弗瑞德里克·布鲁克斯(Fred Brooks),曾经在上世纪六十年代末率领IBM公司300人的团队开发操作系统。他做完这件事之后很有感触,为此专门写了一本书,叫《人月神话》。

布鲁克斯提出两个感慨:

  1. 1个人干12个月的活,绝对不是12个人在1个月内能干完的。项目用的程序员越多,平均每个人出活的速度就越慢。所以你规划项目的时候不要算什么“人月”。

  2. 你这个团队做出来的软件的结构,往往和你这个团队的人员组织管理结构高度相似。所以软件工程不但要管项目,还要管人。

布鲁克斯这本书出来,人们才充分认识到软件工程的难度。现代软件工程要求,软件产品必须达到下面这五个目标,称之为“DRUSS”

  • Dependable:可信赖,让顾客真能指望上你这个软件
  • Reliable:得可靠,不能总出毛病
  • Usable:软件是给人用的,得让人能够上手
  • Safe:用的时候不能出安全事故
  • Secure:它得不容易被黑客攻击才行

现代主流操作系统,包括 Windows, Mac 和 Linux,各自都有接近一亿行代码,而且大致实现了这五个方面的要求。而即便是这三个可以说是最成熟的软件系统,其中仍然还有大量的毛病。

那怎么才能获得这种大型软件工程的能力呢?我们前面说的办法都还是小软件思维,剩下的,就只有一些经验之谈,而没有什么特别系统的行动指南了。

比如说,在系统安全方面,软件开发的首要原则是默认不给用户授权。如果非要授权用户接触一个什么东西,就必须得有显性的授权;每个程序进程只能拥有最有限的授权,等等。软件工程就是由这些原则、工作中遇到的规律、前辈传下来的经验组成的。

技术进步能解决一定的问题,比如更多的分层封装,搞虚拟机,客户端和服务器,高级编程语言,交互式开发环境,可视化的控制和数据流,更好的操作系统等等……但是技术解决不了所有的问题。

1987 年的时候,布鲁克斯写了一篇文章叫《没有银弹》,又提出一个洞见:软件工程的根本问题,是人的问题。主导软件开发的这个人,必须得能够理解高度复杂的东西才行。

写程序是永远在更新的技术,软件分为很多层,会出现各种毛病,你得确保产品满足 DRUSS 五方面的要求,你得操很多的心……你得能驾驭复杂。

像这样的人才,都是绝对的帅才。这就好比带兵打仗,你不用说指挥十万人打仗,你能把十万人安全带到战场,不哗变、不闹事、都能吃饱饭就不错了。

布鲁克斯有句名言是这么说的

“好的判断来自经验,而经验来自坏的判断。”(Good judgement comes from experience, and experience comes from bad judgement.)

正所谓一将功成万骨枯,驾驭大型软件工程的能力,只能通过大型软件工程培养出来。

我们前面讲《生命视角》的时候说过,有些创新能力难复制 —— 因为它是长出来的。我们中国有很多软件开发者,但是我们缺少操作系统这种级别的大型软件开发积累。我们有几代程序员试炼出来的库函数吗?我们有 Windows 3.1,Windows 95 的种子吗?我们有前辈开发者总结出来的原则、规律和教训吗?我们有自己的标准和规范吗?

软件每天都在更新,但软件工程的背后,是一棵经年累月长出来的大树。

我们这一讲正好赶上最近美国要封锁华为公司,而华为正在搞自己的手机操作系统。在软件工程上另起炉灶是一个几乎不可想象的任务,但是如果真有那样的机会,那就是现在。

咱们倒要让美国人看看,中国公司有没有驾驭复杂的能力。

看看自己是不是一个靠谱的程序员,来做题试试。job.xyh.io
附言 1  ·  4年前
Kingmax
讨论数量: 9

看得云里雾里,明白了「复杂」以及「架构」的重要性,可是这篇文章的具体内容真的能够体现出开头的描述吗:

可是为什么中国就没有属于自己的计算机操作系统呢?为啥国产芯片不行呢?因为那些事儿,跟现代软件工程相比,还只能算是简单的事儿。

另外,本文举了几个函数封装、面向对象基础概念、版本控制的问题,这些问题在如今几乎成了优秀程序员的基本功、各大厂商的一轮面试题,解决方案成熟稳定,我实在是做不到:

我希望你能从这一讲体会一下如何治理最复杂的系统。

最后,我极其不赞同:

编程是个非常适合自学成才的项目。很多人不是科班出身,自学编程技术,也容易找到一个程序员的职位,甚至还可以自己开发一个小软件。但仅限于小软件。

非科班出身 ≠ 学习能力差,自学编程 ≠ 实践历练少;如此妄断「但仅限于小软件」,有失偏颇。

因此不吐不快,如有过激还请谅解。

4年前 评论
Mumujin 4年前
巴啦啦

小哥哥,这个 url 是你们的后台吧?还是 Apache 搭载 PHP5 的吗?似乎用的不是 Laravel呀,也没做 csrf 的吧? :joy:

4年前 评论

看得云里雾里,明白了「复杂」以及「架构」的重要性,可是这篇文章的具体内容真的能够体现出开头的描述吗:

可是为什么中国就没有属于自己的计算机操作系统呢?为啥国产芯片不行呢?因为那些事儿,跟现代软件工程相比,还只能算是简单的事儿。

另外,本文举了几个函数封装、面向对象基础概念、版本控制的问题,这些问题在如今几乎成了优秀程序员的基本功、各大厂商的一轮面试题,解决方案成熟稳定,我实在是做不到:

我希望你能从这一讲体会一下如何治理最复杂的系统。

最后,我极其不赞同:

编程是个非常适合自学成才的项目。很多人不是科班出身,自学编程技术,也容易找到一个程序员的职位,甚至还可以自己开发一个小软件。但仅限于小软件。

非科班出身 ≠ 学习能力差,自学编程 ≠ 实践历练少;如此妄断「但仅限于小软件」,有失偏颇。

因此不吐不快,如有过激还请谅解。

4年前 评论
Mumujin 4年前
绝缘体菜狗

不错哦,好文呢,最近这段时间估计真是拖华为的福,让大伙都在反思大跃进,不管是视频,还是文章,都看到不少干货。

4年前 评论

我居然 全部看完了。

4年前 评论

新招聘站似乎不错~看得出来有用心。

4年前 评论

投了几次都没有面试。

4年前 评论
Kingmax

哈哈,管理员小哥有留意我们的招聘站,非常荣幸。

4年前 评论

中国没有自己的操作系统主要是因为生态

4年前 评论
lmaster

file

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!