《软件随想录》读书笔记

软件随想录》是一本有趣的技术书籍,阮一峰翻译的,值得一读。它总结了作者多年的从业经验,读完之后,感觉是从另一个更高的维度去提升了程序员的思维境界。

下面摘录整理了一些读书笔记:

人员管理

  1. 不懂编程的人管理软件公司,就好像不懂冲浪的人硬要去冲浪。
  2. 如同所有行业中最好的人才一样,那些优秀的程序员是不会出现在招聘市场上的。通常优秀的程序员在整个职业生涯中,可能会有 4 次求职。
  3. 找到优秀的程序员的 3 个基本方法:
    1. 走出去,不要只会上招聘网站
    2. 实习生
    3. 建立自己的社区(community)
  4. 员工推荐:小心陷阱。谨记仍然要要求应聘者通过剩下的所有面试,坚持高标准不变。
  5. Aeron 牌电脑椅,靠背和坐垫都被设计成网状形,空气可以自由流通,所以坐着不会捂汗。带有腰部支撑和后部平衡装置的顶级系列新型号,再加上尺寸如果正确,并且调节到最合适的位置,那么大多数人坐一整天都不会感到不舒服。
  6. 当一个程序员抱怨“人际关系复杂”时,他们的意思明白无误,就是指任何个人因素超过技术因素的环境
  7. 互联网公司的三种管理方法:
    1. 军事化管理法
      1. 在软件开发团队中,每个人干的活都不一样,所以如果想进行微观管理,就会变成抽风式 (hit-and-run) 的管理(大多数时候管理层对程序员不闻不问,偶尔却心血来潮介入,追问一些及其微小的细节,或坚持一定要百分之百按照他们的方式或需求做出来)。
    2. 经济利益驱动法
      1. 如果你使用经济利益驱动法,你就是在鼓励程序员与制度博弈。经济利益驱动法的问题是,它将内部激励变成了外部激励。认同法的作用恰恰相反,是为了设法创造出内部激励。
    3. 认同法
      1. 认同法要求你创造一个有凝聚力的、像胶水一样粘在一起的团队,就好像家庭一样。这样一来,人们就会对他们的同事产生忠诚感和义务感。

写给未来程序员的建议

  1. 对于某些最激动人心的编程任务来说,指针仍然是非常重要的。比如说,如果不用指针,你根本没办法开发Linux的内核。如果你不是真正地理解了指针,你连一行Linux的代码也看不懂,说实话,任何操作系统的代码你都看不懂。
  2. 如果你不懂函数式编程,你就无法创造出 MapReduce,正是这种算法使得 Google 的可扩展性达到如此巨大的规模。术语“Map”(映射)和“Reduce”(化简)分别来自Lisp语言和函数式编程。
  3. 消灭软件代码中的缺陷是一件边际报酬递减(随着软件中的缺陷越来越少,修复每一个缺陷所带来的收益也在变小)的事情。
  4. 有一种恐怖的东西叫做“内部软件”(inhouse software),做一个内部程序员( in-house programmer )糟透了:
    1. 你永远无法用正确的方法、而是被迫用最保险的方法做事。
    2. 内部软件只要“能用了”就会停止开发,因此你永远做不出优秀的产品。但如果你开发的是一个商用软件,你就可以不断对它加工、打磨、优化和改良。
    3. 如果你在专业的软件公司中编程,你的工作与公司的主营业务直接相关,是能够为公司直接带来收入的。这至少意味着一件事情,就是管理层会想到你。也就是说,你能得到最好的福利、最舒适的办公环境和最佳的晋升机会。
  5. 那些决定游戏规则的人都是善于写作的人。能不能清晰地写出技术内容的文章决定了你是一个口齿不清的程序员还是一个领袖。
  6. 读《微观经济学》,因为从经营一家公司的角度来看,比起那些不懂的程序员,一个理解基本商业规则的程序员将会更有价值,就是这么简单。

