《软件随想录》读书笔记

副标题:程序员部落酋长Joel谈软件

原作名: More Joel on Software
译者: 阮一峰

第一部分 人员管理


1 找工作

这条规律(优秀的人才从不在市场上求职)有一个推论,那就是在人才市场上找工作的,大部分都是一些水平很差、完全达不到要求的人

2 办公

办公环境

① 针对程序员

大量证据表明,给予程序员独立的办公室会显著提高他们的工作效率。我在自己的网站上也不断重复这一点。但是尽管如此,硅谷的流行做法却是要求创业者将大量程序员塞进一个巨大的开放空间中。

② 针对老板

没错。这种大模大样的作秀在硅谷相当常见,CEO 装得像平头老百姓一样,在一间小隔间里工作,但是某处还有那么一间会议室,他往往会占为己有。(虽然他解释“只有讨论不能公开的事情,才会使用会议室”,但是当你经过那间会议室,有一半的时间,你会看到你的 CEO 在里面,独自一人,通过电话与他的高尔夫球伙伴侃佩而谈,把他穿着 Cole Haans。名牌皮鞋的脚搁在会议桌上。)

“你的公司的成功依赖于程序员真正以办公室为家的程度。如果要让办公室成为程序员的共同选择,最好让它比普通程序员的家更舒适

戴耳机

为什么戴上耳机隔绝噪音被证明会降低程序员的工作质量

有点反常识

3 开会

我都说不清楚有多少次,我和其他程序员在一起开会,有时甚至不超过两个人,我们试图讨论软件应该怎么运作,但是总是毫无成果。我只好回到自己的办公室,拿起一张纸,一个人把它琢磨出来。同其他人互动总是使我难以集中注意力,无法全神贯注地设计出我想要的功能

最让我抓狂的就是有些开发团队养成了一个坏习惯,每次需要做决定的时候就要开会。你有没有试过一边参加会议讨论,一边写诗?这就像一批肥胖的建筑工人一起研究怎样写一出歌剧,但是他们同时还躺在沙发上看着电视剧 Baywatch。坐上沙发的胖子越多,他们就越不可能写出歌剧。

同感 我就是这样的人 需要一个人想

4 招聘(别人)

公司的招牌

作为一个负责招聘的人,你要做的是找出你的公司中理想主义的一面,确保招聘对象了解它们

管理好你的公司的品牌不仅对营销很重要,对招聘新人也同样重要。

待遇制定

我们说程序员不在乎钱并不意味你可以向他们支付低工资

5 管理

错误做法
  • 1 军事化管理法

① 为什么不好

  1. 首先,人们并不喜欢被这样管,尤其是那些对智商很自负的程序员

  2. 军事化管理法的另一个缺点是操作层面的,就是说,没有足够的时间用在微观管理上,原因很简单,因为经理的人数不够。在军队中,同时向一大群人发布一道命令是可行的,因为军队的通常情况就是每个人都在做同一件事。你可以向一个排的 28 个人大吼一声“擦枪”,然后打个盹
    ...
    所以如果想进行微观管理,就会变成“打了就跑”(hit-and-run)的抽风式管理。
    ...
    从效果上看,你起到的所有作用只不过是每隔一会儿就将你手下的可怜程序员敲打一番,

  3. 第三个缺点是,在高科技公司中,负责干活的个人总是比“领导者”有更多的信息,所以他们其实是做决策的最佳人选

② 总结

换句话说,军队使用军事化管理,因为这是唯一的办法,可以使得 18 岁的年轻人在地雷阵中发起冲锋,而不是因为军方认为这是适用于所有情况的最佳管理方法。

  • 2 经济利益驱动法

“经济利益驱动法”假设每个人的行为动机都是金钱,让人们听命于你的最好方法就是给他们物质奖励或者物质惩罚,以此创造行为动机。

① 为什么不好

  1. 他们实际上不在乎钱,除非你在其他事情上搞砸了。

如果你开始听到有人在抱怨薪水,而以前并没有出现这种情况,这经常就是一种信号,表明人们并不真地喜欢他们的工作。如果你想雇的新人提出高得离奇的薪水要求,并且不愿意降低,那么你可能遇到的是这样一种情况,那些人心里想:“好吧,如果不得不接受这份糟糕透顶的工作,那么我至少应该有一份优厚的报酬。”

再比如,一个软件公司给编程错误最少的程序员发奖金。

