《Code Complete 2》读书笔记

这是我阅读代码大全2的读书笔记。

软件的首要使命:管理复杂度

好的设计是降低复杂度,而不是提高复杂度。

使用变成语言,应该是 “programming into a language” 而不是仅仅 “programming in a language”。 后者指根据语言设计solution,而前者指根据solution来使用语言,甚至改变语言。语言只是我们思想的表达工具,而不是决定思想的工具。

信息隐藏是减少重复工作的强大技术,在不断增长的,大量变化的环境中尤其有用。

信息隐藏的秘密有两大类:1)隐藏复杂度 2)隐藏变化源

在做设计时候,多问问自己我应该隐藏什么,而不仅仅是按照对象原则进行思考。

不要有设计完美强迫症(我经常有一种不设计好不舒服司机的赶脚,要改),在你没有足够的经验的和问题认识的时候,尽可以做出一份简单的设计来使用,在自己逐渐掌握和理解问题的基础上,在去迭代完善。 做设计也一样,完美主义心态要有,但是不要绝对,不然就是浪费时间。

关于设计

好的设计都是迭代出来的。你尝试设计的可能性越多,你的最终方案就会越好。

设计过程中同时考虑使用自上而下和自下而上两种思考方法。(自上而下可以理解为分析问题,需要解决什么问题,有几个步骤,几个模块。而自下而上可以理解在如果设计出来之后,底层如何调用,底层如何通信。)

(联想起我做的data cache 模块,开始时候只顾着自上而下了,仅仅考虑完成了总体任务,却忽略了底层如何调用,底层如何使用的问题,导致最初的版本写出来现有代码根本无法使用,那么这种设计就是不对的)

关于类设计

每当你发现自己是通过查看类的内部实现来得到该如何使用这个类的时候,你就不是在针对接口编程,而是在透过接口针对内部实现编程了。

要么使用继承并配上详细说明,要么就不要用它。继承是复杂的,尽量使用组合。

不要使用 protected 而使用 private 修饰变量。protected给子类暴露了实现,提高了维护复杂度,即使是子类也需要使用接口访问数据(设计是为了降低复杂度,使用protected同样提高了程序员维护的复杂度)

如果使用继承,考虑好接口形式:是否可以被覆盖,如果可以被覆盖,是仅仅提供默认实现,还是子类必须自己提供一个实现呢?(对于C++就是 virtual 和 pure virtual 的区别了),如果不可以被覆盖,最好需要明确这一点,比如加上 finally 等关键字。

anyway,继承是复杂的,不要维护太多的层次和接口。

继承有用,但是增加了软件的复杂度,违背了软件技术的首要技术使命——管理复杂度

防御氏编程

使用隔拦程序:对外的接口,在该接口中提供安全的参数检测,错误处理等,然后将数据给内部的接口使用,内部的接口就默认这些参数都是正确的,使用断言来进行判断,保证数据正确性,而不做额外的错误处理。

研究表明,很少有人可以理解超过3层以上嵌套逻辑的含义,所以不要嵌套超过3层!

代码的优化调整技术

对于线性查找的场合,都可以使用哨兵的查找方式,这样可以大大提高效率。

关于优化调整深刻的一段话:

我已经体会到,恪守“对每一次的改进都进行量化”的准则,是抵御思考成熟前匆忙优化之诱惑的法宝,这一准则也帮助我坚守编写简单清晰代码的一贯作风。如果某项优化非常重要,值的为它付出剖析和对优化效果进行量化测量的代价,那么只要优化有效,我们还是可以去做的,但是,如果某项优化的重要性不够,不值得为它去做效能剖析,那么就不值得为它付出可读性,可维护性和其他代码恶化等方面的代价。未经测量的代码优化对性能上的改善充其量是一次投机,但是对可读性等产生的负面影响则确凿无疑。

代码调优一定不是拍脑袋想的,负责一切以代码的清晰,可读,可维护性为第一指标。

项目集成

软件构建的工作量与项目大小成近似线性关系,而其余元素(比如工作总量,文档数量)都是非线性关系。

个人性格

这是我们目前觉得code complete 2中讲的最有意思和价值的章节:)

出色程序员解决问题的速度,规模,错误率是非优秀的10倍。事实证明,个人性格对于造就程序员高手具有决定性意义。

有几点需要培养的特质:

  1. 聪明和谦逊。承认自己的智力有限,并通过学习来弥补,你会成为更好的程序员,你越是谦逊,进步的就越快。
  2. 求知欲。学习成功的代码,高手的代码,学习成功项目的经验。
  3. 诚实。不是高手就不假装是高手,乐于承认错误。

@note 合理估算时间,不要妥协。如果时间合理,需要坚持自己对于进度的估计,而不是被压力所胁迫。妥协之后如果不成功,后果更加不好,不如坚持自己的估算,反而赢得尊重。

好的坚持方式是这样子:

  1. 项目的估算时间是不会让步,这是自然规律。
  2. 但是我们可协商进度的其他方面(立场加退步),比如少一些特性,降低性能,划分阶段任务,或者多一些人手。
  3. 和专业程序员靠齐。技术带头人知道,编程工作中只有15%用来和计算机交互,其余都是和人打交道的。技术带头人会为人写代码,而不是机器。
  4. 交流与合作。
  5. 创造力和纪律。根据美国NASA总结,许多有很强创造力的人都极其遵守纪律,正如俗话说的:「Form is liberating」(形式就是解放)。
  6. 懒惰。立刻行动,克服最困难的部分是一个优秀工程师的特质。

一个问题需要铭记:如果你工作10年,你会得到10年的经验,还是1年经验的10次重复?必须检讨自己的行为,才能获得真正的经验。只有坚持不懈的学习,才能获得经验;如果不这么做,就无法获得经验,无论你工作多少年!!!!

非常深刻,但是又很警示的话,不要为了完成而完成,不要为了做而做,要有突破,要有总结,要不停的学习,这样子才可以得到经验。

另外一个重要的素质:习惯。

好习惯非常重要,因为程序员做的大部分事情都是无意识完成的。你还记得你上次质疑编码风格是什么时候的事情了嘛?一旦形成习惯,都是在无意识的状态下完成。

注重习惯的培养,比如开始写代码之前先写伪代码,编译之前先认真检查代码,使用新的习惯来替换旧的习惯。好性格与培养正确的习惯关系甚大,要成为杰出的程序员,先要养成良好的习惯,其他自然水到渠成。

读完感想

  1. 软件工程的终究目标是管理复杂度。keep it stupid simple.
  2. 好的设计是迭代出来的。
  3. 为人写代码而不是机器。
  4. sometimes form is liberating。
  5. 一个问题需要铭记:如果你工作10年,你会得到10年的经验,还是1年经验的10次重复?必须检讨自己的行为,才能获得真正的经验。只有坚持不懈的学习,才能获得经验;如果不这么做,就无法获得经验,无论你工作多少年!