代码大全 学习笔记

说明:这本书的确是好,以文字只能记录少许,作为大纲而已,具体的知识复习最好还是看原书,多看几遍,其义自见。

 

第10章

1.     在声明变量的时候初始化(不是单纯赋0);

在靠近变量第一次使用的位置初始化;

2.     Const在定义类常量、输入参数、以及任何初始化后其值不再发生改变的局部变量时非常有用;

3.     计数器、累加器在下一次使用时忘记重置也是常见的错误,如ijk,count等;

4.     尽可能缩短变量存活时间。当把一个大程序分成多个子程序时,短的变量存货时间也很有价值;(全局变量尽可能少用)

5.     在循环开始之前去初始化该循环里使用的变量,而不是在该循环所属的子程序开始处初始化这些变量;直到变量即将被使用时再为其赋值;与扩充一个作用于小的变量的作用于相比,缩减一个已经有很大作用于的变量的作用域是非常困难的;

6.     具名常量的使用;

7.     每个变量都只用于单一用途;

8.     确保使用了所有已经声明的变量,为引用的变量数量与错误率成正比;

 

第11章

1.     对变量的恰如其分的描述就是最好的变量名;

2.     当用totalmaxsumaverage、等限定词时,请记住把这个限定词加到名字的最后;保持命名一致性;

3.     由于代码会经常修改、扩充,或者复制到其他程序中去,因此很多有经验的程序员索性不适用ijk这样的变量;eventIndexi好多了;

4.     状态变量不要用flag,要详尽些的名字;

5.     但是无论从哪种角度看,你程序中的大多数变量都是临时性的。把其中几个临时变量成为临时的,可能表明你还没有弄清楚他们的实际用途;

6.     命名规则还是有必要的,特别是多人共同开发项目,或者把一个程序交给另一位程序员来维护时;

7.     可以将子程序(函数)的首字母大写,以区分变量;

8.     缩写的一般原则,去掉所有的非前置音(computer->cmptr, screen->scrn,integer->intgr);去掉虚词,and or the等;去掉无用的后缀ed ,ing ;保留每个音节中最引人注意的发音;

9.     在代码里用缩写对照表解释极短的名字的含义;

10. 避免在名字中使用数字,拼错单词。。不要紧靠大小写区分变量名;

11. 避免在名字中包含易混淆的字符,如1,I,l。。。。。。

12. 命名规则应该可以区分局部变量、全局变量和类数据;

13. 阅读代码的次数远远多于编写的次数;

 

第12章

1.     避免使用“神秘数值”,使用具名常量:修改会变得更可靠,修改会变得更容易;你的代码变得更可读;

2.     一条很好的经验法则是,程序主体中仅能出现的数字量就是0和1;

3.     每次使用除法符号时,分母是否为0?

4.     避免混合类型的比较;

5.     注意编译器的警告,杰出的程序员会修改他们的代码来消除所有的编译器警告;

6.     检查整数除法,整数溢出(还要考虑程序在未来的扩展)(检查中间结果溢出)

7.     对于浮点数,避免数量级相差太大的加减运算;

8.     浮点数避免等量判断;

9.     如果字符串太多,就会失控,并引发内存问题,对于嵌入式系统开发以及其他存储空间非常珍贵的应用中,这一点就必须考虑;

10. 字符和字符串字面表示的意思是模糊的,可以用具名常量代替;

11. C中,长度为n的字符串需要n+1的地址空间;

12. calloc()比malloc()多了一个初始化为0的功能;

13. 可以用布尔变量来简化判断条件;

14. 把枚举类型的第一个元素留作非法值;

15. 权威人士建议:永远不要随即的访问数组,只能顺序的访问,因为在数组里随机访问就像在程序中随便使用goto语句一样,这种访问很容易变得难以管理且容易出错。建议使用集合、栈、队列等按顺序存取元素的数据结构来取代数组。

16. #defineARRAY_LEAGTH(x) (sizeof(x)/sizeof(x[0])) 更灵活使用数组;