这种方法的一个重大问题是,它内部激励(intrinsic motivation)变为了外部激励(extrinsic motivation)

内部激励是指你内心想将事情做好的天然愿望。
外部激励是指来自外界的激励,有人付钱让你干某事就是外部激励。

但是当你出钱让人们去做那些无论如何他们都想做的事情时,他们就会受到一种叫做“过度合理化效应”(Overjustification Effect)的支配。“我要写出没有 bug 的代码,因为我喜欢钱,我想要奖金。”他们会这样想。外部激励就取代了内部激励。因为外部激励是一种弱得多的激励,所以最终结果就是,你实际上降低了他们做出优异工作的愿望。当你停止支付奖金或者他们变得不太在乎钱时,他们就不再关心自己写出的代码是否没有 bug 了。

  1. 经济利益驱动法的另一个大问题是,人们有追求局部利益最大化(1ocl maxima)的倾向。他们会想出办法将你支付给他们的报酬尽量最大化,但是实际上却没有达到你真正想要的结果

如果你使用经济利益驱动法,你就是在鼓励程序员与制度博弈。

Robert D. Austin 写过一本书《组织绩效评估与管理》(Measuring and Managing Performance in Organizations)。书中提到,当你引入新的绩效测量方法时,会有两个阶段的发展。第一阶段,你实际上得到了你想要的东西,因为还没人想出作弊的方法。但是,到了第二阶段,你实际上让事情变得比原来更糟,因为每一个人都想出了如何将你测量的指标值最大化的对策,即使代价是毁掉公司,他们也在所不惜

这也是国家兴衰的原理 不可避免的

更糟糕的是,信奉“经济利益驱动法”的经理们认定,他们只要不断地调整指标就可以避免上述情况。Austir 博士的结论是,这样的想法是行不通的,它最终不会起作用。无论你多么努力地试着调整指标,力求让它们正确地反映你想得到的结果,最终一定事与愿违。

“经济利益驱动法”的最大问题是,它其实根本不是一种管理,更像是管理的退位,或者说是一种设计精巧的推卸责任的方法,不愿承担责任找到办法将事情做得更好。它是一个信号,表明管理层根本不知道如何引导人们做出更好的工作,所以他们强迫每个雇员在制度框架下自己想办法将事情做好。

正确做法
  • 1 认同法

这样一来,只剩下一个办法了,我把它叫做“认同法”。这种管理方法的目标是,使得人们认同你希望达到的目标

它实施起来比其他方法得多,而且还需要一些很不简单的人际沟通的技巧。但是,如果你真地做到了,它的效果就比其他方法好得多。

① 为什么好

  1. 前面说过了,经济利益驱动法的问题是,它将内部激励变成了外部激励。认同法的作用恰恰就是设法创造出内部激励

② 怎么做

  1. 如果公司的目标确实在某种程度上是高尚,或者至少在别人看起来是高尚的,那么肯定有助于人们产生认同感。

1984 年,苹果公司在超级碗决赛时,播出了一则广告。就是从那个时候起,苹果公司几乎创造出一种狂热的认同,它靠的差不多就是不停地讲:我们反对极权主义。这种话看上去是不是好像夸夸其谈?但是它的确起作用!

  1. “认同法”的第二部分则是向人们提供必要的信息,使得公司向正确的方向前进。

参与了解, 而不是被蒙在鼓里的服从

硅谷的管理风格

海岸高科技公司的通常做法正好相反。我在西海岸生活的那段日子让我习惯了这样一种看法,即管理只是一种不得不做、让人厌烦的杂务活,之所以公司需要管理,就是为了不影响聪明人的工作,让他们把事情做完。在一个研究型大学里,系主任实际上是一种负担,没有人真想千,大家都更愿意去做研究。硅谷式风格的管理正是这样。经理存在的唯一理由就是把家具的位置摆好,不要挡道,只有这样,真正的天才才能做出优秀的成果

第二部分 写给未来程序员的建议


1 学校只教 Java 的危险性

很多学生会说 毕业后用的都是 java, 学校有必要学 c 等古老语言吗

    1. 为了降低难度

好处:

主管,大概会很喜欢这样。最妙不可言的是,Java 语言中没有什么太难的地方,不会真地淘汰什么人,你搞不懂指针或者递归也没关系。所以,计算系的淘汰率就降低了,学生人数上升了,经费预算变大了,可谓皆大欢喜。

