`
sunxboy
  • 浏览: 2828096 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

代码大全-读书笔记

阅读更多

整一个月把这本<<代码大全>>看完了,受益不浅。
整理了一下读书笔记,备忘。

设计是一个启发式过程

关注质量就是提高生产力的最佳途径

就像修建建筑物一样,项目的成败很大程度上在构建活动开始之前就已经注定了。

优秀的程序员永远是紧缺的。

程序员是软件食物链的最后一环,架构师吃掉需求,设计师吃掉架构,而程序员则消化设计。

在构建活动开始之前清除一个错误,那么返工的成本仅仅是“在开发过程的最后阶段做同样事情”的十分之一到百分之一。

三种常见的软件项目种类及其典型的良好实践
    典型应用
商业系统: internate站点,intranet站点,库丰管理,游戏,管理信息系统,工资系统
    生命周期模型
    敏捷开发(极限编程、Scrum、time-box开发等) 渐进原型(prototyping)
    计划与管理
    增量式项目计划、随需测试与QA计划、非正式的变更控制
    需求
    非形式化的需求规格
    设计
    设计与编码是结合的
    构建
    结对编程或独立编码、非正式的check-in手续或check-in手续
    测试与QA
   开发者测试自己的代码、测试先行开发、很少或没有测试(由单独的测试小组来做)
    部署
    非正式的部署过程
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     典型应用
使命攸关的系统: 嵌入式软件、游戏、internet站点、盒装软件、软件工具、webservices
     生命周期模型
     分阶段交付、渐进交付、螺旋型开发
     计划与管理
     基本的预先计划、基本的测试计划、随需QA计划、正式的变更控制
     需求
     半形式化的需求、规格、随需的需求评审
     设计
     架构设计、非形式化的详细设计、随需的设计评审
     构建
     结对编程或独立编码、非正式的check-in手续、随需代码评审
     测试与QA
    开发者测试自己的代码、测试先行开发、单独的测试小组
     部署
     正式的部署过程
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     典型应用
性命攸关的嵌入式系统: 航空软件、嵌入式软件、医疗设备、操作系统、盒装软件
     生命周期模型
     分阶段交付、螺旋型开发、渐进交付
     计划与管理
     充分的预先计划、充分的测试计划、充分的QA计划、严格的变更控制
     需求
     形式化的需求规格、形式化的需求检查
     设计
     形式化的架构检查、形式化的详细设计、形式化的详细设计检查
     构建
     结对编程或独立编码、正式的check-in手续、正式的代码检查
     测试与QA
    开发者测试自己的代码、测试先行开发、单独的测试小组、单独的QA小组
     部署
     正式的部署过程
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

在序列式开发法和迭代式开发法之间做出选择
更加序列化的方法
1.需求相当稳定
2.设计直截了当,而且理解透彻。
3.开发团队对于这一应用领域非常熟悉。
4.项目的风险很小
5.长期可预测性很重要
6.后期改变需求、设计和编码代价很可能较昂贵。

更迭代的方法
1.需求并没有被理解透彻,或者出于其他理由你认为它是不稳定的。
2.设计很复杂,或者有挑战性,或者两者兼具。
3.开发团队对于这一应用领域不熟悉。
4.项目包含许多风险。
5.“长期可预测性”不重要
6.后期改变需求、设计和编码的代价很可能较低。

花费在问题定义、需求分析、软件架构上的时间,依据项目的需要而变化。一般说来,一个运作良好的项目会在需求、架构以及其他前期计划方面投入10%-20%的工作量和20%-30%的时间。这些数字不包括详细设计的时间---那是构建活动的一部分。

关于需求的书籍
==============
Wiegers,karl.<<Software Requirements>> 中译本:<<软件需求>>清华大学出版社
Robertson,Suzanne and James Robertson.<<Mastering the Requirements Process>> 中译本:<<掌握需求过程>>人民邮电出版社
Gillb,Tom.<<>Competitive Engineering>

关于软件架构的书籍
==================
Bass,Len,Parl Clements,and Rick Kazman.<<Software Architecture in Practice>>
Buschman,Frank,et al.<<Pattern-Orented Software Architecture,Volume I:A System Of Patterns>>
Clements,Paul,ed.<<Documenting Software Architectures:Views and Beyond>>
Clements ,Paul,Rick Kazman,and Mark Klein<<Evaluating Software Architectrues:Methods and Case Studies>>
Fowler,Martin.<<Patterns of Enterprise Application Architecture>>

Jacolbson,lvar,Grady Booch,and James Rumbaugh.<<The Unified Software Development Process>>

在哲学界,本质的属性是一伯事件必须具备、如果不具备就不再是该事物的属性。

有两种设计软件的方式:一种方法是让设计非常简单,看上去明显没有缺陷;另一种方式是让设计非常复杂,看上去没有明显的缺陷。
从本质上说软件开发就是不断去发掘错综复杂、相互连接的整套概念的所有细节。其本质的困难来自很多方面:必须去面对复杂、无序的现实世界;精确而完整地识别出各种依赖关系与例外情况;设计出完全正确而不是大致正确的解决方案;诸如此类。

项目失败的大多数都是由差强人意的需求、规划和管理所导致的。但是,当项目确由技术因素导致失败时,其原因通常就是失控的复杂度。
在软件架构的层次上,可以通过把整个系统分解为多个子系统来降低问题的复杂度。
保持子程序的短小精悍也能帮助你减少思考的负担。从问题的领域着手,而不是从底层实现细节入手去编写程序,在最抽象的层次上工作,也能减少人的脑力负担。
把任何人在同一时间需要处理的本质复杂度的量减到最少。
不要让偶然性的复杂度无谓地快速增长。

高质量设计的特征:
最小的复杂度:要避免做出“聪明的”的设计,因为“聪明的”设计常常都是难以理解的。
易于维护:易于维护意味着在设计时为做维护的程序员着想。
松散耦合:设计出相互尽可能最少的类。
可扩展性:你能增强系统的功能而无须破坏其底层结构。
可重用性:系统的组成部分能在其他系统中重复使用。
高扇入:让大量的类使用某个给定的类。
低扇出:让一个类里少量或适中地使用其他的类。
可移植性:
精简性:一本书的完成,不在它不能加入任何内容的时候,而在不能再删去任何内容的时候。
层次性:尽是保持系统各个分解层的层次性。设计出来的系统应该筩在任意层次上观察而不需要进入其他层次。

格式化的基本原理指出,好的布局凸现程序的逻辑结构。

如果程序语句按照有意义的方式布局,高手能比新手更好发记住语句,而当语句乱七八糟时,高手的优势就不明显了。
好的布局主要是为了展现代码的逻辑结构。

通过不多的集中布局手段就能实现良好的布局。
正如将相关语句分级很重要一样,将不相关的语句分隔开也很有必要。
程序中空行的最佳比例约为8%-16%,高于16%后调试时间将显著延长。

请用缩进形式显示程序的逻辑结构,作为一项守则,那些逻辑上隶属某语句的语句都应缩进。
缩进二到四个空格最得当。
对包含两个以上的项的表达式,应该用括号去澄清之。

四种常见的布局风格:
纯块结构
模仿纯块结构
使用“begin-end”对(花括号)指定块边界
行尾布局

对于Java,标准操作就是使用纯块缩进结构。

有些程序元素的布局主要牵涉美观问题。然而,控制结构的布局却会影响可读性和可理解性,故而实践中应优先考虑之。

格式化控制结构块的要点:
不要用未缩进的begin-end对。别让begin和end两次缩进。
段落之间要使用空行。有些代码块没有用begin-end对界定。逻辑代码块(即属于一个整体的语句组)应该像英语中的段落那样对待。
单语句代码块的格式要前后统一。
对于复杂的表达式,将条件分隔放在几行上。
不用goto
case语句不要有行尾布局的例外
语句长度大约在80字符左右。
使用空格会让逻辑表达式更易读。
使用空格让数组引用更容易读。
使用空格让子程序参数更容易读。

使续行明显
语句有时需分为几行,要么由于太长,超过了允许的编程标准,要么因为占据一行会让行长得离谱。
断名最简单的方法是将第一行部分做成若干单独时就有明显语法错误的样子。
把紧密关联的元素放在一起,如果要断句,应将属于一体的东西放在一起,例如数组下标、子程序参数等。

对赋值语句后续行按标准量缩进
将每个语句单独置于一行
每行只声明一个数据
变量声明应尽是接近其首次使用的位置
合理组织声明顺序:

注释的缩进要与相应代码一致
每行注释用至少一个空行分开。

子程序的布局:
用空行分隔子程序的各部分
将子程序参数按标准缩进

在布局类接口时,一般应将类成员按如下顺序表示:
1。说明类及其完整用法的头部注释。
2。构造函数与析构函数
3。public子程序
4。protected子程序
5。private子程序和数据成员

类实现通常应按以下顺序排布:
1。描述类所在文件之内容的头部注释
2。类数据
3。public子程序
4。protected子程序
5。private子程序

如果文件包含多个类,要清楚地标出每一个类
用空行将类与相邻类分开。
不要在类里过度注释

文件和程序布局
一个文件应只有一个类
文件的命名应与类名有关
在文件中清晰地分隔各子程序
至少用两个空行将各子程序分开,采用两到三行空格,可以清楚地表现出有关空行是子程序的一部分
,还是子程序之间的分隔。

外部文档
单元开发文件夹(unit-development folder,UDF)
又称“软件开发文件夹”,是一种非正式文档,其中包含了供开发者在编程期间使用的记录。
UDF主要用途是提供在其他地方没有说明的设计决策踪迹。
详细设计文档
是低层次的设计文档,描述在类层或子程序层的设计决定,曾考虑过的其他方案,以及采用所选方案的理由。
内部文档
内部文档嵌入于程序清单本身,是最详细的文档,位于源码层次上,是代码修正后最可能保持正确的那种文档。
在代码层文档中起主要作用的因素并非注释,而是好和编程风格。编程风格包括良好的程序结构、直率易懂的方法、
有意义的变量名和子程序名、具名常量(而非文字常量)、清晰的布局,以及最低复杂度的控制流及数据结构。

注释种类
重复代码:只是用不同文字把代码的工作又描述了一次。
解释代码:通常用于解释复杂、有巧、敏感的代码块,但通常正是因为代码含混不清,才体现出这类注释的价值。
代码标记:
标记性注释并非有意在代码中,它提醒开发者某处的工作未做完。统一为特定的标记风格。
概述代码:
将若干代码行的意思以一两句话说出来。
代码意图说明:
目的性注释用来注释一段代码的意图,它指出要解决的问题,而非解决的方法。
代码无法表述的信息:
某些信息不能通过代码来表达,但又必须包含在源代码中。这种注释包括版权声明、保密要求、版本号等杂项信息;与代码设计有关的注意事项;相关要求或者架构文件的索引;联机参考链接,优化注记等等。

对于完工的代码,只允许有的三种注释类型:代码无法表述的信息、目的性注释和概述性注释。
高效注释的指导原则:
采用不会打断或抑制修改的注释风格
/***********************************************************
 class:GigaTion (GIGATION.CPP)

 author:Dwight H.Coder
 date:July 4,2014

 Routines to control the twenty first century's code evaluation
 tool. The entry point to these routines is the EvaluateCode
 routine at the bottom of this file.
***********************************************************/
对Java的一般原则是应对单行注释使用“//”,而对较长注释应用“/*...*/”

用伪代码编程法减少注释时间
由于在直译低层次的编程语言代码前,就已写出高层次的伪代码,因而可以获得所有设计方面的好处。
将注释集成到你的开发风格中。
性能不是逃避注释的好借口
IBM的研究发现,约每十条语句有一个注释,这样的密度时程序清晰度最高。

注释技术:
注释单行
对于好的代码,很少需要注释单条语句,要注释一行代码,有两个可能的理由:
该行代码太复杂,因而需要解释。
该行语句出过错,你想记下这个错。
关于单行注释,指导原则:
不要随意添加无关注释。
行尾注释及其问题:维护起来会很困难。
不要对单行代码做行尾注释。
不要对多行代码做行尾注释。
有三种例外情况:
行尾注释用于数据声明
避免用行尾注释存放维护注记
用行尾注释标记块尾:用行尾注释标记大的代码块的结束位置是很合适的。如while或if语句

注释代码段
注释应表达代码的意图
一种在意图层写注释的办法,就是想象如果将这段代码换成同样功能的子程序,会怎样命名它。
代码本身应尽力做好说明
注释代码时应注重“为何做”,而不是“怎么做” (用有意义的枚举来代替0,变量再换好一些的名)
用注释为后面的内容做铺垫:好的注释会告诉读者后面有什么内容。
让每个注释都有用
说明非常规做法:假如代码本身有些含义未表达明显,就把这些含义放在注释里。
别用缩略语:注释不应有歧义,应当易读而无须猜测缩写为何意。
将主次注释区分开
//copy the string portion of the table ,along the way omitting
//strings that are to be deleted
//-------------------------------------------------------------

//determine number of strings in the table
...
还有一种通常是最好的办法---将主注释所述的操作独立为子程序。
错误或语言环境独特点都要加注释。
给出违背良好编程风格的理由。

不要注释投机取巧的代码,应重写之。注释不应帮扶难度大的代码。
若某事对你来说像是技巧,对别人来说会难以理解。你总会找到不用技巧的方法,因而请重写代码。将代码完善到没有注释的最好程度,然后添加注释使其更完善。
注释数据声明:
变量声明的注释应给出变量未表达出来的各种信息。
注释数值单位:如果某数值表示长度,请指明长度单位是什么。
对数据的允许范围给出注释
注释编码含义
注释对输入数据的限制
将与变量有关的注释通过变量名关联起来。(连同更新)
注释全局数据,如果用了全局数据,要在其声明处做出注释。
应在每个if,case,循环或者代码前面加上注释。
应在每个控制结构后加上注释。
将循环结束处的注释看成是代码太复杂的征兆。

注释子程序的指导原则:
注释应靠近其说明的代码。子程序不该有庞大的注释头。
在子程序上部用一两句话说明之,如果不能用一两话说清楚,有必要考虑你到底想让子程序做什么。
原则上所有子程序都应附概述性说明,除非已有很简单的Get/Set访问器子程序。
在声明参数外注释这些参数。
利用诸如javadoc之类的代码说明工具
注释接口假设
对子程序的局限性作注释
说明子程序的全局效果
记录所用算法的来源
用注释标记程序的各部分

标注类的一般原则:
说明该类的设计方法
说明局限性、用法假设等。
注释类接口
不要在类接口处说明实现细节

注释文件的一般原则
在文件开头处用注释说明文件的内容
说明各文件的意图和内容
将姓名、电子邮件及电话号码放到注释块中
包含版本控制标记
请在注释块中包含法律通告
将文件命名为与其内容相关的名字


很多好的编程做法都能减轻你的大脑灰质细胞的负担:
1.将系统分解,是为了使之易于理解.
2.进行审查,评审和测试正是为了减少人为失误.
3.将子程序编写得短小,以减轻大脑负荷.
4.基于问题而不是低层实现细节来编程,从而减少工作量.
5.通过各种各样的规范,将思路从相对繁琐的编程事务中解放出来.
研究表明谦虚的程序员善于弥补其不足之处,所编写的代码让自己和它人都易看懂,其中的错误也较少.

犯错不是罪过,从中学不到什么才是罪过.
学习编程的一个特别好的途径是研究高手的程序.

编程生涯成熟的部分标志就是发展出一种不屈不挠的诚实感.通常表现为以下几个方面:
1.不是高手时不假装是高手.
2.乐于承认错误.
3.力图理解编译器的警告,而非弃之不理.
4.透彻理解自己的程序,而不要只是编译看看能否运行.
5.提供实际的状况报告.
6.提供现实的进度方案,在上司面前坚持自己的意见.

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

我们的精神品德既非与生俱来,也非逆于天性.....其发展归因于习惯......我们要学的东西都通过实际做的过程学到......如果人们建的房子好,我们就成为好的建设者,而造的房子不好时,我们就是差的建设者......所以小时候形成了怎样的习惯关系很大----正是它会造成天壤之别,或者说就是世上所有差异之源.                                              
                                                              ---亚里士多德
要培养先以伪代码编写类,再改用实际代码,以及编译前认真检查代码的习惯.

总而言之,软件设计与构建的主要目标就是征服复杂性,许多编程实践背后的动机正是为了降低程序的复杂度.降低复杂度几乎是衡量程序员成果的最重要依据.

对于小的项目,程序员的个人才能对软件质量影响最大.程序成功与否部分取决于其对开发过程的选择.
对于多个程序员参与的项目,组织性和重要性程序超过了个人技能.即使你有一个庞大的团队,其合力并等于每个人能力的简单相加.人们一起工作时的方式将决定其能力是珠联璧合还是相互抵消.

关于开发过程的重要性,一个明显的例子是看看在需求还未确定就开始设计和编码的后果.
开发过程之所以重要,主要原因是软件开发中,质量一开始就要逐步建立起来.这与那种先拼凑代码,再通过测试剔除缺陷的思路相悖.
不成熟的优化是另一个过程性错误,行之有效的开发过程是在开始时粗调,后来再进行精调.
低层的过程也很重要,如果遵照写伪代码再对其填充代码的步骤,就能享受到自上而下的设计好处.你也应确保向代码中加入注释,而不是以后再添加进去.

在问题域使用类,来实现有实际意义的结构
隐藏低层数据类型及其实现细节的信息.
使用具名常量来说明字符串和文字量的意义.
对中间计算量结果使用中间变量.
用布尔函数使复杂逻辑判断更清晰.

关键是对软件开发的各方面,你都应保持开放的心态,这样才能从开发过程和产品中有所收获.
<<Programmers at Work>>
<<程序开发心理学>>

分享到:
评论
1 楼 sunxboy 2008-02-18  
一个好的OO系统几乎在业务逻辑层看不到超出两个以上条件的if else等判断语句,这些条件语句都是可以被GoF设计模式的状态模式/策略模式等替代。

相关推荐

Global site tag (gtag.js) - Google Analytics