17. 永远不要“信任”客户初期提出的指标要求,他随时会更改的更苛刻;

 

第13章

1.     可以用结构体来简化对数据块的操作,也可以明确数据关系,以及简化参数列表;

2.     把指针操作限制在子程序或者类里。假设你在程序中多次使用了一个链表,每次使用它时,不要通过手动操作指针去遍历该链表,应该编写一组诸如NextLink(),PreviousLink(),InsertLink(),DeleteLink(),这样的访问器子程序来完成操作更好些。减少访问指针代码的数量,你就减小了犯下遍布程序各处、永远也找不完的粗心过错的可能性。为指针分配编写子程序是另一种控制数据的方法;

3.     同时声明和定义指针;

4.     在与指针分配相同的作用域删除指针;

5.     在使用指针前检查指针,先检查指针所引用的变量再使用它;

6.     不要把同一个变量用于多种用途,这一点对于指针来说尤为重要;

7.     如果在你的代码中包含了一个复杂的表达式,那么就把他赋值给一个命名良好的变量,已明确该操作的用意,同时还可能起到简化循环内操作的作用;

8.     在删除或释放指针之后把它们设置为空值:悬空指针,即使用一个已经被delete或者free的指针;

9.     破坏程序的最好办法之一就是在已经删除或者释放了一个指针之后再delete或者free它;

10. 如果能想到可以替代指针的方案,且工作的很合理,就去用吧~

11. C++引用,必须总是引用一个对象,而指针可以指向空值,还有就是引用所指向的对象在该引用初始化之后不能改变;

12. 避免使用强制类型转换;

13. 模块化、信息隐藏并结合使用设计良好的类可能还算不上绝对真理,但是他们能极大的提升大型程序的可理解行和可维护性;

14. 避免使用全局变量;

15. 使用全局变量的理由:

用到在概念上用于整个程序的数据,如一个用于表示程序状态的变量;

模拟具名常量,如true false等;

消除流浪数据;

16. 首先把每一个变量设为局部的,仅当需要时才把变量设置为全局的;

17. 使用全局变量能做的任何事情,都可以用访问器子程序做的更好;

 

第14章

1.     如果语句之间存在依赖关系,并且这些关系要求你把语句按照一定的顺序加以排列,那么请设法是的这些依赖关系变得明显;

2.     利用子程序名凸显依赖关系,利用子程序参数明确显示依赖关系,例如在一起排列的几个子程序都使用了同一个参数,那么就能说明他们是联系在一起的;

3.     就像写文章一样,段与段之间(一大段子程序与子程序之间),句与句之间(代码行之间)是按照作者的思路来安排的一样,我想,好的文章行文流畅,构思严谨巧妙,好的代码也是一个道理;

4.     作为一条普遍规律,要让程序易于自上而下阅读;

5.     把相关语句组织在一起,你有可能发现他们之间有很强的联系,而与它们前后的语句组没有多少有意义的联系,在这种情况下,你可能希望把这些关联很强的语句重构成独立的子程序;(具体参见P352的方框图,很形象,也能说明使用goto的坏处)

 

第15章

1.     对于if语句,先写正常的代码路径,再处理不常见的情况;确保等量分支正确;把正常情况的处理放在if后而不是else后面;

2.     让if子句后跟随一个有意义的语句;

3.     尽量写else语句,即便else为空,但这样至少可以促使程序员在编写代码的时候考虑else情况。如果else为空,请用注释解释为什么在这里else子句是没有必要的;

4.     Case语句的排列,可以按照执行频率排列case子句,也可以吧正常的情况放在前面;或者按照字母顺序排列;

5.     如果某个case后情况较为复杂,就写一个子程序来处理;

6.     对于default子句只用来检查真正的默认情况,而不要用来处理剩下的某种情况;

 

第16章

1.     使用循环是编程中最复杂的方面之一:知道如何以及何时使用每一种循环是创建高质量软件的一个决定性因素;