Java 语言不够难其实是它的特色,不能算缺点。

坏处:

我再告诉你一件事。1900 年的时候,拉丁语和希腊语都是大学里的必修课,原因不是因为它们有什么特别的作用,而是因为它们有点被看成是受过高等教育的人士的标志。

在某种程度上,我的观点同拉丁语支持者的观点没有不同(下面的四点理由都是如此):“(拉丁语)训练你的思维,锻炼你的记忆。分析拉丁语的句法结构是思考能力的最佳练习,是真正对智力的挑战,能够很好地培养逻辑能力。”以上出自 Scott Barker 之口(htp: /www. Promotelatin. org/whylatin.htm)。但是,今天我找不到一所大学还把拉丁语作为必修课。指针和递归不正像计算机科学中的拉丁语和希腊语吗?

  • 2 用不上

好处:

说到这里,我坦率地承认,当今的软件代码中 90%都不需要使用指针。事实上,如果在正式产品中使用指针,这将是十分危险的。好的,这一点没有异议。与此同时,函数式编程在实际开发中用到的也不多。这一点我也同意。

坏处:

但是,对于某些最激动人心的编程任务来说,指针仍然是非常重要的。比如说,如果不用指针,你根本没办法开发 Linux 的内核。如果你不是真正地理解了指针,你连一行 Linux 的代码也看不懂,说实话,任何操作系统的代码你都看不懂

如果你不懂函数式编程,你就无法创造出 MapReduce,正是这种算法使得 Googlet 的可扩展性(scalable)达到如此巨大的规模。

除了上面那些直接就能想到的重要性,指针和递归的真正价值在于那种你在学习它们的过程中所得到的思维深度,以及你因为害怕在这些课程中被淘汰所产生的心理抗压能力,它们都是在建造大型系统的过程中必不可少的。指针和递归要求一定水平的推理能力、抽象思考能力,以及最重要的,在若干个不同的抽象层次上同时审视同一个问题的能力。因此,是否真正理解指针和递归与是否是一个优秀程序员直接相关。

  • 3 面向对象语言才是未来

好处:

开发起来当然更容易

坏处:

(我不是指面向对象式的“设计”,那种编程只不过是要求你花上无数个小时重写你的代码,使它们能够满足面向对象编程的等级制继承式结构,或者说要求你思考到底对象之间是“has-a”从属关系,还是“is-a”继承关系,这种“伪问题”将你搞得烦躁不安。)你需要的是那种能够在多个抽象层次上同时思考问题的训练。这种思考能力正是设计出优秀软件架构所必需的。

你也许想知道,在教学中,OOP (Object-Oriented Programming,面向对象编程)是否是指针和递归的优质替代品,是不是也能起到淘汰作用。简单的回答是“不”。我在这里不讨论 OOP 的优点,我只指出 OOP 不够难,无法淘汰平庸的程序员。大多数时候,OOP 教学的主要内容就是记住一堆专有名词,比如“封装”(encapsulation)和“继承”(inheritance)., 然后再做一堆多选题小测验,考你是不是明白“多态”(polymorphism)和“重载”(overloading)的区别。这同历史课上要求你记住重要的日期和人名的难度差不多。OOP 不构成对智力的太大挑战,吓不跑一年级新生。据说,如果你没学好 OOP,你的程序依然可以运行,只是维护起来有点难。但是如果你没学好指针,你的程序就会输出一行段错误信息,而且你对什么地方出错了毫不知情,然后你只好停下来,深吸一口气,真正开始努力在两个不同的抽象层次上同时思考你的程序是如何运行的。

正如 Steve Yegge/所指出的,Java语言是“名词王国

说到这里,就引出了我职业生涯中的一个重要发现。周而复始地,你会注意到,当程度员遇到问题的时候,他们会把问题重新定义,使得这些问题可以用算法解决。这样一来,问题转化成他们可以解决的形式,但是实际上,那些问题是一种“琐碎”问题。也就是说,程序员解决的只是问题的某种外在形式,而并没有解决真正的问题,原因是这些问题非常难,不是表面的算法可以概括的。

2 技术派和务实派

从这个角度看,计算机界可以分成技术派(geek)和务实派(suits)两大类。

作者是挺务实派的

区别
  • 1 关于质量管理的差异

① 各方表现

技术派想要把质量问题用软件自动处理。为了这个目的,他们发明了单元测试 (unit testing)、测试驱动开发方法(test-driven development)、自动测试(automated testing)、动态逻辑等,目的只有一个,就是“证明”程序中没有错误。

