本书在笔者实习时就已经开始阅读,按照自己的所处阶段有间隔的分成了3次阅读,一直到现在终于完成了。读者千万不要认为这本书真的只是“代码大全”,在我看来,这本书就是软件工程师的心法,提升软件工程的认知、意识。各种技术层出不穷,也有很多技术最终消失在时间里,但这本书的精髓则适用于每一代软件开发者。
本身还提供了各方面的CheckList,可以借助这部分CheckList培养自己的意识。
由于之前阅读的书籍中,有些内容与本书有重合,或者比本书讲的更透彻,这里只记录了书中的部分章节。
第一章:欢迎进入软件构建的世界 1、什么是软件构建? 软件构建可以理解为软件开发中真正要动手做的那部分,主要活动包括详细设计、编码、调试、集成、开发测试(单元测试和集成测试)。 2、软件构建为何如此重要? 软件构建是软件开发中的主要活动,是软件开发的核心,占用了软件开发中的30~80%的时间,是软件开发中唯一一个必须要完成的部分,源码也是最新最精准的文档,软件构建的质量直接关系着整个项目的质量,把注意力放在软件构建上能够大大提升程序员的开发效率。
第二章:用隐喻更充分的理解软件开发 1、当将软件的构建过程比作房屋的构建过程时,可以发现,仔细的准备是必要的,发生变动时最贵的成本是人的时间,而大型项目和小型项目之间也有差异。 2、软件开发实践中,每位工程师都有许多工具,但不存在任何一个能适用于所有工作的工具,因地制宜德尔选择正确工具是成为能有效编程的程序员的关机。
第三章:三思而后行:前期准备 1、核对表(细节可参考文中描述的原则核对) ①是否辨明了自己所从事的软件的类型,并对所用的开发方法做出相应的剪裁?(许多项目是高度迭代的,某些则应该是序列式的) ②是否充分明确定义了需求?而且需求足够稳定,能够开始构建了?(详见需求核对表) ③是否充分明确的定义了架构,以便开始构建?(详见架构核对表) ④是否已经指出当前项目中独有的风险?(以避免构建活动面临不必要的风险) 2、在项目初期关注质量、发现问题,远比后期发现解决成本更低。
第五章:软件构建中的设计 1、软件的首要技术使命就是管理复杂度,以简单性作为努力目标的标记方案对此最有帮助。 2、好的设计是迭代的,你尝试设计的越多,你的最终方案就会约好。 3、隐藏实现、封装变化。
第六章:可以工作的类 1、类的接口应该提供一致的抽象。很多问题都是由于违背该原则而引起的。 2、类的接口应该隐藏一些信息,如某个系统接口、某项设计决策、或一些实现细节。 3、包含(组合、聚合)往往比继承更可取,除非是要对一个“is a”的关系建模。 4、限制继承的层次,继承是一种有用的工具,但它却会增加复杂度,这有违软件的首要使命-管理负责度。 5、类是管理复杂度的首先工具。要在设计类时给予足够的关注,才能实现这一目标。 6、尽量减小类和类之间相互合作的范围,让以下几个数字最小: ①所实例化的对象的种类; ②在被实例化对象上直接调用的不同子程序的数量; ③调用的“通过其他对象返回的”对象的子程序的数量;(A通过调用B的返回值C来调用C的方法,)
第七章:高质量的子程序 1、为什么要创建子程序? 提高程序的可读性,减少以及隔离程序复杂度,提高代码复用率,在代码变更时减少带来的影响(功能变更,变更导致的测试),可移植性,方便后期优化,隐藏复杂逻辑结构等的实现细节...... 2、如何设计子程序? 保证子程序功能的内聚性,既一个子程序只完成一个功能。避免其它的内聚性,比如逻辑上的内聚性,顺序上的内聚性等。 3、什么是好的子程序名字? 能够描述子程序所做的事情,使用动宾结构,并且对返回值有所描述,比如checkOrderInfo,使用对仗词(比如get/set,create/destroy),一般命名长度为9~15个,在一个项目里最好给一些通用的操作确立命名规则(比如创建、更新记录时),避免模糊命名(比如detail); 4、子程序可以多长? 考虑事项:子程序的功能的内聚性,嵌套的层次,变量的数量,决策点的数量等; 研究表明应该一般不超过200行, 5、如何使用子程序参数? 按照输入、修改、输出的顺序排列参数; 如果几个程序都用了类似的一些参数,应该让这些参数的排练顺序保持一致; 不要把子程序的输入参数用作工作变量,工作变量最好在子程序中创建,保证参数尽量不被改变; 把子程序的参数个数限制在大约7个以内,且保证每一个参数都被用到; 为子程序传递用以维持其借口抽象的变量或对象,传递给子程序什么类型的参数,应该为对子程序而言,哪种方式对子程序更方便; 第八章:防御式编程 1、什么是防御式编程?为什么需要? 防御式编程不是指不让别人批评你的代码,而是指确保你要承担的责任,保证你的方法不会因为传入错误数据而破坏,看似微小的防范,收益可能大于你的想象,能够让错误更容易发现,修改,并减少对已经编写代码的修改 2、如何使用防御式编程? 在开发阶段,建议不从产品角度考虑,建议让错误暴露的越明显越好,能更快的排查错误;在产品上线时,防御式编程的代码可能影响性能以及体验,需要适当修改,但是需要根据场景考虑,比如银行设备以及普通网站,不同产品,错误处理方式不一样; 隔离程序与参数,即对参数进行验证,使之能包容错误造成的损害,并进行适当处理; 3、如何对错误进行处理?处理的方式 需要根据实际场景,程序是更需要健壮性还是正确性,一般普通的消费产品更倾向于健壮性,但和数据相关,则更倾向于正确性;建议在架构设计上就决定好如何处理错误,是异常还是其他的方式。 4、关于异常 避免在构造和析构函数中使用异常;考虑创建一个集中的方式处理异常,能够为一些与异常有关的信息提供集中的存储;把项目中对异常的使用标准化,考虑创建抛出异常的基类,这样就能把记录日志、报告错误等操作集中起来并标准化;不滥用异常,应该在异常和其他错误处理手段进行权衡,如果某些错误能局部处理,那就局部处理它;
第十一章:变量名的力量 1、代码的阅读次数远远大于编写的次数,为了可读性,确保所取的名字更侧重于阅读而不是编写方便。 2、命名时要足够具体,不要用模糊或者太通用能用于各种目的的名字,名字需要能表达变量所代表的含义,需要让阅读者无需苦苦思索。 3、命名规则应该能区分不同类型的数据,最好能够区分局部数据、类数据、全局数据,还应当可以区分类型名、具名常量、枚举类型和变量名等,具体命名类型的建议参考代码大全。 4、无论哪种类型的项目,都应该采用某种命名规则。所采用的规则的种类取决于程序的规模,以及项目成员的人数。 5、慎用缩写,现代编程语言很少使用缩写,如果真的要使用,最好维护一个项目字典或者标准前缀帮助理解,并且缩写英国有自己的规则,具体细节可参考代码大全。
第十四章:组织直线型代码 1、组织直线型代码的原则主要是按照依赖关系来排列。 2、可以用比较好的子程序名、参数列表、注释,以及使用不同的变量让依赖关系看起来更明显。 3、如果代码之间没有顺序依赖关系,则尽可能让相关的语句更接近。
第十九章:一般控制问题 1、布尔表达式(判断的条件)尽量可读,有助于提升代码的质量。 2、深层次的嵌套使得代码可读性降低,很少有人能理解超过3层的if嵌套,尽量避免使用超过3到4层的嵌套,可采用如下方法减少嵌套层次: ①重复判断一部分条件; ②转换成if-then-else; ③转换成case语句; ④把深层嵌套代码提取成单独的子程序; ⑤使用对象和多态。 3、衡量代码复杂度的方法,可以采用McCabe方法。
第二十三章:调试 1、调试前要理清思路,理解问题的根本。胡乱猜测错误的来源和随机修改将会让你的程序陷入比刚开始调试时更为糟糕的境地。 2、检查出现问题的地方的最近修改的代码,很可能修改引入了新的bug 3、解决问题要根本解决,不能尝试着改变一个东西,发现结果正常就认为是解决了,要发现产生问题的原因,是否根本解决。 3、要反复检查解决问题的代码,确认解决问题时没有引入新的bug。 4、更多可参考核对表
第三十一章:布局与风格 1、可视化布局的首要任务是指明代码的逻辑组织,可以通过注释、空格、空行、缩进等区分不同的逻辑块。评估该任务是否实现的指标包括准确性、一致性、可读性和可维护性。 2、外表悦目比起其他指标是最不重要的。然而,如果其他指标都达到了,代码又质量好,那么布局效果看上去也不错。 3、结构化代码有其自身目的。始终如一的沿用某个习惯而少来创新。不能持久的布局规范只会损害可读性。 4、布局的很多方面涉及信仰问题。应试着将客观需要和主观偏好区分开来。定出明确的目标,在此基础上再讨论风格参数的选择。
第二十八章:管理构建 1、程序员倾向于将管理者视为技术进化的低级层次,制定标准的事情由一位受人尊敬的架构师来做更容易被人接纳。 2、管理你的管理者:
第三十二章:自说明代码 1、该不该注释是个需要认真对待的问题。差劲的注释只会浪费时间。好的注释才有价值。注释的位置可以在:变量特定的含义和限制、某个职责代码块的开始、一般控制结构的开始、子程序调用处、方法开始处描述功能、类开始处描述功能。 2、源代码应当含有程序大部分的关键信息。只要程序依然在用,源代码比其他资料都能保持更新,故而将重要信息融入代码是很有好处的。 3、好代码本身就是最好的说明。如果代码太糟,需要大量注释,应先试着改进代码,直至无须过多注释为止。 4、注释应说出代码无法说出的东西,例如概述或用意等信息。注释本身应该包含的是对代码的简洁的抽象概括,而不是具体代码的实现细节。 5、注释风格也应该简洁易于维护,有的注释风格需要许多重复性劳动,应舍弃之。
第三十三章:个人性格 1、人的个性对其编程能力有直接影响。 2、最有关系的性格为:谦虚、求知欲、诚实、创造性和纪律,以及高明的偷懒。 3、程序员高手的性格与天分无关,而任何事都与个人发展相关。 4、出乎意料的是,小聪明、经验、坚持和疯狂(编程狂人)既有助也有害。 5、很多程序员不愿主动吸收新知识和技术,只依靠工作时偶尔接触新的信息。如果能抽出少量时间阅读和学习编程知识,要不了多久就鹤立鸡群。 6、软件技术一直在变,做软件技术不仅要完成已有的战斗,还要迎接未来的战斗,年轻人在对技术的探索欲上就会比老人强,就可能被淘汰, 7、好性格与培养正确的习惯关系甚大。要成为杰出的程序员,先要养成良好的习惯,其他自然水到渠成。
第一章:欢迎进入软件构建的世界 1、什么是软件构建? 软件构建可以理解为软件开发中真正要动手做的那部分,主要活动包括详细设计、编码、调试、集成、开发测试(单元测试和集成测试)。 2、软件构建为何如此重要? 软件构建是软件开发中的主要活动,是软件开发的核心,占用了软件开发中的30~80%的时间,是软件开发中唯一一个必须要完成的部分,源码也是最新最精准的文档,软件构建的质量直接关系着整个项目的质量,把注意力放在软件构建上能够大大提升程序员的开发效率。
第二章:用隐喻更充分的理解软件开发 1、当将软件的构建过程比作房屋的构建过程时,可以发现,仔细的准备是必要的,发生变动时最贵的成本是人的时间,而大型项目和小型项目之间也有差异。 2、软件开发实践中,每位工程师都有许多工具,但不存在任何一个能适用于所有工作的工具,因地制宜德尔选择正确工具是成为能有效编程的程序员的关机。
第三章:三思而后行:前期准备 1、核对表(细节可参考文中描述的原则核对) ①是否辨明了自己所从事的软件的类型,并对所用的开发方法做出相应的剪裁?(许多项目是高度迭代的,某些则应该是序列式的) ②是否充分明确定义了需求?而且需求足够稳定,能够开始构建了?(详见需求核对表) ③是否充分明确的定义了架构,以便开始构建?(详见架构核对表) ④是否已经指出当前项目中独有的风险?(以避免构建活动面临不必要的风险) 2、在项目初期关注质量、发现问题,远比后期发现解决成本更低。
第五章:软件构建中的设计 1、软件的首要技术使命就是管理复杂度,以简单性作为努力目标的标记方案对此最有帮助。 2、好的设计是迭代的,你尝试设计的越多,你的最终方案就会约好。 3、隐藏实现、封装变化。
第六章:可以工作的类 1、类的接口应该提供一致的抽象。很多问题都是由于违背该原则而引起的。 2、类的接口应该隐藏一些信息,如某个系统接口、某项设计决策、或一些实现细节。 3、包含(组合、聚合)往往比继承更可取,除非是要对一个“is a”的关系建模。 4、限制继承的层次,继承是一种有用的工具,但它却会增加复杂度,这有违软件的首要使命-管理负责度。 5、类是管理复杂度的首先工具。要在设计类时给予足够的关注,才能实现这一目标。 6、尽量减小类和类之间相互合作的范围,让以下几个数字最小: ①所实例化的对象的种类; ②在被实例化对象上直接调用的不同子程序的数量; ③调用的“通过其他对象返回的”对象的子程序的数量;(A通过调用B的返回值C来调用C的方法,)
第七章:高质量的子程序 1、为什么要创建子程序? 提高程序的可读性,减少以及隔离程序复杂度,提高代码复用率,在代码变更时减少带来的影响(功能变更,变更导致的测试),可移植性,方便后期优化,隐藏复杂逻辑结构等的实现细节...... 2、如何设计子程序? 保证子程序功能的内聚性,既一个子程序只完成一个功能。避免其它的内聚性,比如逻辑上的内聚性,顺序上的内聚性等。 3、什么是好的子程序名字? 能够描述子程序所做的事情,使用动宾结构,并且对返回值有所描述,比如checkOrderInfo,使用对仗词(比如get/set,create/destroy),一般命名长度为9~15个,在一个项目里最好给一些通用的操作确立命名规则(比如创建、更新记录时),避免模糊命名(比如detail); 4、子程序可以多长? 考虑事项:子程序的功能的内聚性,嵌套的层次,变量的数量,决策点的数量等; 研究表明应该一般不超过200行, 5、如何使用子程序参数? 按照输入、修改、输出的顺序排列参数; 如果几个程序都用了类似的一些参数,应该让这些参数的排练顺序保持一致; 不要把子程序的输入参数用作工作变量,工作变量最好在子程序中创建,保证参数尽量不被改变; 把子程序的参数个数限制在大约7个以内,且保证每一个参数都被用到; 为子程序传递用以维持其借口抽象的变量或对象,传递给子程序什么类型的参数,应该为对子程序而言,哪种方式对子程序更方便; 第八章:防御式编程 1、什么是防御式编程?为什么需要? 防御式编程不是指不让别人批评你的代码,而是指确保你要承担的责任,保证你的方法不会因为传入错误数据而破坏,看似微小的防范,收益可能大于你的想象,能够让错误更容易发现,修改,并减少对已经编写代码的修改 2、如何使用防御式编程? 在开发阶段,建议不从产品角度考虑,建议让错误暴露的越明显越好,能更快的排查错误;在产品上线时,防御式编程的代码可能影响性能以及体验,需要适当修改,但是需要根据场景考虑,比如银行设备以及普通网站,不同产品,错误处理方式不一样; 隔离程序与参数,即对参数进行验证,使之能包容错误造成的损害,并进行适当处理; 3、如何对错误进行处理?处理的方式 需要根据实际场景,程序是更需要健壮性还是正确性,一般普通的消费产品更倾向于健壮性,但和数据相关,则更倾向于正确性;建议在架构设计上就决定好如何处理错误,是异常还是其他的方式。 4、关于异常 避免在构造和析构函数中使用异常;考虑创建一个集中的方式处理异常,能够为一些与异常有关的信息提供集中的存储;把项目中对异常的使用标准化,考虑创建抛出异常的基类,这样就能把记录日志、报告错误等操作集中起来并标准化;不滥用异常,应该在异常和其他错误处理手段进行权衡,如果某些错误能局部处理,那就局部处理它;
第十一章:变量名的力量 1、代码的阅读次数远远大于编写的次数,为了可读性,确保所取的名字更侧重于阅读而不是编写方便。 2、命名时要足够具体,不要用模糊或者太通用能用于各种目的的名字,名字需要能表达变量所代表的含义,需要让阅读者无需苦苦思索。 3、命名规则应该能区分不同类型的数据,最好能够区分局部数据、类数据、全局数据,还应当可以区分类型名、具名常量、枚举类型和变量名等,具体命名类型的建议参考代码大全。 4、无论哪种类型的项目,都应该采用某种命名规则。所采用的规则的种类取决于程序的规模,以及项目成员的人数。 5、慎用缩写,现代编程语言很少使用缩写,如果真的要使用,最好维护一个项目字典或者标准前缀帮助理解,并且缩写英国有自己的规则,具体细节可参考代码大全。
第十四章:组织直线型代码 1、组织直线型代码的原则主要是按照依赖关系来排列。 2、可以用比较好的子程序名、参数列表、注释,以及使用不同的变量让依赖关系看起来更明显。 3、如果代码之间没有顺序依赖关系,则尽可能让相关的语句更接近。
第十九章:一般控制问题 1、布尔表达式(判断的条件)尽量可读,有助于提升代码的质量。 2、深层次的嵌套使得代码可读性降低,很少有人能理解超过3层的if嵌套,尽量避免使用超过3到4层的嵌套,可采用如下方法减少嵌套层次: ①重复判断一部分条件; ②转换成if-then-else; ③转换成case语句; ④把深层嵌套代码提取成单独的子程序; ⑤使用对象和多态。 3、衡量代码复杂度的方法,可以采用McCabe方法。
第二十三章:调试 1、调试前要理清思路,理解问题的根本。胡乱猜测错误的来源和随机修改将会让你的程序陷入比刚开始调试时更为糟糕的境地。 2、检查出现问题的地方的最近修改的代码,很可能修改引入了新的bug 3、解决问题要根本解决,不能尝试着改变一个东西,发现结果正常就认为是解决了,要发现产生问题的原因,是否根本解决。 3、要反复检查解决问题的代码,确认解决问题时没有引入新的bug。 4、更多可参考核对表
第三十一章:布局与风格 1、可视化布局的首要任务是指明代码的逻辑组织,可以通过注释、空格、空行、缩进等区分不同的逻辑块。评估该任务是否实现的指标包括准确性、一致性、可读性和可维护性。 2、外表悦目比起其他指标是最不重要的。然而,如果其他指标都达到了,代码又质量好,那么布局效果看上去也不错。 3、结构化代码有其自身目的。始终如一的沿用某个习惯而少来创新。不能持久的布局规范只会损害可读性。 4、布局的很多方面涉及信仰问题。应试着将客观需要和主观偏好区分开来。定出明确的目标,在此基础上再讨论风格参数的选择。
第二十八章:管理构建 1、程序员倾向于将管理者视为技术进化的低级层次,制定标准的事情由一位受人尊敬的架构师来做更容易被人接纳。 2、管理你的管理者:
- 把你希望做什么的念头先藏起来,收集起来,等着你的管理者组织一场有关你希望什么的头脑风暴/集体讨论(你的想法)。
- 把做事情的正确方法传授给你的管理者。这是一项需要持之以恒的工作,因为管理人员经常会提升、调迁或者解聘。
- 关注你的管理者的兴趣,按照他的真正意图去做,而不是用一些不必要的实现细节来分散注意力。(把它设想成堆你工作的一种封装)
- 拒绝按照你的管理者所说的去做,坚持用正确的方法做自己的事。
- 换工作。
第三十二章:自说明代码 1、该不该注释是个需要认真对待的问题。差劲的注释只会浪费时间。好的注释才有价值。注释的位置可以在:变量特定的含义和限制、某个职责代码块的开始、一般控制结构的开始、子程序调用处、方法开始处描述功能、类开始处描述功能。 2、源代码应当含有程序大部分的关键信息。只要程序依然在用,源代码比其他资料都能保持更新,故而将重要信息融入代码是很有好处的。 3、好代码本身就是最好的说明。如果代码太糟,需要大量注释,应先试着改进代码,直至无须过多注释为止。 4、注释应说出代码无法说出的东西,例如概述或用意等信息。注释本身应该包含的是对代码的简洁的抽象概括,而不是具体代码的实现细节。 5、注释风格也应该简洁易于维护,有的注释风格需要许多重复性劳动,应舍弃之。
第三十三章:个人性格 1、人的个性对其编程能力有直接影响。 2、最有关系的性格为:谦虚、求知欲、诚实、创造性和纪律,以及高明的偷懒。 3、程序员高手的性格与天分无关,而任何事都与个人发展相关。 4、出乎意料的是,小聪明、经验、坚持和疯狂(编程狂人)既有助也有害。 5、很多程序员不愿主动吸收新知识和技术,只依靠工作时偶尔接触新的信息。如果能抽出少量时间阅读和学习编程知识,要不了多久就鹤立鸡群。 6、软件技术一直在变,做软件技术不仅要完成已有的战斗,还要迎接未来的战斗,年轻人在对技术的探索欲上就会比老人强,就可能被淘汰, 7、好性格与培养正确的习惯关系甚大。要成为杰出的程序员,先要养成良好的习惯,其他自然水到渠成。
更多推荐
读书笔记:《代码大全2》
发布评论