2.     使用带退出的循环,把所有的退出条件放在一起,用注释来阐明操作意图;

3.     如果你要执行次数固定的循环,for是好选择(不需要循环内部控制);如果存在一个必须使执行从循环中跳出的条件,那么就应该改用while循环;

4.     把循环内部当成一个子程序看待——把控制尽可能的放到循环体外,把循环看做一个黑盒子;

5.     对于进入循环的指导原则:

只从一个位置进入循环;

把初始化代码仅放在循环前面:就进原则主张把相关语句放在一起;因为如果不这么做的话,一旦把该循环放在一个更大的循环中,并忘记修改相应的初始化代码,就会导致错误;在你把循环代码移动或复制到另一个子程序中,却没有移动或复制初始化代码的时候,也会发生同样的问题;

6.     使用 { } 把循环中的语句括起来,哪怕只有一句话;

7.     一个循环只做一件事情,循环应该和子程序一样,每个循环只做一件事情,并把他做好;

8.     避免依赖于循环下标最终取值的代码;

9.     Break语句不能用于除循环与switch之外的任何其他语句;

10. 检测循环的端点情况,确认不会出现offbyone的情况;是否愿意执行这种检查,是高效程序员与低效程序员之间的一项关键差别;

11. 把循环内容限制在一页纸以内,嵌套限制在3层以内;

 

第17章

1.     如果能增强可读性,那就使用return;

2.     谨慎的使用goto可以减少重复代码体积,最好还是不用,缺点太多;

 

第18、19章

1.     对于布尔表达式,最好用TRUE好FALSE而不是1和0。因为有的时候代码根本没有反映出究竟1代表的是真,0代表的是假,还是恰好相反。甚至连1、0是不是代表真和假也不清楚;

2.     判断条件较复杂时,可以使用变量或者子函数返回值的方法来替代;

3.     在if中,把判断条件从否定形式转换为肯定形式,并且互换if和else子句的代码;或者把变量换一个名字,!statusOk 替换成 ErrorDetected;

4.     If( !A|| !B)  ==  if(!(A && B));

5.     对括号的计数技巧,左括号+1,右括号-1;

6.     对于C家族语言中,应该把常量放在比较的左端;

7.     把数和0比较,while( balance != 0 ) 比较好,而while( balance )则不好;

8.     小心使用空语句,应该突出这种用法,可以让空语句的分号独占一行,或者用一组括号来强调;或者,为空语句定义一个DoNothing()函数;例如:

#define DoNothing()

…..

While(statusNotRdy)

{

       DoNothing();

}

9.     如何将深层嵌套展开,在P445-P453中,有着一些技巧介绍;复杂的代码表明你还没有充分的理解你的程序,所以无法简化他。深层嵌套是一个警告,他说明要么你拆分出子程序,要么应该重新设计那部分复杂代码;

10. 结构化编程的核心思想很简单,那就是一个程序应该只采用一些单入单出的控制结构,即一个代码块,只能从一个位置开始执行,并且只能结束于一个位置。一个结构化的程序将按照一种有序的且有规则的方式运行,不会做不可预知的随便跳转;

11. 结构化编程的三个组成部分:顺序、选择、迭代(循环)。

结构化编程的中心论点是:任何一种控制流都可以由顺序、选择和迭代这三种结构生成;

12. 复杂度判断与度量,详见P458;

 

第20章

1.     效率(占少的系统资源,内存和执行时间)

适应性

可靠性(很长的平均无故障时间)

健壮性(接受无效输入或者压力环境时继续正常运行的能力)

可维护性

2.     质量保证的一部分就是制定出一套与产品需求、架构以及设计相关联的测试策略;

3.     变来变去的自然影响就是质量不稳定的恶化,因此,有效地管理变更是实现高质量的一个关键;

4.     制作原型,是指开发出系统中关键功能的实际模型。结果表明,构建原型能产生更完善的设计,更贴近用户的要求,以及更好的维护性;