务实派并不真地关心质量有没有问题。只要有人愿意出钱购买软件,他们才不想关心代码中有没有错误。

② 务实派的优势

当前,在技术派与务实派的大战中,务实派是获胜的一方,因为他们控制了公司的预算。老实说,我不觉得这是一件很糟糕的事情。务实派认识到,消灭软件代码中的错误是一件边际报酬递减的事情。一旦软件的质量达到了一定的水准,能够用来解决特定的问题,那么就会有用户从这个软件中获益,用户也会因此愿意出钱购买。

同时,务实派对于“质量”有一个更广义的定义。你尽管大胆地想象,这个定义完全符合利益原则。所谓软件的“质量”,就是看它能为大家带来多少奖金,奖金越多,也就表明软件的质量越高。出人意料的是,“质量”的这种定义有深得多的内涵,远不止于写出没有错误的代码。

③ 技术派的劣势

不要误解我,单元测试本身并不坏,当你运行完所有的单元测试,就可以机械式地“证明”一个程序是“正确的”。但是,这样做的不利之处是,任何不能被自动测试的东西就会被排斥在质量的定义之外,变成与软件质量无关。即使我们明知用户更喜欢看上去很漂亮的软件,但是因为没有办法自动评估一个软件看上去到底有多漂亮,所以软件的美观就被排斥在自动化 QA 过程之外。

标准的制定真的很重要, 就像 GDP 虽然好, 但也带来了盲目的追求导致负效应

所以,总而言之,如果真有一种机械方法可以证明软件程序的正确性,那么实际上你所能证明的只是现有的程序是否同某些其他程序完全一模一样。也就是说,后一个程序同前一个程序一定必须包含同样数量的熵。否则的话,证明对象中一定有一些行为没有被定义,因此也就无法证明。这样就会导致写出一个设计规格说明书等价于写出一个程序。你的行为的所有意义仅仅是把一个问题从这里搬到了那里,你实际上什么也没有做。

这样的例子看上去有点太残忍,但是虽然如此,许多程序员还是热衷于寻找如何验证软件质量的圣杯® (holy grail),许多人白白走了许多弯路。

还是不要太完美主义

3 对计算机专业学生的 7 条建议

二话不说,下面就是 Jol 针对计算机专业学生的 7 条免费建议。(绝对超值哦。)

 (1) 毕业前练好写作。

 (2) 毕业前学好 C 语言。

 (3) 毕业前学好微观经济学。

 (4) 不要因为枯燥就不选修非计算机专业的课程。

 (5) 选修有大量编程实践的课程。

 (6) 别担心所有工作都被印度人抢走。

 (7)找一份好的暑期实习工作。

 我会一一解释这 7 条建议。如果你头脑简单到我说什么你就做什么,那么你就不必读下去了。在这种情况下,我还要加上一条:

 (8) 寻求专业人士的帮助,培养你的自信心。
  • (1) 毕业前练好写作
  1. 那些决定游戏规则的人都是善于写作的人。

为什么C语言是最流行的语言,原因就是创始人 Brian Kemighan 和 Dennis Ritchie 写了一本伟大的书《C 程序设计语言》。

如果不是 Linus Torvalds 不断地散布福音,请问 Linux 操作系统会成功吗?虽然他是一个非常聪明的计算机天才,但是 Linus 吸引来全世界一大批志愿者的真正原因却是 Linus Torvalds 的表达能力。他通过电子邮件和邮件列表用书面形式传播自己的想法,最终引起了所有人的注意。

  1. 一个普通程序员与一个优秀程序员的区别,不在于他们懂得的编程语言谁多谁少,也不在于他们喜欢用 Python 语言还是喜欢用 Java 语言,而在于他们能否与他人交流思想。如果你能说服其他人,你的力量就可以得到放大。

  2. 如果你能写出清晰的注释和技术规格说明书,其他程序员就能够理解你的代码,因此他们就能在自己的代码中使用,而不必重写。如果你做不到这一点,你的代码对其他人就没有价值。如果你能为最终用户写出清晰的使用手册,其他人就能明白你的代码是用来干什么的,这是唯一让别人明白你的代码有何价值的方法。SourceForge上有许多优美的、有用的代码,但是它们都像被埋葬了一样,根本没人来用,原因就是它们的作者没有写好使用说明(或者压根就没写)。这样一来就没有人知道他们的成果,他们杰出的代码就衰亡了。

  3. 我注意到,微软公司中那些真正优秀的程序经理都是具有优秀写作能力的人。

  4. 如果一个程序员不会用英语写作、没有良好的写作能力,我就不会雇他。如果你能写,不管你去哪家公司工作,你很快就会发现写作技术文档的任务会落到你头上,这意味着你已经开始在放大自己的影响力了,管理层正在注意到你