管理大型项目

  1. 网页设计师现在的处境,其实犹太人早在几十年前就体会到了,那就是所有人都同意遵守同一部法典并不能保证所有人的行为都符合同样的规范。因为法条太复杂、太深奥、太难懂了,想要完全正确地理解法条几乎是不可能的。
  2. 标准(如W3C)当然很重要的,但是你不能迷信标准,你必须理解由于人为犯错,所以标准有时候会引发误解、困惑、甚至是争议。
  3. 这是一个很好的例子,说明了“实用主义者”与“理想主义者”两大阵营之间存在的巨大鸿沟:用户升级新版IE后,无法“正常”浏览网站。他们不会为理想主义者那愚蠢的信仰叫好,不会理解为什么你们一定要网络浏览器符合某些神秘的、柏拉图式理想化的、实际上根本还没有实现的“标准”。他们不想听你们讲那些丑陋的Hack,他们只想要网络浏览器能够正常浏览现实中的网站。
  4. 理想主义者在大原则上是百分之百正确的。同样,实用主义者在现实中也是正确的。这场争论将精确地把世界分成两半,两大阵营之间的口水战将持续下去。
  5. 优秀的设计似乎是最容易复制的东西,但是做起来却又不是那么容易,因为做出优秀的设计本身就是一件“麻烦事”,实际上能够提供牢固得令人震惊的竞争优势。

编程建议

  1. 循证式日程规划(Evidence-Based Scheduling)
    1. 循证式日程规划先收集历史数据,主要来源是过去的time sheet,然后统计分析,得到了一条概率分布曲线,显示在任一个给定日期你完成工作的可能性有多大。
    2. 蒙特卡洛方法(Monte Carlo method)模拟未来各种可能的结果。
    3. 将每个任务所需的时间控制在16小时之内,这就会迫使你好好地去规划你要造成的那个任务。
    4. 几条经验:
      1. 只有第一线的程序员才能提出完成日期的估计值。任何管理层制定然后交给程序员去执行的日程规划,都注定会失败。只有真正负责开发的程序员才能估计出完成任务需要哪些步骤。
      2. 一发现错误就立即修正,将用时算入原始任务的用时之中。
      3. 防止管理层向程序员施加压力,被要求加快开发速度。如果程序员的进度落后于日程,就会感到惶惶不可终日,非常沮丧,这时再大的激励也是没用的。如果程序员的进度快于日程,则会感到欢欣鼓舞,工作效率非常高,这时根本不需要激励。日程规划并不是一个玩心理游戏的地方。
      4. 一份日程规划的好处之一,就是你会在工作开始之前,就被迫删去一些次要的或无用的功能,从而全力开发有用的或重要的功能。正是这种迫使你砍掉某些功能的压力,使得你最终做出一个更强大、更优秀的产品,它包括了很好的功能组合,而且能够在较早的日期完成。
    5. 有效的日程规划是创造优秀软件的钥匙。它强迫你首先完成最重要的功能,让你做出正确的选择,思考要开发一个怎样的软件。这会使你的产品变得更出色,使你的老板感到更开心,使你的客户感到更满意,以及更重要的一点,那就是使你下午6点能够准时下班。
  2. 战略问题
    1. 从长远的观点来看,那些不关心效率、不关心程序是否臃肿、一个劲往软件中加入高级功能的程序员最终将拥有更好的产品。
    2. 过去的积累可能会变成"历史包袱"。
  3. 编程
    1. 将“循环操作”这个单独的步骤抽象出来,用任何你想用的方法完成这个步骤,其中就包括用额外的硬件将运算过程轻松地扩展(Scale)到多台服务器上。谷歌的许多应用程序都使用了这种MapReduce技术,所以一旦有人对底层的并行计算程序进行优化或消除bug,那么所有这些应用程序都会受益。
    2. 寻找一种代码的书写规范,让错误的代码变得容易被看出。让代码中的相关信息在显示屏上集中在一起,使你能够当场发现和改正某些种类的错误。
    3. “应用型匈牙利命名法”(Apps Hungarian)是有价值的,它加强了代码之间的联结,使得代码更容易阅读、书写、除错和维护。最重要的是,它让错误的代码容易现形。