5.     一个缺陷存在的时间越长,消除他的代价就越高;

6.     既不是最快也不是最慢的开发方法生产出的软件缺陷最多;

 

第21章

1.     在工作中,开发人员总会对自己的某些错误点视而不见,而其他人不会有相同的盲点,所以开发人员让其他人来检查自己的工作室很有好处的;

2.     由有经验的人员复查新人的代码是培养新人以提高其代码质量的好机会;复查可以快速的将所有开发者的水平提升到最优秀的开发者高度;

 

第22章

1.     测试包括:单元测试;组件测试;集成测试;回归测试;系统测试

分类:黑盒测试、白盒测试;

2.     测试时要求你假设在代码里面找到错误;

3.     在开始写代码之前写测试用例,并不比之后再写要多花功夫,只是调整了一下测试用例编写活动的工作顺序而已;且这将迫使你在开始写代码之前至少思考一下需求和设计,而这往往会催生出更高质量的代码;且能更早的把需求上的问题暴露出来;

4.     因此,测试的窍门在于选择那些最有可能找到错误的测试用例;

5.     有一种边界条件更加隐蔽,就是当边界条件涉及到互相关联的多个变量的时候,例如两个变量相乘;

6.     误区:缺陷在代码里面是均匀分布的;

      而是集中在少数几个子程序里面;

7.     大多数错误的影响范围是相当有限的,85%的错误可以在修改不超过一个子程序的范围内得意修正;

8.     三种最为常见的错误源头:缺乏应用领域知识、频繁变动且相互矛盾的需求、以及沟通和协调的失效;

9.     大多数构建期错误是由编程员的失误造成的,95%!

10. 15-20%的错误是由于对设计的错误理解造成的,因此,花点时间来彻底理解设计是很值得的;

11. 保留测试记录:缺陷的管理方面的描述(报告日期、报告人、描述或标题、生成编号、以及修正错误的日期等)

问题的完整描述;

复现错误需要的步骤;

绕过该问题的建议;

问题的严重程度(致命、严重、表面)

缺陷根源(需求、设计、编码、测试)

对编码缺陷的分类:offbyone,错误赋值、错误数组下标、子程序调用错误等;

修改错误所改变的类和子程序;

缺陷所影响的代码行数;

查找该错误的所花费的小时数;

修正错误所花费的小时数;

 

第23章

1.     理解你正在编写或者维护的程序,因为如果你确实已经透彻的理解了他,这个程序就不应该有缺陷,你应该早就纠正了这些缺陷;

2.     一旦你发现了错误,请问问自己为什么会犯这样的错误。如何才能更快的发现这个错误?如何预防此类错误的发生?代码里面还有类似的错误么?

3.     审视自己解决问题的方法;

4.     调试误区:

     凭猜测找出缺陷;

        不要把时间浪费在理解问题上;

     用嘴唾手可得的方式修改错误(改特殊值);

5.     即便某个错误初看似乎不能归咎于你,但出于你自身的利益,最好还是假设他的产生同你相关,这样的假设有助于你的调试;

6.     思考,假如你要调查一桩谋杀案,哪个会更有趣?是整个城镇挨家挨户确认,还是通过蛛丝马迹推断凶手身份?

7.     科学的调试方法:

a.     将错误状态稳定下来;

b.     确定错误的来源:

1.     手机产生缺陷的相关数据;

2.     分析所收集的数据,并构造对缺陷的假设;

3.     确定怎样去证实或证伪这个假设,可以通过对程序进行测试或者通过检查代码;

4.     按照3确定的方法对假设做出最终结论;

c.      修补缺陷;

d.     对所修补的地方进行测试;

e.     查找是否还有类似的错误;

8.     如果一个错误总是无法复现,这通常会是一个初始化错误,或者是一个同时间有关的问题,或者是悬空指针;

9.     缩小嫌疑代码的范围,可以用二分法;