对晋升也有帮助。

  • (2) 毕业前学好 C 语言

来说再自然不过的事情,那么你就是在盲目无知的情况下编程。在我看来,这就好像一个医生不懂得最基本的解剖学就在开处方,他看病的根据完全是因为那些娃娃脸的医药厂商销售代表说这种药有用。

  • (3) 毕业前学好微观经济学

不管怎样,你一定要去学微观经济学,因为你必须搞懂供给和需求,你必须明白竞争优势,你必须理解什么是净现值(PV),什么是贴现,什么是边际效用。只有这样,你才会懂得为什么生意是现在这种做法。

为什么计算机系的学生也应该学经济学?因为,从经营一家公司的角度来看,比起那些不懂的程序员,一个理解基本商业规则的程序员将会更有价值。就是这么简单。我无法告诉你有多少次我是那样地充满挫折感,因为我看到了太多的提出一些疯狂的想法的程序员,这些想法在代码上也许可行,但在资本主义世界中毫无意义。如果你懂得商业规则,你就是一个更有价值的程序员,你会因此得到回报的,但是前提是你要去学习微观经济学。

  • (4) 不要因为枯燥就不选修非计算机专业的课程

为什么我要关心某人的“欧洲历史”课程成绩呢,毕竟作为雇主我要找的应该是程序员啊?何况,历史是那么枯燥,不得高分很正常。哦,这么说来,你的意思是我应该雇用你,而不用考虑一旦工作变得枯燥你会不会努力工作?别忘了,在编程工作中也有很枯燥的东西。每一项工作都有枯燥难耐的时刻。我不想雇用那些只想干有趣事情的人

  • (5) 选修有大量编程实践的课程

作为一个程序员,你可能只能选择计算机科学专业。这是一个不错的专业,但是它同软件开发不是一回事。

此学会了如何写作一样。它们是你能找到的最佳课程。如果你喜欢编程,可是学校里上的都是入演算或者线性代数这种连电脑的边都摸不到的课程,假定你不明白这些课程的意义,你也不要因此心情恶劣。在那些 400 等级的课程代号中,去寻找名称中带有“Practicum”这个词的课程。

  • (6) 别担心所有工作都被印度人抢走。

  • (7)找一份好的暑期实习工作。

  • (8) 寻求专业人士的帮助,培养你的自信心。

第三部分 设计的作用


1 UNIX vs. Windows

用户界面功能之间的关系

我举一个很小的例子,向你们说明 UNIX 和 Windows。之间的文化战争。“UNIX 文化”倡导将用户界面和功能分隔开来

形成鲜明对照的是,在“Windows 文化”中,第一步总是先写出 GUI(图形用户界面),所有核心功能与用户界面的代码联系之紧密足以让入感到绝望

不论从什么角度看,这两种文化的差别大致上就是阳春白雪下里巴人之间的差别。

事实上,它很精确地反映在全国各个计算机系的课程设置上。在常春藤联盟(Ivy League)的院校中,只教授 UNIX、函数式编程、状态机② (state machine)理论。当你顺着排名的顺序往下看到那些越来越少人问津的学校,你就会看到 Java 语言开始在课程中出现了。你再往下看,大概就会看到有-一些课程起了这样的名字:Microsoft Visual Studio2005 的 101 课程,3 个学分。等到你看到 2 年制学院的部分,会发现有些课程的名字,同“21 天 SQL Server 证书课程”差不多,简直如同周末有线电视中的广告一样。想找好工作吗?现在正是你最好的时机开始学习(另一个声音出来说)Java Enterprise Beans!

② 字体渲染

目前,这两家公司都使用次像素渲染(subpixel rendering)技术,使得字体在低分辨率的屏幕上也能显得很清晰。这两家公司的根本不同之处在于指导思想

苹果公司通常认为,字体算法的首要目的是尽可能多地保持原始设计的样子,即使有损屏幕显示的清晰性,也在所不惜。