开办软件公司

  1. 三点意见
    1. 如果你说不清楚你的软件解决了什么棘手的问题,就不要去开软件公司。
    2. 不要独自一人创办公司。一个人创业十分孤独和压抑没有任何人与你交流思想,为你出谋划策。要是有两个人一起创业,你就会感到对你的合伙人负有义务,就会努力撑下去,渡过难关。
    3. 一开始不要抱有太高期望。
  2. 为什么低成本的软件供应商就不能在软件业中生存下来呢?我们只雇用最便宜的程序员为什么就是不行?根本原因是软件的销售复制成本为 0。这意味着,程序员的劳动力成本分摊在你销售出去的所有软件中,对软件来说,如果销售量很大,质量的改进成本并不会造成单位软件成本的上升。相反,软件质量的改进还会创造出新价值,而且价值创造的速度要快于成本提升的速度。
  3. 布鲁克斯法则(Brooks’ Law) ——向一个已经延误的软件项目增加人手,只会使它更加延误。一个优秀的程序员独自完成一项任务,就不需要额外的沟通和协调。如果同样的任务让 5 个程序员一起完成,他们之间就必须沟通和协调,这会花掉大量时间。开发团队越小,就越能获得额外的收益。人力与工时的互换只是一个神话。
  4. 用许多平庸的程序员取代少数优秀的程序员,这种做法的真正问题在于,不管平庸的程序员工作多长时间,他们做出来的东西都无法像优秀程序员做得那样好。
  5. 令人难过的是,内部软件很少重要到需要雇用巨星/优秀程序员来开发。这就是为什么最令人满意的职业生涯往往是在真正的软件公司里,而不是在银行担任 IT 技术人员。

经营软件公司

  1. 软件开发中,对你最重要、最关键的部分,一定要使用更原始的工具。至少也要使用开源/自由软件,这样至少出错的时候,你多多少少有机会解决问题,不会被解雇。
  2. 建立优质客服
    1. 技术支持团队必须能够与开发团队直接沟通,这很关键,这意味着你不能把技术支持人员外包出去,他们必须与开发人员在同一个地址办公,必须有途径让问题得到直接和彻底的解决。
    2. 当软件每次发生问题都被彻底解决之后,所有常见和容易的问题都被消灭了,技术支持工作实际上就变成了处理疑难杂症,对程序来说这意味着要进行调试和除错。因此对技术支持人员的要求更高、培训力度要更大。
    3. 很多时候,为了避免冒犯客户,我们要求客户去检查某样东西,都可以这样表达:不是直接要求他们去检查某个设置,而是告诉他们先改变这个设置,然后再改回去,目的是“确保这个设置被成功保存”。
    4. 客户投诉的时候,人很容易就变得感情用事。解决方法是记住一些重要句子,不断练习把它们说出口。等到你需要用到它们的场合,你就会把冲动自动抛在脑后,转而让客户开心。
    5. 同客户争吵,你永远不会是赢家。

挑选发布日期

  1. 软件功能必须按照优先顺序排序,否则一切将会变糟。只要你一不注意,你手下的程序员就会按照趣味性的顺序开发各项功能,你就将因此无法按时发布软件,或者无法取消部署某项功能,因此你就会陷入很被动的局面。
  2. 市场分割,即根据你的客户愿意支付的价格将他们分成不同的组,从每个客户身上赚取最大的消费者剩余,是一种有效的定价手段。但是长远来看,这种价格歧视会对你的产品形象产生显著的负面影响。
  3. 当消费者对商品所知有限时,消费者通常就会认为比较贵的商品就是质量比较高。
  4. 当你在制定价格时,你就是在发出信号。

修订软件

  1. 如果通过测量某些无意义的静态指标来改进工作,那是无用的。我们真正需要的是一个能够不断改进工作质量的流程:先询问五个为什么,找到根本性的原因,告诉客户为了防止类似故障再次发生我们所采取的举措。书写一份标准、详细的操作流程和确认清单,所有操作步骤都严格按照流程一一操作。目标的:我们遇到的所有引起服务中断的故障都是真正由于极其罕见的、无法预料的"黑天鹅因素"而引起的。
  2. 不要开发那些销售人员无意间答应某个客户的功能,也不要因为"反正迟早要做"而先去开发那些不重要尽管有趣味性的功能。