第5章要点 软件构建中的设计
1. 软件的首要技术使命就是管理复杂度。以简单性作为努力目标的设计方案对此最有帮助。
2. 简单性可以通过两种方式来获取:一是减少在同一时间所关注的本质性复杂度的量,二是避免生成不必要的偶然的复杂度。
3. 设计是一种启发式的过程。固执于某一种单一的方法会损害创新能力,从而损害你的程序。
4. 好的设计都是迭代的。你尝试设计的可能性越多,你的最终设计方案就会变得越来越好。
5. 信息隐藏是一个非常有价值的概念。通过询问“我应该隐藏些什么”能够解决很多困难的涉及问题。
第6章要点 可以工作的类
1. 类的接口应提供一致的抽象。很多问题都是由于违背该原则而引起的。
2. 类的接口应隐藏一些信息------如某个系统接口、某项设计决策、或一些实现细节。
3. 包含往往比继承更为可取------除非你要对“是一个/is a”的关系建模。
4. 继承是一种有用的工具,但它会增加复杂度,这有违于软件的首要技术使命------管理复杂度。
5. 类是管理复杂度的首选工具。要在设计类时给与足够的关注,才能实现这一目标。
第7章要点 高质量的子程序
1. 创建子程序最主要的目的是提高程序的可管理性,当然也有其他一些好的理由。其中,节省代码空间只是一个次要的原因:提高可读性、可靠性和可修改性等原因都更重要一些。
2. 有时候,把一些简单的操作写成独立的子程序也非常有价值。
3. 子程序可以按照其内聚性分为很多类,而你应该让大多数子程序具有功能上的内聚性,这是最佳的一种内聚性。
4. 子程序的名字是它的质量指示器。如果名字糟糕但恰如其分,那就说明这个子程序设计的很差劲。如果名字糟糕而且又不准确,那么它就反映不出程序是干什么的。不管怎样,糟糕的名字都意味着程序需要将修改。
5. 只有在某个子程序的主要目的是返回由其名字所描述的特定结果时,才应该使用函数。
6. 细心的程序员会非常谨慎地使用宏,而且只在万不得已时才用。
第8章要点 防御式编程
这一概念来源于防御是驾驶。那就是你永远不能确定另一位司机将要做什么。
1. 最终产品代码中对错误的处理方式要比“垃圾进,垃圾出”复杂得多。
2. 防御式编程技术可以让错误更容易发现、更容易修改,并减少错误对产品代码的破坏。
3. 断言可以帮助人尽在发现错误,尤其是在大型系统和高可靠性的系统中,以及快速变化的代码中。
4. 关于如何处理错误输入的决策是一项关键的错误处理决策,也是一项关键的高层设计决策。
5. 异常提供了一种与代码正常流程角度不同的错误处理手段。如果留心使用异常,它可以成为程序员们知识工具箱中的一项有益补充,同时也应该在异常和其他处理手段之间进行权衡比较。
6. 针对产品代码的限制并不试用于开发中的软件。你可以利用这一优势在开发中添加有助于更快地排查错误的代码。
第9章要点 伪代码编程过程
1. 创建类和子程序通常都是一个迭代的过程。在创建子程序的过程中获得的认识常常会反过来影响类的设计。
2. 编写好的伪代码需要使用易懂的英语,要避免使用特定编程语言中才有的特性,同时要在意图的层面上写伪代码(即描述该做什么,而不是要怎么去做)。
3. 伪代码编程过程是一个行之有效的做详细设计的工具,它同时让编码工作更容易。伪代码会直接转化为注释,从而确保了注释的准确度和实用性。
4. 不要只停留在你所想到的第一个设计方案上。反复使用伪代码做出多种方案,然后选出其中最佳的一种方案在开始编码。
5. 每一步完成后都要检查你的工作成果,还要鼓励其他人帮你来检查。这样你就会在投入精力最少的时候,用最低的成本发现错误。
第10章要点 使用变量的一般事项
1. 数据初始化过程很容易出错,应当多加注意。
2. 最小化每个变量的作用域。把同一变量的引用点集中在一起,把变量限制在子程序或类的范围之内,避免使用全局数据。
3. 把使用相同变量的语句尽可能集中在一起。
4. 早起绑定会减低灵活性,但有助于减小复杂度。晚期绑定可以增加灵活性,同时增加复杂度。
5. 把每个变量用于唯一的用途。
第11章 变量名的力量
1. 好的变量名是提高程序可读性的一项关键要素。对特殊种类的变量,比如循环下标和状态变量,需要加以特殊的考虑。
2. 名字要尽可能的具体。那些太模糊或者太通用以至于能够用于多种目的的名字通常都是很不好的。
3. 命名规则应该能够区分局部数据、类数据和全局数据。他们还应当可以区分类命名、具名变量、枚举类型名字和变量名。
4. 无论做哪种类型项目,你都应该采用某种变量命名规则。你所采用的规则的种类取决于你的程序的规模,以及项目成员的人数。
5. 现代编程语言很少需要用到缩写。如果你真的要使用缩写,请使用项目缩写词典或者标准前缀来帮助理解缩写。
6. 代码阅读的次数远远多于编写的次数。确保你所取得名字更侧重于阅读方便而不是编写方便。
第12章 基本数据类型
1. 使用特定的数据类型就意味着要记住适用于各个类型的很多独立的原则。用本章的核对表来确认你已经对常见问题作了考虑。
2. 如果你的语言支持,创建自定义类型会使得你的程序更容易修改,并更具有自描述性。
第13章 不常见的数据类型
1. 结构体可以使得程序更简单、更容易理解,以及更容易维护。
2. 每当你打算使用结构体的时候,考虑采用类是不是会工作得更好。
3. 指针很容易出错。用访问器子程序或类以及防御式编程实践来保护自己的代码。
4. 避免用全局变量,不只是因为它们很危险,还因为你可以用其他更好的方法来取代他们。
5. 如果你不得不使用全局变量,那么就通过访问器子程序来使用它。访问器子程序能为你带来全局变量所能带来的一切优点,还有一些额外好处。
注:访问器子程序通常就是指的方法。
第14章 组织直线型代码
1. 组织直线型代码的主要原则是按照依赖关系进行排列。
2. 可以用好的子程序名、参数列表、注释,以及------如果代码足够重要------内务管理变量来让依赖关系变得更明显。
3. 如果代码之间没有顺序依赖关系,那就设法使相关的语句尽可能地接近。
第21章 协同构建
1. 协同开发实践往往能比测试发现更多的缺陷,并且更有效率。
2. 通常,结对编程拥有和详查相同的成本,并能产生质量相当的代码。当需要缩短开发周期的时候,结对编程就非常有价值。相对于单独工作来说,有些开发人员更喜欢结对工作。
第22章 开发者测试
1. 同编码之后编写测试用例相比较,编码开始之前编写测试用例,工作量和花费的时间差不多,但是后者可以缩短缺陷-侦测-调试-修正这一周期。
2. 测试数据本身出错的密度往往比被测代码还要高。查找这种错误完全是浪费时间,又不能对代码有所改善,因此测试数据里面的错误更加让人苦恼。要想写代码一样小心的开发测试用例,这样才能避免产生这种问题。
3. 从长远来看,改善测试过程的最好办法就是将其规范化,并对其进行评估,然后从评估中获得经验教训来改善这个过程。
第23章 调试
1. 在动手解决问题之前,要理解问题的根本。胡乱猜测错误的来源和随机修改将会让你的程序陷入比刚开始调试时更为糟糕的境地。
2. 将编译器警告级别设置为最严格,把警告信息所报告的错误都改正。如果你忽略了明显的错误,那么要改正那些微妙的错误就会非常麻烦。
3. 调试工具对软件开发而言是强有力的支持手段。找出这些工具并加以应用,当然,请记得在调试的时候开动脑筋。
第24章 重构
1. 修改是程序一生都要面对的事情,不仅包括最初的开发阶段,还包括首次发布之后。
2. 在修改中软件的质量要么改进,要么恶化。软件演化的首要法则就是代码演化应当提升程序的内在质量。
3. 重构成功之关键在于程序员应该学会关注那些标志着代码需要重构的众多的警告或“代码臭味”。
4. 重构成功的另一要素是程序员应当掌握大量特定的重构方法。
5. 重构成功的最后要点在于要有安全重构的策略。一些重构方法会比其它重构方法要好。
6. 开发阶段的重构是提升程序质量的最佳时机,因为你可以立刻让刚刚产生的改变梦想变成现实。请珍惜这些开发阶段的天赐良机。
第25章 代码调整策略
1. 定量测量是实现性能最优化的关键。定量测量需要找出能真正决定程序性能的部分,在修改之后,应当通过重复测量来明确修改是提高还是降低了软件的性能。
2. 绝大多数的程序都有那么一小部分代码耗费了绝大部分的运行时间。如果没有测量,你不会知道是哪一部分代码。
3. 代码调整需要反复测试,这样才能获得理想的性能提高。
4. 为性能优化工作做好准备的最佳方式就是在最初阶段编写清晰的代码,从而使代码在后续工作中易于理解和修改。
第26章 代码调整技术
1. 优化结果在不同的语言、编译器和环境下有很大差异。如果没有对每一次的优化进行测量,你将无法判断优化到底是帮助还是损害了这个程序。
2. 第一次优化通常不会是最好的。即使找到了效果很不错的,也不要停下扩大战果的步伐。
3. 代码调整这一话题有点类似于核能,富有争议,甚至会让人冲动。一些人认为代码调整损害了代码可读性和可维护性,他们绝对会将其弃之不用。其他人则认为只要有适当的安全保障,代码调整对程序是有益的。如果你决定使用本章所述的调整方法,请务必谨慎行事。
第27章 程序规模对构建的影响
1. 在其他条件都相等的时候,大项目的生产率会低于小项目。
2. 在其他条件都相等的时候,大项目的每千行代码错误率会高于小项目。
3. 在小项目里的一些看起来“理当如此”的活动在大项目中必须仔细地计划。随着项目规模扩大,构建活动的主导地位逐渐降低。
4. 放大轻量级的方法论要好于缩小重量级的方法论。最有效的办法是使用“适量级”方法论。
第30章 编程工具
1. 程序员有时会在长达数年的时间里忽视某些最强大的工具,之后才发现并使用之。
2. 好的工具能让你的日子过得安逸得多。
3. 下面这些工具已经可用了:编辑、分析代码质量、重构、版本控制、除错、测试、代码调整。
4. 你能打造许多自己用的专用工具。
5. 好的工具能减少软件开发中最单调乏味的工作的量,但它不能消除对“编程”的需要,虽然它会持续的重塑(reshape)“编程”的含义。
第32章 自说明代码
1. 该不该注释是个需要认真对待的问题。差劲的注释只会浪费时间帮倒忙,好的注释才有价值。
2. 源代码应当含有程序大部分的关键信息。只要程序依然在用,源代码比其他资料都能保持更新,故而将重要的信息融入代码是很有用处的。
3. 好代码本身就是最好的说明。如果代码太糟糕,需要大量的注释,应先试着改进代码,直至无需过多注释为止。
4. 注释应说出代码无法说出的东西------例如概述或用意等信息。
5. 有的注释风格需要许多重复性劳动,应舍弃之,改用易于维护的注释风格。
第33章 个人性格
1. 人的个性对其编程能力有直接影响。
2. 最有关系的性格为:谦虚、求知欲、诚实、创造性和纪律,以及高明的偷懒。
3. 程序员高手的性格与天分无关,而任何事都与个人发展相关。
4. 出乎意料的是,小聪明、经验、坚持和疯狂既有助也有害。
5. 很多程序员不愿意主动吸收新知识和技术,只依靠工作时偶尔接触新的信息。如果你能抽出少量时间阅读和学习编程知识,要不了多久就能鹤立鸡群。
6. 好性格与培养正确的习惯关系甚大。要成为杰出的程序员,先要养成良好习惯,其他自然水到渠成。
第34章 软件工艺的话题
1. 编程的主要目的之一是管理复杂性。
2. 合作开发是要求团队成员之间进行广泛沟通,甚于同计算机的交互;而单人开发则是自我交流,其次才是与计算机。
3. 编程规范一旦滥用,只会雪上加霜;使用得当则能为开发环境带来良好机制,有助于管理复杂性和相互沟通。
4. 编程应基于问题域而非解决方案,这样便于复杂性管理。
5. 注意警告信息,将其作为编程的疑点,因为编程几乎是纯粹的智力活动。
6. 开发时迭代次数越多,产品的质量越好。
7. 墨守成规的方法有悖于高质量的软件开发。请将编程工具箱中填满各种编程工具,不断提高自己挑选合适工具的能力。