微软公司通常认为,字体的形状一定要适应像素的限制,要保证屏幕显示不模糊、容易辨识,即使字体的形状因此背离原始设计,也在所不借

2 用户界面 vs. 社会化界面

用户界面的设计目标是帮助用户能够成功操作

而社会化界面的设计目标是帮助人与人之间的社会关系能够成功运作,即使这意味着必须要冒犯某个特定的用户。

当你在编写充当人与人之间的中介的软件时,做好易用性设计以后,下一步你就必须做好社会化界面的设计。而且,社会化界面比易用性设计更重要。如果社会化界面一塌糊涂,那么就算你有世界上最好的用户界面,你的软件也活不了。

展望下一个十年,我期待软件公司会雇用受过人类学家(anthropologist)和人种学家(ethnographer)训练的人,请他们参与社会化界面的设计。他们采用的方法不是兴建易用性实验室,而是走向室外,开展田野调查,写出人种调查报告(ethnography)。但愿我们会找到社会化界面设计的一些原则。那一定非常迷人…就像 20 世纪 80 年代用户界面设计刚刚兴起时那样有趣…所以,敬请期待。

软件实现上的小细节会导致在线社区发展、运作、用户体验上的大差异

3 tips

别给用户太多选择

们。正常情况下,我们美国人认为选择越多,我们就会越幸福(宽松式的裤子还是休闲式的裤子)。但是 Schwartz 告诉我们,事实正好相反,他认为太多的选择实际上损害了我们内心的幸福感。”

这个道理放在任何领域都适合

简约不一定简单

iPod 的设计似乎是最容易复制的东西,但是做起来却又不是那么容易,你看看微软试图仿效 iPod 的例子,就会明白这一点。做出优秀的设计本身就是一件“麻烦事”,实际上能够提供牢固得令人震惊的竞争优势

简化性的拥护者会举出 37 signals 和苹果公司 iPod 播放器作为津津乐道的证据,证明简化的产品十分畅销。我会争辩说,在这两个例子中,商业成功来自于许多因素的共同作用,比如培养追随者、传播理念、简洁明快的设计、感情上的诉求、美学成就、很短的反应时间、及时的用户反馈、与用户行为(user model)相对应的程序模型(program model)、整体上高度的易用性、让用户感到控制权都在自己手中等。所有这些因素都是用户非常喜欢、愿意为之付钱的优点,从这个角度看,它们都可以被视作产品的某种“功能”。但是,它们中没有一种可以被看作是“简化性”的表现。比如,iPod 是一种优美的产品,这也算是一种“功能”

第四部分 管理大型项目


1 关于网页标准

网页标准的乱象

犹太人中的极端正统派(ulra-orthodox)完全同意并且坚决地实践犹太宗教经典中的每一个字。但是,如果你去过耶路撒冷的那些极端正统派的犹太社区,你就会发现,你根本找不到任何一个社区的拉比愿意去吃另一个社区的拉比家中的食物,尽管犹太人对于什么是“清洁的”食物并没有分歧。网页设计师现在的处境,其实住在 Mea Shearim 区的犹太人早在几十年前就体会到了,那就是所有人都同意遵守同一部经典并不能保证所有人的行为都符合同样的规范。因为法条太复杂、太深奥、太难懂了,想要完全正确地理解法条几乎是不可能的,难免会落入陷阱或遇到地雷,所以比较安全的做法就是,你到别人家中做客的时候只吃水果。

这个问题产生的根源可以追溯到 1981 年,当时 Jon Postel 提出了鲁棒性原则(robustness principle):“对于己方的行为要保守(conservative), 对于他方的行为要宽容(liberal)。”(tools.ietf.org/html/rfc793)他想说的意思是,让一个协议健壮地运行的最好方法就是,每个人都要非常非常小心地让自己的行为符合规范,而且同时在与合作伙伴进行信息交换时,又要采取极端宽容的态度。也就是说,只要你能猜出对方的意思是什么就可以了,不用苛求对方的行为一定要符合规范。

现在,网上到处都是有错误的网页,原因就是所有早期的浏览器开发者制造出了超级宽容、超级友善、无比包容错误的浏览器。

标准当然是很重要的,但是你不能迷信标准,你必须理解由于人会犯错,所以标准有时候会引发误解、困惑,甚至是争议。

第五部分 编程建议


1 工作规划的粒度