10. 如果出现了一个难于诊断的新错误,这个错误通常是同那些最近修改的代码相关的;

11. ‘忏悔式讨论’,当你向其他人解释自己的程序时,常常能发现自己犯下的一些错误;

12. 在编译器报告了一个令人困惑的语法错误时,请看看错误行的前后代码;

13. 一旦反现了真凶,请尝试分析为什么编译器会提供错误的信息。更好的理解自己的编译器有助于查找将来的缺陷;

14. 找出没有配对的注释或者引号:/*”/**/ ,这行代码可以终结注释或字符串。

15. 让自己的代码质量一塌糊涂的最好方法,就是不懂装懂的手动修补程序缺陷;

16. 修改代码时一定要有一个恰当的理由;不要投机的修改代码;一次只做一个改动;

17. 如果你想不出如何查找类似缺陷,这就意味着你还没有完全理解这个问题;

18. 如果对程序提出了警告,这常常会表示你现在有了一个学习你所使用语言更多知识的良机;

19. 用对待错误的态度对待警告;

20. 在面向对象的编程中,很少会需要用到长度超过一个屏幕的子程序;

21. 重复粘贴即设计之谬(在某个地方的修改,你都不得不在另一处也修改);

 

第24章

1.     相对于大规模修改,小的修改更容易出错;

2.     不要把重构当成先写代码后改的代名词;

3.     当你对付某段混乱的代码时,一种屡试不爽的办法使这些代码靠近当前的代码规范,例如使用含义明确的变量名等,从而有效地将这部分代码引入到理想世界中。一次次这样处理下去。代码的基础质量就能迅速提升;

 

第25章

1.     对用户来说,程序员按时交付的软件,提供一个清爽的用户界面,避免系统死机常常比程序的性能重要;

2.     在花费时间处理一个性能问题之前,请想清楚你的确是在解决一个确实需要解决的问题。

3.     有些改变无法通过代码来实现,需要从设计的角度来更改;

4.     Pareto法则,80/20法则,程序员应当权衡代码的各个部分,找出最需要关注的地方,然后集中火力对付占用了绝大部分资源的少量代码;

5.     在讨论程序性能的时候,没有“可能”一词的位置,你应该实际的测试程序的性能;

6.     在最初的开发阶段,程序原老是把目光集中在优化上面会干扰自己对其他程序目标的理解和判断。(阅读一段新代码的时候也一样);

7.     程序正确性重要度远高于运行速度;

8.     分页的问题;

9.     一些优化的方法策略,详见P605;

第26章

1.     减小代码资源占用更主要的是通过类和数据结构的重新设计来实现的;

2.     详细操作见书中例子理解更深刻;

 

第33章

1.     多数时候软件开发中的坚持其实就是没有好处的“固执”。当在某段新代码上卡壳时,坚持很难让人称道。不妨另辟蹊径,尝试重新设计类,或者绕过去,以后回头再试。

一时解决不了的,设置底牌,譬如如果三十分钟内还解决不了,再花10分钟想想其他办法,如果还不行,暂且交给潜意识来解决吧。

2.     如果你工作10年,你会得到10年的经验还是1年经验的10次重复?必须检讨自己的行为,才能获得真正的经验。只有坚持不断的学习,才能获取经验;

3.     彻夜编程让你感觉像是世上最好的程序员,却要花几个星期去纠正你在短暂辉煌时埋下的失误。

4.     好习惯:要培养先以伪代码编写类再改用实际代码,以及编译前认真检查代码的习惯

5.     好习惯:力图理解编译器的警告,而非弃之不理。

6.     学习编程一个特别好的途径是研究高手的程序;并找一些一流的程序员评论你的代码。

多编写多练习;

7.     比尔盖茨说,任何日后出色的程序员前几年就做的很好。在你搞编程颇有些年头后,很难突然说“怎样才能使这个循环更快些呢?”或者“如何让这段代码更好看懂呢?”。优秀的程序员早就养成了这些习惯。

 


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值