为什么软件开发者不太愿意做日程规划呢?有两个原因。第一个原因是做起来比较麻烦;第二个原因是,没人相信日程规划是可行的。如果一件东西可能是不对的,那又何必费事把它做出来呢?

如果日程规划是以“天”为单位,甚至以“周”为单位,我就认定它是没用的

你必须将日程规划先分解成一些非常小的任务,这些任务能够在以“小时”为单位的时间段中完成。不能有任何任务所需的时间超过 16 小时。

如:

2022-04-25-16-13-00

等到他完成了六七件真实的任务以后,他的数据就会逐步变得准确了。

2 关于匈牙利命名法

此为历史遗留问题, 不看也罢

应用型匈牙利命名法”的前缀是非常有用、非常有含义的,比如“ⅸ”表示数组的索引值(index),“c”表示一个计数器(count),“d”表示两个数量之间的差额(difference.)(例如“dx”就表示宽度),等等。

系统型匈牙利命名法”的前缀就差远了,比如“1”表示长整型(1ong),“ul”表示无符号的长整型(unsigned long),“dw”表示双精度值(double wod),这实际上也是一个无符号的长整型。在“系统型匈牙利命名法”中,名称的前缀能起到的唯一作用就是告诉你这个变量到底是哪一种数据类型。

这种差别很细微,但是完全误解了 Simonyif 的意图和做法。如果说这件事有什么教训,那就是如果你写出艰涩的学术性文章,没人能够理解,那么你的思想就会被误解,人们会把误解后的思想当作你原来的思想加以嘲笑,根本不管你原来的思想是什么样的。在“系统型匈牙利命名法”中,你会看到许多变量的名字类似 dwFoo,意思是“double word foo”(双精度变量)。看到这样的变量名时你简直就想骂街。告诉你一个变量是双精度值对你几乎没有任何用处。所以,人们抛弃“系统型匈牙利命名法”就毫不奇怪了。

结论: 匈牙利命名法的前缀应该指示它的应用含义, 而不是标明数据类型

大暴动在 ET 第一次发布的时候达到了高峰。微软最终做出了表态,“不推荐使用匈牙利命名法”。那时真是欢声雷动啊。

现在的IDE让匈牙利命名法没有太大必要了, 反而还是累赘

3 关于异常处理

在结束这个话题之前,我还要再做一件答应过的事,那就是再骂一次异常处理(exception)。我上一次开口骂的时候,惹来了一大堆麻烦。那是在 Joel on Software 的网站上,我写了一篇即兴评论,大意是我不喜欢异常处理,因为它本质上是一种无形的 goto,我指出为什么它比有形的 goto 更糟糕。

像可控异常(checked exception)这样的方法可以使整个过程变得比较容易。

要是我只是写一个小小的脚本程序,每天收集一次数据,然后把它打印出来,那么异常处理真是好用得不得了。我的日子不可能过得再轻松了,我不需要关心任何可能发生的错误,只要把所有烦心的代码用一个大的 try/catch包裹起来,如果发生错误,就向我发送Email,这样就一切OK了。异常处理对于那些随手写写的软件项目和脚本程序很好用,只要不是非常重要和关键性的代码,它都是适用的。

但是,如果你写的是一个操作系统,或者核电厂的管理软件,或者一个专用于心脏手术的高速电锯的控制程序,那么异常处理是极端危险的

我觉得作者并没有说服我, 关键也没有更好的替代方案

第六部分 开办软件公司


第七部分 经营软件公司


1 开发

关于找第三方库

作者的观点是最好自己写, 我觉得现在的时代要看情况, 未必
通过这件事,我学到了软件开发中重要的一课。那就是,对你最重要、最关键的部分,你一定要使用更原始的工具。举例来说,假定你正在写一个很酷的 3D 射击游戏(就像同样在那个时期出现的《雷神之锤》),你排在第一位的卖点就是生成最酷的 3D 图像。为了达到这个目的,你就不能使用任何你能找到的 3D 库。你一定要写一个你自己的 3D 库,因为这是达到你目的的基础。那些使用诸如 DirectX 这样现成的 3D 库的公司,只是因为他们的卖点不是软件的 3D 表现(也许他们有一个很好的故事)。

一个好的软件架构师只会使用那些“可以被信任”或“可以被维护”的工具。一种工具“可以被信任”,并不意味着它是由像 BM 那样可以被信任的大公司制造的,而是意味着你百分百确信它会正常运作

实事求是

2 如何做客服

客户来找客服是大好机会

记住,要是有客户打来电话,你要把这当作一个千载难逢的机会,一个可以培养出死心塌地的忠实客户的机会。如果你做得好,客户逢人就会唠叨你的服务是多么出色。

不过,我还没有变得那么激进,故意制造一些问题迫使客户打电话给我们,以便我们有机会向他们证明我们的客户服务是多么卓越。要知道,许多客户遇到问题的时候根本不打电话,他们就是在那里生闷气。

回复技巧

微软公司的 Raymond Chen 讲过一个小故事 (blogs.msdn.com/oldnewthing/archive/2004/03/03/83244.aspx)。有一次,客户打电话来抱怨键盘失灵,结果不出所料,原因是键盘没插好。但是,如果你直接问客户键盘有没有插好,他们会觉得受到了侮辱,怒气冲冲地回答:“它当然插好了!难道我看上去像一个笨蛋吗?”而实际上,他们并没有检查过接口

你可以换一种说法,”Raymond Chen 建议,“改成这样说:‘别着急,有时候键盘接口会有灰尘,导致接触不良。你能不能拔掉键盘插头,吹掉上面的灰尘,然后再把它插回去?’”

“然后,客户爬到桌子底下,发现自己忘了插好插头(或者把插头插入错误的接口)。他们把灰尘吹掉,插入插头,回复你说:‘嗯,很好,问题解决了,谢谢。’”

第八部分 发布软件


第九部分 修订软件


1 软件线上稳定性

① 做不到极致

要想得到真正高的服务稳定性,成本是极其高昂的。俗称“6 个 9”的服务稳定性(99.9999%的时间正常运行)意味着每年下线时间不能超过 30 秒。这真有点接近荒谬了。即使有人声称他们已经投资了上千万美元,建立了超一流的大型超冗余“6 个 9”系统,也无法排除出现严重故障的可能性。 即使是公认的最可靠系统,比如 AT&T 的长途电话服务,也会出现长时间的服务中断(1991 年中断了 6 个小时),这意味着它们的服务稳定性只能到达一个令人羞于启齿的“3 个 9”水平(99.9% 的时间正常运行)…AT&T 的长途电话服务被认为是“电信级”(carrier grade)的系统,是服务稳定性的黄金标准,你的系统会比它更稳定吗

② 难在哪

提高服务稳定性的最大困难,就是“黑天鹅难题”(problem of black swans)。这个名词是由 Nassim Taleb提出来的 (www.edge.org/3 rd_culture/ taleb04/taleb indexx. Html),他这样定义:“黑天鹅代表外来因素,是一个超出正常预料的事件。”几乎所有的互联网服务中断都来自于意料之外的突发事件,属于极其小概率的非主流意外。这类事件是如此罕见,以至于常规的统计方法(比如“故障间隔平均时间”)都失效了。“请问新奥尔良市发生特大洪水的平均间隔时间是多少?”

③ 有什么可以代替它的指标

经过几次内部讨论以后,我们所有人都同意不为服务稳定性设置一个静态值作为目标,那是毫无意义的。我们觉得,如果有人希望通过测量某些无意义的指标来改进工作,那肯定是没用的。

我们真正需要的是一个能够不断改进工作质量的流程。所以,我们决定不向我们的顾客提出一个 SLA 条款,而是搭建一个网志。在这个网志上面,我们将实时记录每一次的服务中断,提供完整的事后分析,询问五个为什么,找到根本性的原因,告诉我们的顾客为了防止类似故障再次发生我们所采取的举措。就拿这一次的交换机事故来说,我们采取的变化就是,在内部文档中写入详细的操作步骤和检查清单。以后再在生产环境中安装交换机的时候,所有操作步骤都必须严格按照文件中写好的步骤完成。

坦诚 透明 才是最好的办法

我们的顾客可以访问这个网志,看看故障的原因到底是什么,以及我们正在怎样改进我们的服务。我们希望,我们的顾客能够因此增强信心,相信我们的服务品质正在稳步提高。

与此同时,如果我们的顾客感到我们的故障对他造成了影响,他就可以向我们要求补偿,客服人员会给他的账户延长使用期限或者退款。 顾

客户至上 服务至上

posted @ 2022-07-23 18:45  小蒋不素小蒋  阅读(182)  评论(0编辑  收藏  举报

ICP证:沪ICP备20014317号