世间本无沙漠, 我每想你一次, 上帝就落下一粒沙, 从此便有了撒哈拉! 这世界本来没有海, 只因为我每想你一次, 上帝就掉下一滴眼泪, 于是就有了太平洋!

【如何阅读别人的代码】

上一篇 / 下一篇  2007-04-01 14:07:51 / 个人分类:有用才行

++++++++++++★黑基空间★$zhd-r"N.Fc$k(\E
★黑基空间★r!l%h IKK
第一章: 导论★黑基空间★EC_)i"H3{-l"]^ ^x

(\3l/P~D0++++++++++++
;`T3u[ z6H(M8A*L0★黑基空间★ G|+UPE1c/i/S
★黑基空间★C1h*j/US3Ma-fc

fo9h6Wz01.要养成一个习惯, 经常花时间阅读别人编写的高品质代码.★黑基空间★7bJ$`\xyI

,q Pkg)~(l H02.要有选择地阅读代码, 同时, 还要有自己的目标. 您是想学习新的模式|编码风格|还是满足某些需求的方法.★黑基空间★,?6CC9\.?9Sv U
★黑基空间★8E~ ?.K$B2x lG$r"J
3.要注意并重视代码中特殊的非功能性需求, 这些需求也许会导致特殊的实现风格.
2OLu8`~5pe0
/C;r9~ g;?s'{3fA04.在现有的代码上工作时, 请与作者和维护人员进行必要的协调, 以避免重复劳动或产生厌恶情绪.
*@+[8t"~ LDwW0
+H?&z S'EAvw2i05.请将从开放源码软件中得到的益处看作是一项贷款, 尽可能地寻找各种方式来回报开放源码社团.
(t8~ohO1dV0
j v5m0jY06.多数情况下, 如果您想要了解"别人会如何完成这个功能呢?", 除了阅读代码以外, 没有更好的方法.★黑基空间★*K%Cij#f.[8t

C)g8M{x.g0`0TC07.在寻找bug时, 请从问题的表现形式到问题的根源来分析代码. 不要沿着不相关的路径(误入歧途).★黑基空间★y)s&waA n
★黑基空间★VW%v,C8l
8.我们要充分利用调试器|编译器给出的警告或输出的符号代码|系统调用跟踪器|数据库结构化查询语言的日志机制|包转储工具和Windows的消息侦查程序, 定出的bug的位置.
D.@xA9zu0
I y!}Cc)h'h/e{09.对于那些大型且组织良好的系统, 您只需要最低限度地了解它的全部功能, 就能够对它做出修改.★黑基空间★E|ZN2l.w:c
★黑基空间★ _ za b+i;_
10.当向系统中增加新功能时, 首先的任务就是找到实现类似特性的代码, 将它作为待实现功能的模板.★黑基空间★woQ-i1MQ5v2cm
★黑基空间★6c7`8G k'~)N;cx@)]!f
11.从特性的功能描述到代码的实现, 可以按照字符串消息, 或使用关键词来搜索代码.
,?c%Y"\`hp t+N*e/p0★黑基空间★ c%Xz2k/b"pX/o
12.在移植代码或修改接口时, 您可以通过编译器直接定位出问题涉及的范围, 从而减少代码阅读的工作量.★黑基空间★(z(hD)K].adg1E
★黑基空间★+~6tI'SK)~
13.进行重构时, 您从一个能够正常工作的系统开始做起, 希望确保结束时系统能够正常工作. 一套恰当的测试用例(test case)可以帮助您满足此项约束.
h)VO|,u;I;X7O0
h"Ap7g-dU]O&g@014.阅读代码寻找重构机会时, 先从系统的构架开始, 然后逐步细化, 能够获得最大的效益.★黑基空间★-z!x)m%Y D8V7z

IZ-j|(s'Q6k]4~)p015.代码的可重用性是一个很诱人, 但难以理解与分离, 可以试着寻找粒度更大一些的包, 甚至其他代码.
j?,L m,ur0
R.l7N(o'GU;_)AO016.在复查软件系统时, 要注意, 系统是由很多部分组成的, 不仅仅只是执行语句. 还要注意分析以下内容: 文件和目录结构|生成和配置过程|用户界面和系统的文档.★黑基空间★U{%MLb&R3qAr h

$FXMD5E ]?018.可以将软件复查作为一个学习|讲授|援之以手和接受帮助的机会.★黑基空间★c0X%KVL
++++++++++++++++++++
8Th_ Z3cY6@0★黑基空间★*K%t)h@3m J#n,`d;E
第二章: 基本编程元素
GMv-qd#g0
3_TXh&X.Bi3sU0++++++++++++++++++++
Y,k#d`&]0★黑基空间★'Y![!l Z)K;Eq
★黑基空间★lI#}:QN5o2nX%|
★黑基空间★C_$Z;k+`T `5W
19.第一次分析一个程序时, main是一个好的起始点.★黑基空间★JvJ l7Js

T3oR*a{P{7M020.层叠if-else if-...-else序列可以看作是由互斥选择项组成的选择结构.★黑基空间★6J0P:s]'e'c!X

@,N Ah-p0H|021.有时, 要想了解程序在某一方面的功能, 运行它可能比阅读源代码更为恰当.
3es OWred,@]0
u"N2Qr[V5~[6x022.在分析重要的程序时, 最好首先识别出重要的组成部分.
d2];u0O/K*q$h7NA0★黑基空间★K"~ uU9\ Wo(KW"Q
23.了解局部的命名约定, 利用它们来猜测变量和函数的功能用途.
[/RBoL0★黑基空间★-R$og-B$t g,gl
24.当基于猜测修改代码时, 您应该设计能够验证最初假设的过程. 这个过程可能包括用编译器进行检查|引入断言|或者执行适当的测试用例.
L/L4bn2v d Il0
HHcMp:M^J025.理解了代码的某一部分, 可能帮助你理解余下的代码.
{ l@(?6i-I*l7i Vq8Ck0
0Qh b Yd3];~026.解决困难的代码要从容易的部分入手.
&wV(w(w@0★黑基空间★.r{IA QF
27.要养成遇到库元素就去阅读相关文档的习惯; 这将会增强您阅读和编写代码的能力.
+} OPN V l6O)s8Py xg0
.gTDs/xC+O1UC028.代码阅读有许多可选择的策略: 自底向上和自顶向下的分析|应用试探法和检查注释和外部文档, 应该依据问题的需要尝试所有这些方法.
G-j5V#K(l#\ t~&q0
g4v y_w)@ k]@*s029.for (i=0; i<n; i++)形式的循环执行n次; 其他任何形式都要小心.★黑基空间★a:c/AO*@#z1Q
★黑基空间★&L6N6f9j.@`6FcI
30.涉及两项不等测试(其中一项包括相等条件)的比较表达式可以看作是区间成员测试.★黑基空间★*G3{2H x8r9c'B'l(Y+m K%G
★黑基空间★3j&^tn%S|2@}['L b
31.我们经常可以将表达式应用在样本数据上, 借以了解它的含义.★黑基空间★8h1M-x1a&z?jZPJ

YY GPi h"[/a7L032.使用De Morgan法则简化复杂的逻辑表达式.
j:b k yy&G2f0★黑基空间★%{]R`)v$OE'X(Qy
33.在阅读逻辑乘表达式时, 问题可以认为正在分析的表达式以左的表达式均为true; 在阅读逻辑和表达式时, 类似地, 可以认为正在分析的表达式以左的表达式均为false.
c`4V;A2i]8Q]0★黑基空间★$tw7vNS$P
34.重新组织您控制的代码, 使之更为易读.
oZ }E8tK0★黑基空间★i6M O5{[,F9[_:bo
35.将使用条件运行符? :的表达式理解为if代码.★黑基空间★2i.l:z8}1K%{
★黑基空间★2ngMs5eQg`Cv#^ ^
36.不需要为了效率, 牺牲代码的易读性.★黑基空间★x7|Uw&C{
★黑基空间★1ns I:CXO BSt1f
37.高效的算法和特殊的优化确实有可能使得代码更为复杂, 从而更难理解, 但这并不意味着使代码更为紧凑和不易读会提高它的效率.
$VTxXs/z0★黑基空间★j3@2N/?-q
38.创造性的代码布局可以用来提高代码的易读性.★黑基空间★])^cg|x ^)?
★黑基空间★*{ kgM5j ZZ'n2X$E
39.我们可以使用空格|临时变量和括号提高表达式的易读性.
U.e)Wn[;[ J0★黑基空间★4C0\h!?n5?i2eg
40.在阅读您所控制的代码时, 要养成添加注释的习惯.★黑基空间★C%S#i7_qLy"d

5ifF&y'QN041.我们可以用好的缩进以及对变量名称的明智选择, 提高编写欠佳的程序的易读性.★黑基空间★y:L)c)~ k WA5a

4a"P*QSj`,H u042.用diff程序分析程序的修订历史时, 如果这段历史跨越了整体重新缩排, 常常可以通过指定-w选项, 让diff忽略空白差异, 避免由于更改了缩进层次而引入的噪音.★黑基空间★0H1G [tO6|

-?d`p9XFXM:h5?5^043.do循环的循环体至少执行一次.
0M0[Ct;reXTT_0★黑基空间★6o T0W cm@b
44.执行算术运算时, 当b=2n-1时, 可以将a&b理解为a%(b+1).★黑基空间★4n:z0|a"Zv|{[
★黑基空间★rYE:`i G;P
45.将a<<n理解为a*k, k=2n.★黑基空间★ o6}/?/@k
★黑基空间★*dY*z'H)QX^%u1K_
46.将a>>n理解为a/k, k=2n.★黑基空间★~E/U3EYN%][

6_$aGeVK047.每次只分析一个控制结构, 将它的内容看作是一个黑盒.★黑基空间★$v8N'^!~y?3t'_A:S
★黑基空间★o|&Fp&y_"|
48.将每个控制结构的控制表达式看作是它所包含代码的断言.★黑基空间★(oS:G a(W

.c*L N-L8f049.return, goto, break和continue语句, 还有异常, 都会影响结构化的执行流程. 由于这些语句一般都会终止或重新开始正在进行的循环, 因此要单独推理它们的行为.★黑基空间★ X9F[GmHVzMt
★黑基空间★yr8@6I&`f:W
50.用复杂循环的变式和不变式, 对循环进行推理.★黑基空间★.ad{0g9a1E0x
★黑基空间★IIUcdt f
51.使用保持含义不变的变换重新安排代码, 简化代码的推理工作.★黑基空间★(O'E#D4~1q/A K{
★黑基空间★ G#ZojL

x["`\` t0★黑基空间★9S?3w&VT|y4K
+++++++++++++++++++
,khz+D,|{6F0
_4u1i|s+|0第三章: 高级C数据类型★黑基空间★(^];tpN I A
★黑基空间★;Y d9j3m'o!]5l E
+++++++++++++++++++
c"\[jpYt0★黑基空间★6Cw!|IM`
★黑基空间★{](FwC

2n0H@2w%[6tgN$}| v052.了解特定语言构造所服务的功能之后, 就能够更好地理解使用它们的代码.★黑基空间★$@i5A0pG7\n*}8j

LZJ e,@]$h9YSa'g053.识别并归类使用指针的理由.★黑基空间★'h"A"Iz3zKG i
★黑基空间★2w`O"N%~e ~:p1x
54.在C程序中, 指针一般用来构造链式数据结构|动态分配的数据结构|实现引用调用|访问和迭代数据元素|传递数组参数|引用函数|作为其他值的别名|代表字符串|以及直接访问系统内存.
o4M:hu2]W GZ!x0
h2F m-he/Z4HN }7]a055.以引用传递的参数可以用来返回函数的结果, 或者避免参数复制带来的开销.
x/Pjks8K!mu0
_8qd+v fJ k K056.指向数组元素地址的指针, 可以访问位于特定索引位置的元素.
]c4jjC8DXq?'a0★黑基空间★J.~5r0sY
57.指向数组元素的指针和相应的数组索引, 作用在二者上的运算具有相同的语义.
0z/A N,iH0★黑基空间★LQQg G!~5}*_
58.使用全局或static局部变量的函数大多数情况都不可重入(reentrant).
i3^1Hd` x{S;G0
$j0cJKf/Cx059.字符指针不同于字符数组.
.b.m&I8w@.|? l.bK+[0
)gc3DG4_uD-m060.识别和归类应用结构或共用体的每种理由.★黑基空间★k!|G vo$}(K?

N:Z3nH@/Q-r061.C语言中的结构将多个数据元素集合在一起, 使得它们可以作为一个整体来使用, 用来从函数中返回多个数据元素|构造链式数据结构|映射数据在硬件设备|网络链接和存储介质上的组织方式|实现抽象数据类型|以及以面向对象的方式编程.★黑基空间★!m-sn|?.v3lB Q~
★黑基空间★*` |Xj9R6p5QR2~5o-}
62.共用体在C程序中主要用于优化存储空间的利用|实现多态|以及访问数据不同的内部表达方式.★黑基空间★(Qe&~2^B7G-k

hwPf"^Y(Y2E2E063.一个指针, 在初始化为指向N个元素的存储空间之后, 就可以作为N个元素的数组来使用.★黑基空间★k9B+I] YM8P

s#y%^ JUX!s?064.动态分配的内在块可以电焊工地释放, 或在程序结束时释放, 或由垃圾回收器来完成回收; 在栈上分配的内存块当分配它的函数退出后释放.
A%W7M yg0[8z.~X0
"|j!u*rQIo8i065.C程序使用typedef声明促进抽象, 并增强代码的易读性, 从而防范可移植性问题, 并模拟C++和Java的类声明行为.
7pp6I?k-Z0
Fb-PJ{6w!K,u066.可以将typedef声明理解成变量定义: 变量的名称就是类型的名称; 变量的类型就是与该名称对应的类型.
BQ#H/DKP1rX"SIGJU0+++++++++++++++★黑基空间★pDjh&] `$UoA
★黑基空间★MR1bv,oq+c&B'jKx
第四章: C数据结构★黑基空间★)]^VnHh

G!RwIj1qp0+++++++++++++++★黑基空间★It#q? l
★黑基空间★2g1{$p:F I#[k2rR

,e F.O2{:E0
3t3LZr/s*{(Dd5^067.根据底层的抽象数据类型理解显式的数据结构操作.
L4^'wE7JO;W0
1q S*Qonu%n9l'O'A(u068.C语言中, 一般使用内建的数组类型实现向量, 不再对底层实现进行抽象.★黑基空间★,b\[p#~Xr&o
★黑基空间★VJ|qO.~[ t~G
69.N个元素的数组可以被序列for (i=0; i<N; i++)完全处理; 所有其他变体都应该引起警惕.
*sSOo$g9i&e*JA0★黑基空间★/I\ b?ra:m{;{9|
70.表达式sizeof(x)总会得到用memset或memcpy处理数组x(不是指针)所需的正确字节数.★黑基空间★-IT8Z-g d;C rX8H*[
★黑基空间★*Xr+poyLb"m6n
71.区间一般用区间内的第一个元素和区间后的第一个元素来表示.★黑基空间★'EPt1m9P9ykur%E
★黑基空间★Ac4f]3O qS0M
72.不对称区间中元素的数目等于高位边界与低位边界的差.★黑基空间★;ozZtX1o8Zuj
★黑基空间★(cr/At"Txz
73.当不对称区间的高位边界等于低位边界时, 区间为空.★黑基空间★ QK%Q4p d)e#i(r
★黑基空间★#rh6LW9~+{H)g
74.不对称区间中的低位边界代表区间的第一个元素; 高位边界代表区间外的第一个元素.★黑基空间★7g,A$Ei;H[7d@
★黑基空间★8sJj? ew2pw
75.结构的数组常常表示由记录和字段组成的表.★黑基空间★;J)]7_#Db,`yBkP
★黑基空间★!V6S(p4o8D-V
76.指向结构的指针常常表示访问底层记录和字段的游标.
"jE;y;P |yqE9r0e(k0★黑基空间★C,R AohdH
77.动态分配的矩阵一般存储为指向数组列的指针或指向元素指针的指针; 这两种类型都可以按照二维数组进行访问.★黑基空间★7DG {*EE L9M+wz-C
★黑基空间★P:r]'_ o*S@
78.以数组形式存储的动态分配矩阵, 用自定义访问函数定位它们的元素.★黑基空间★"P#`B;A-JgF
★黑基空间★SdZ W4g
79.抽象数据类型为底层实现元素的使用(或误用)方式提供一种信心的量度.★黑基空间★oEqI|CU7Rb

F8Nr iZ/V ~y$e080.数组用从0开始的顺序整数为键, 组织查找表.
x.RvYa6b V$N0★黑基空间★d:O;aQ D9Y} V
81.数组经常用来对控制结构进行高效编码, 简化程序的逻辑.
1AE\FO+Y ES!w^6f\0
P u x"vU*@p082.通过在数组中每个位置存储一个数据元素和一个函数指针(指向处理数据元素的函数), 可以将代码与数据关联起来.★黑基空间★-Q.wB4A'h+I E \
★黑基空间★.c+j-m P"E'r"^
83.数组可以通过存储供程序内的抽象机(abstract machine)或虚拟机(virtual machine)使用的数据或代码, 控制程序的运作.
Ym.D)|B3R5eN*?0
4]&lW(YUj084.可以将表达式sizeof(x) / sizeof(x[0])理解为数组x中元素的个数.
T"bN&V1O$H-W0
5Luc0X` v3},Cl085.如果结构中含有指向结构自身|名为next的元素, 一般说来, 该结构定义的是单向链表的结点.★黑基空间★-t'[k+Xp/g
★黑基空间★{X7W.n)?S(e3O"s P
86.指向链表结点的持久性(如全局|静态或在堆上分配)指针常常表示链表的头部.
-r*y'RL#o;Cm0★黑基空间★'`._ D["J O
87.包含指向自身的next和prev指针的结构可能是双向链表的结点.
\)T*~Wk+zx;[3{0★黑基空间★9T;R9] W g$v Gj
88.理解复杂数据结构的指针操作可以将数据元素画为方框|指针画为箭头.
iK0T,E [ ]a0
l"U J2SM(A.Y4u!Z089.递归数据结构经常用递归算法来处理.
y+xXU:_5?j g4T0★黑基空间★ |$f'L9s(B&Hxo
90.重要的数据结构操作算法一般用函数参数或模板参数来参数化.★黑基空间★N PU3J'`y

)L$X n6C,K] c` P091.图的结点常常顺序地存储在数组中, 链接到链表中, 或通过图的边链接起来.★黑基空间★E"B)T\V9\DE
★黑基空间★#Hr(PMM P6z'J0\ Ot Z
92.图中的边一般不是隐式地通过指针, 就是显式地作为独立的结构来表示.
;T{c1w n/x0
] i&r_\ J5}093.图的边经常存储为动态分配的数组或链表, 在这两种情况下, 边都锚定在图的结点上.
j%f)\6on$Wwv ?0
,UU*VxWi1u094.在无向图中, 表达数据时应该将所有的结点看作是等同的, 类似地, 进行处理任务的代码也不应该基于它们的方向来区分边.
mux]s.q9]0★黑基空间★-n8JU4s$fb'P)M
95.在非连通图中, 执行遍历代码应该能够接通孤立的子图.★黑基空间★8pC!Do)e%?0ks

'F \6`/s#Jor8i*A S096.处理包含回路的图时, 遍历代码应该避免在处理图的回路进入循环.★黑基空间★%q R1D _/a7W2F

#z FQG_Y#H097.复杂的图结构中, 可能隐藏着其他类型的独立结构.
E3S:LXs/V K;f0
+S!q-h$KJ7a0
u)GB zX^``*h0
RmiAzQ Z0+++++++++++++++++
9k/cNDX.j.^FPc){0
-MN9~U HOU0第五章: 高级控制流程★黑基空间★cjeh;}dS#Vz
★黑基空间★+OEI1_ EygQy
+++++++++++++++++
#f S$@j2?}D6s0
/Z-}4M,Xl1z(a9xwn{0★黑基空间★M9Rk0hJe{"j6y)q
★黑基空间★P.EKw)P%ZLXyzQ
98.采用递归定义的算法和数据结构经常用递归的函数定义来实现.★黑基空间★5TnZ8];Z$o

g;T3dh,h6E i&N099.推理递归函数时, 要从基准落伍测试开始, 并认证每次递归调用如何逐渐接近非递归基准范例代码.
_h#T+F~S#g0★黑基空间★ o1]9h|-Q)g~'O
100.简单的语言常常使用一系列遵循该语言语法结构的函数进行语法分析.★黑基空间★P1BA`:r!_g2rj:f0M

#aO1Uu*f3R-j${0101.推理互递归函数时, 要基于底层概念的递归定义.★黑基空间★d j!A,zMQ ~2C!SO b

#Zd}9^EK3p0102.尾递归调用等同于一个回到函数开始处的循环.★黑基空间★.R;H:Uw)kz$mf

2v{mT`0103.将throws子句从方法的定义中移除, 然后运行Java编译器对类的源代码进行编译, 就可以容易地找到那些可能隐式地生成异常的方法.
(V0tnE|3FT0★黑基空间★Lkx,N-@5R7K
104.在多处理器计算机上运行的代码常常围绕进程或线程进行组织.★黑基空间★0PR9o.N)t9BT

PRQ @J0L.Q-Vh0105.工作群并行模型用于在多个处理器间分配工作, 或者创建一个任务池, 然后将大量需要处理标准化的工作进行分配.
Be7h3if:]G8e;Vl{j"L0★黑基空间★ ~0J/Y(VO)~
106.基于线程的管理者/工人并行模型一般将耗时的或阻塞的操作分配给工人子任务, 从而维护中心任务的响应性.
[N3b y(Mm0
zBzi?0l\0107.基于进程的管理者/工人并行模型一般用来重用现有的程序, 或用定义良好的接口组织和分离粗粒度的系统模块.★黑基空间★ YwXq-oB q#Ms\:K

JE(q{;c+k$~5lf"c0108.基于流水线的并行处理中, 每个任务都接收到一些输入, 对它们进行一些处理, 并将生成的输出传递给下一个任务, 进行不同的处理.
u o(?6{a%y-PE0
2s(^ y n0HpW0109.竞争条件很难捉摸, 相关的代码常常会将竞争条件扩散到多个函数或模块; 因而, 很难隔离由于竞争条件导致的问题.★黑基空间★t2~ ]o/c-u"{%~WV

%| pn9o/` h+fvx0110.对于出现在信号处理器中的数据结构操作代码和库调用要保持高度警惕.
lAht]Q^1Q8jPER0
%p] n3D5oj)`#IS0111.在阅读包含宏的代码时, 要注意, 宏既非函数, 也非语句.★黑基空间★ La ].K#S#O5iK
★黑基空间★&KIu U:~jw:lg#B
112.do…while(0)块中的宏等同于控制块中的语句.
P0iH"l z]S3b(F0★黑基空间★(?-Xa's/m`A N(]
113.宏可以访问在它的使用点可见的所有局部变量.★黑基空间★&S nU m9Tq
★黑基空间★.l x;OPI:xY;^(Q
114.宏调用可改变参数的值★黑基空间★]s9Tr E
★黑基空间★lQ:b;TG
115.基于宏的标记拼接能够创建新的标记符.
6g-Egr)a-K0+++++++++++++++++★黑基空间★O@y:H H(PU)k2D`
★黑基空间★Tu T1u zDy
第六章: 应对大型项目★黑基空间★_:Mh)tS

)aUT lN{;R ~0+++++++++++++++++
$Q a!R$zYHf)k0★黑基空间★opL5Lk5`#\
★黑基空间★(lR.N.c%s

.Z&{"K;B a%T'{ V_1Y@.W0116.我们可以通过浏览项目的源代码树—包含项目源代码的层次目录结构, 来分析一个项目的组织方式. 源码树常常能够反映出项目在构架和软件过程上的结构.
(}^9@(Ha#y-vQ9s,c+n)^0★黑基空间★O;n#` }u
117.应用程序的源代码树经常是该应用程序的部署结构的镜像.
t4X?t} Rb0★黑基空间★%yU jA"k
118.不要被庞大的源代码集合吓倒; 它们一般比小型的专门项目组织得更出色.★黑基空间★ bZVa5Z}+D!V k

VFn`W W/az)u&g0119.当您首次接触一个大型项目时, 要花一些时间来熟悉项目的目录树结构.
'Z!C.^4c:Sl*lf*@0★黑基空间★"J L^U.@2}W2v
120.项目的源代码远不只是编译后可以获得可执行程序的计算机语言指令; 一个项目的源码树一般还包括规格说明|最终用户和开发人员文档|测试脚本|多媒体资源|编译工具|例子|本地化文件|修订历史|安装过程和许可信息.★黑基空间★X)M%Ot{.`.^ X^"Qt"O

xPYiPOh XB0121.大型项目的编译过程一般声明性地借助依赖关系来说明. 依赖关系由工具程序, 如make及其派生程序, 转换成具体的编译行动.★黑基空间★,@ A ~'|0nd
★黑基空间★+^!D+^;\w8H?U*kP
122.大型项目中, 制作文件常常由配置步骤动态地生成; 在分析制作文件之前, 需要先执行项目特定的配置.★黑基空间★+U!?["F:H7\V;qm
★黑基空间★9P;^V1Y5x.F2S
123.检查大型编译过程的各个步骤时, 可以使用make程序的-n开关进行预演.
DsF_2y0
v,fb T8Y }-[|0124.修订控制系统提供从储存库中获取源代码最新版本的方式.
T MfM;hI"H0★黑基空间★!K9M'_Vb#X?
125.可以使用相关的命令, 显示可执行文件中的修订标识关键字, 从而将可执行文件与它的源代码匹配起来.
+uj+l0Or@$P [0
f)m7T%MC&U0126.使用修订日志中出现的bug跟踪系统内的编号, 可以在bug跟踪系统的数据库中找到有关的问题的说明.★黑基空间★D1Rq8YB6v+~'k3?
★黑基空间★*V iM$nr"b0Q h6d
127.可以使用修订控制系统的版本储存库, 找出特定的变更是如何实现的.★黑基空间★!\l0o%h3c

/a6W0_IZ!nz I0128.定制编译工具用在软件开发过程的许多方面, 包括配置|编译过程管理|代码的生成|测试和文档编制.★黑基空间★c0~,bU{

(LXi$T F0129.程序的调试输出可以帮助我们理解程序控制流程和数据元素的关键部分.★黑基空间★ v1j&[Y$e4b-{6XK P$n
★黑基空间★ Gg`}!dI2nB
130.跟踪语句所在的地点一般也是算法运行的重要部分.
?0[tR+A&[YL8L O0★黑基空间★d X]6C w u
131.可以用断言来检验算法运作的步骤|函数接收的参数|程序的控制流程|底层硬件的属性和测试用例的结果.
P-f6H%f3IU$u5J n7] ?p0
eL0rc2Z0132.可以使用对算法进行检验的断言来证实您对算法运作的理解, 或将它作为推理的起点.★黑基空间★Kc})j N0m&KxK
★黑基空间★I?ldrM
133.对函数参数和结果的断言经常记录了函数的前置条件和后置条件.★黑基空间★ X#n3MnY[ t

Ti{;HsrN j/R1Z1^0134.我们可以将测试整个函数的断言作为每个给定函数的规格说明.★黑基空间★.vtOx}$c;jF
★黑基空间★7E5HaM6w'X%v
135.测试用例可以部分地代替函数规格说明.
r[F2mQ(~0★黑基空间★6s/?~h J!M:J
136.可以使用测试用例的输入数据对源代码序列进行预演.
'{F p{*wd@0★黑基空间★A_-O9~"Wi3rDa

#Ur&`z2q_I0
f HKe3hA'Q4H0+++++++++++++++++++
[W,e i[/xZ#z0
\+R$y u Ee-Y0第七章: 编码规范和约定★黑基空间★P_H9N)M3` E2o

$R7s#F@#{T9n0+++++++++++++++++++★黑基空间★!TL {-Y}bi
★黑基空间★4|8z9c a"h `.Em

&]sr!rYsn5J0
H5`+g@iQ-Ad0137.了解了给定代码库所遵循的文件组织方式后, 就能更有效率地浏览它的源代码.
}f`o\iT0
$^8yf Z&Z i#CE0138.阅读代码时, 首先要确保您的编辑器或优美打印程序的tab设置, 与代码遵循的风格规范一致.
5Z]h!Z0V2m-Z)f0
Z.dg!d` ~9Y+N0139.可以使用代码块的缩进, 快速地掌握代码的总体结构.
y(Dh-P9{'] q0★黑基空间★8x$x)~dB(U4[^
140.对编排不一致的代码, 应该立即给予足够的警惕.
_y4s R4YkEE}2i0
J7fuJ6Na0141.分析代码时, 对标记为XXX, FIXME和TODO的代码序列要格外注意: 错误可能就潜伏在其中.★黑基空间★5O+r| E MK]

xyUC$siq0b0142.常量使用大写字母命名, 单词用下划线分隔.★黑基空间★ ^-x%S:o:|u

2G:I\2eW0143.在遵循Java编码规范的程序中, 包名(package name)总是从一个顶级的域名开始(例如, org, com), 类名和接口名由大写字母开始, 方法和变量名由小写字母开始.
htw o_ p'|n;g0
5{h~?IG0144.用户界面控件名称之前的匈牙利记法的前缀类型标记可以帮助我们确定它的作用.
E3^s`0x0
'c L&bEI%S a3rpb0145.不同的编程规范对可移植构造的构成有不同的主张.★黑基空间★ WV6Sa/W JJ
★黑基空间★K~XM]%j#T4N.B
146.在审查代码的可移植性, 或以某种给定的编码规范作为指南时, 要注意了解规范对可移植性需求的界定与限制.
4s&_V/z H%Yx0★黑基空间★S[h },A4\X
147.如果GUI功能都使用相应的编程结构来实现, 则通过代码审查可以轻易地验证给定用户界面的规格说明是否被正确地采用.
*mE0L;u3R3cw0
2h@`U2]%[$I0148.了解项目编译过程的组织方式与自动化方式之后, 我们就能够快速地阅读与理解对应的编译规则.
8Hd.[6PaV ^V*Aq0★黑基空间★ |'QN&nJX
149.当检查系统的发布过程时, 常常可以将相应发行格式的需求作为基准.★黑基空间★}G?1h;S${Qe
++++++++++++
.]-{m C)P h0★黑基空间★S7`BO+A\}6Qq9_s
第八章: 文档★黑基空间★fu'yiP

V.z\%gq`0++++++++++++★黑基空间★uz$T\w
★黑基空间★#yV^G/K
★黑基空间★K)tyx)j!d+D o7M:]

c3uGG!]hV*a]'g0150.阅读代码时, 应该尽可能地利用任何能够得到的文档.★黑基空间★NRlLwRM
★黑基空间★e8snE&^R:g"z
151.阅读一小时代码所得到的信息只不过相当于阅读一分钟文档.
5k{y2LC?0★黑基空间★}{&|r9H,CLt Z
152.使用系统的规格说明文档, 了解所阅读代码的运行环境.
4I%I\3R1p)c;U'M^0
e7h+UjG*b^0153.软件需求规格说明是阅读和评估代码的基准.★黑基空间★9x#_{vu_6[z
★黑基空间★7n sflE;F4@4V+p
154.可以将系统的设计规格说明作为认知代码结构的路线图, 阅读具体代码的指引.
:y;cZvEM'zO0★黑基空间★"rmW1qI*a
155.测试规格说明文档为我们提供可以用来对代码进行预演的数据.
#`GO?-tN(O X0
5Wt/P1qZ e g#K,L0156.在接触一个未知系统时, 功能性的描述和用户指南可以提供重要的背景信息,从而更好地理解阅读的代码所处的上下文.★黑基空间★!S#a7E%\]

mw?$ZuAz/GCM0157.从用户参考手册中, 我们可以快速地获取, 应用程序在外观与逻辑上的背景知识, 从管理员手册中可以得知代码的接口|文件格式和错误消息的详细信息.
%BC~+KI0★黑基空间★$y*D v5S(K
158.利用文档可以快捷地获取系统的概况, 了解提供特定特性的代码.★黑基空间★Er gVhU&v$d

)~,[h7^gZ0159.文档经常能够反映和提示出系统的底层结构.
?'S+i6y;U@|0★黑基空间★.x3W` \5i P+]-Z#i],}n
160.文档有助于理解复杂的算法和数据结构.
PA.Vn%Z_0N9o0
AL%v dJ a_GP#Z0161.算法的文字描述能够使不透明(晦涩, 难以理解)的代码变得可以理解.★黑基空间★cTJ.fu(E

'g |"Z h?vf'H0162.文档常常能够阐明源代码中标识符的含义.★黑基空间★@RrN!SbN:~
★黑基空间★ l*[V H%tXFJ9f.DHHv
163.文档能够提供非功能性需求背后的理论基础.★黑基空间★%zvA-am7Qb&j"?
★黑基空间★6i%\`$Q*U%N7jV
164.文档还会说明内部编程接口.
${n y(X T0★黑基空间★r5[$G+U i:l-gz2e`
165.由于文档很少像实际的程序代码那样进行测试, 并受人关注, 所以它常常可能存在错误|不完整或过时.
;NK2X*E6c$SY0★黑基空间★M\R%n(r}},Z+T
166.文档也提供测试用例, 以及实际应用的例子.
0EM7\8C}0★黑基空间★W.d)}@.E.]%P&[
167.文档常常还会包括已知的实现问题或bug.
z2}cuLM"C cs.g0
th ^#F0X[R1{0168.环境中已知的缺点一般都会记录在源代码中.
f-kp,[)?+tdoQ%~0
H1C'J/D$p(Q`-}Z0169.文档的变更能够标出那些故障点.
l4St1[&V0
yo_J z{'z)}0170.对同一段源代码重复或互相冲突的更改, 常常表示存在根本性的设计缺陷, 从而使得维护人员需要用一系列的修补程序来修复.
,\9~1p$^aSdA0★黑基空间★#`PH/U:b~!N
171.相似的修复应用到源代码的不同部分, 常常表示一种易犯的错误或疏忽, 它们同样可能会在其他地方存在.
E{H%Xy,IX/j3H^0★黑基空间★t!~Eh#]1_$hKY1]1C
172.文档常常会提供不恰当的信息, 误导我们对源代码的理解.★黑基空间★3R~9J'[iZ#S o!F

ek)a#Q.`:S6O^ ]0173.要警惕那些未归档的特性: 将每个实例归类为合理|疏忽或有害, 相应地决定是否应该修复代码或文档.
(F J Y0y&S0
F^#Y;M @5V!^kzs0174.有时, 文档在描述系统时, 并非按照已完成的实现, 而是系统应该的样子或将来的实现.★黑基空间★9j7Jc3`6BN5B

,s*i ?nb,OHh0175.在源代码文档中, 单词gork的意思一般是指”理解”.★黑基空间★,x!@5r:zsOPZ
★黑基空间★)l0I7u/i H2hY}f
176.如果未知的或特殊用法的单词阻碍了对代码的理解, 可以试着在文档的术语表(如果存在的话)|New Hacker’s Dictionary[Ray96]|或在Web搜索引擎中查找它们.★黑基空间★1UkU'f I*pOJX4`q

`8H+I5Db({0177.总是要以批判的态度来看待文档, 注意非传统的来源, 比如注释|标准|出版物|测试用例|邮件列表|新闻组|修订日志|问题跟踪数据库|营销材料|源代码本身.
0w0VedOHm0
\#j8~y-DA El0178.总是要以批判的态度来看待文档; 由于文档永远不会执行, 对文档的测试和正式复查也很少达到对代码的同样水平, 所以文档常常会误导读者, 或者完全错误.★黑基空间★.oz:b-D$o,J0t

X b^:c Fc&d0179.对于那些有缺陷的代码, 我们可以从中推断出它的真实意图.★黑基空间★q pvmetU(m$r]
★黑基空间★#W2x PO%iI#m
180.在阅读大型系统的文档时, 首先要熟悉文档的总体结构和约定.★黑基空间★HL \NbzM1\gl
★黑基空间★4Dw0{\0X"p5G+za2_C
181.在对付体积庞大的文档时, 可以使用工具, 或将文本输出到高品质输出设备上, 比如激光打印机, 来提高阅读的效率.★黑基空间★D q+l2s7c*gaJ*Ei}I mB
★黑基空间★Rp*_w-t[)`4ok q
★黑基空间★(h4n a.n"|Jl
★黑基空间★(jLp5U1v7h%f$e
++++++++++++++
-C2HX s O&`,h+jP0
{(mbE4k W%C0第九章: 系统构架★黑基空间★(Vv }0d$@ vX

nZ*dQH3y F0++++++++++++++
[LB[GC0★黑基空间★oiu)`'f2W"d&a
★黑基空间★?,SP!L;xK%nN
★黑基空间★@5a]W4qJn
182.一个系统可以(在重大的系统中也确实如此)同时出多种不同的构架类型. 以不同的方式检查同一系统|分析系统的不同部分|或使用不同级别的分解, 都有可能发现不同的构架类型.★黑基空间★.\$WR%V3R
★黑基空间★n.|0Xmz
183.协同式的应用程序, 或者需要协同访问共享信息或资源的半自治进程, 一般会采用集中式储存库构架.
L.L#?9_P m0
9Gg6XZ P ~z,P0184.黑板系统使用集中式的储存库, 存储非结构化的键/值对, 作为大量不同代码元件之间的通信集线器.★黑基空间★U8[8A f\d8TX
★黑基空间★9Z/|Tt/};~\"LUx
185.当处理过程可以建模|设计和实现成一系列的数据变换时, 常常会使用数据流(或管道—过滤器)构架.
f ?6o2MVN(k-n A0
&b2nY9b-S0186.在批量进行自动数据处理的环境中, 经常会采用数据流构架, 在对数据工具提供大量支持的平台上尤其如此.
km6@i{lJ ?0
SG PF*I N(C Q\(C$I8MK/^ N0187.数据流构架的一个明显征兆是: 程序中使用临时文件或流水线(pipeline)在不同进程间进行通信.★黑基空间★(sH$Ub%A|7v

4q6g _%s/nY3b0188.使用图示来建模面向对象构架中类的关系.
9g"_9G*MV0??*P#`A0
i4D3b:Yqh"k-C0189.可以将源代码输入到建模工具中, 逆向推导出系统的构架.
4~okn.?.r*[0
|dg%C9t0190.拥有大量同级子系统的系统, 常常按照分层构架进行组织.★黑基空间★:[S TOk4Zj0iG+V

6uC6jQg(K0191.分层构架一般通过堆叠拥有标准化接口的软件组件来实现.
#F oId/Y-d0
B h!R3mMct\0192.系统中每个层可以将下面的层看作抽象实体, 并且(只要该层满足它的需求说明)不关心上面的层如何使用它.★黑基空间★ a.vr5G1]-W5C4q;Lz^7J

vx.kR7y0193.层的接口既可以是支持特定概念的互补函数族, 也可以是一系列支持同一抽象接口不同底层实现的可互换函数.★黑基空间★5wi1X cv:y:nY5RB
★黑基空间★,Rf+x'MYPM
194.用C语言实现的系统, 常常用函数指针的数组, 表达层接口的多路复用操作.
8A `^4Lk q Y?0★黑基空间★/c ZQnDe
195.用面向对象的语言实现的系统, 使用虚方法调用直接表达对层接口的多嘴复用操作.
%e,_,j f}1_k$u~ N0★黑基空间★.w~}@X?
196.系统可以使用不同的|独特的层次分解模型跨各种坐标轴进行组织.
F4tg[H0★黑基空间★)D @1X7PE G
197.使用程序切片技术, 可以将程序中的数据和控制之间依赖关系集中到一起.★黑基空间★?%b7p9r7T7NDRf

"Mubbo'ZVg0198.在并发系统中, 一个单独的系统组件起到集中式管理器的作用, 负责启动|停止和协调其他系统进程和任务的执行.★黑基空间★#dJo^9b?D:`

g6^*F.OX0199.许多现实的系统都会博采众家之长. 当处理此类系统时, 不要徒劳地寻找无所不包的构架图; 应该将不同构架风格作为独立但相关的实体来进行定位|识别并了解.★黑基空间★(CZ;^LkR-D B
★黑基空间★'qN/ZT4a5n7loe
200.状态变迁图常常有助于理清状态机的动作.★黑基空间★"v`(W:gy]!T~ h@"W

5A*Jh/f_0201.在处理大量的代码时, 了解将代码分解成单独单元的机制极为重要.
;|`9bUH6tobn0
(W.k!c{2LQ%fW5h1o'pD0202.大多数情况下, 模块的物理边界是单个文件|组织到一个目录中的多个文件或拥有统一前缀的文件的集合.★黑基空间★1Xw*k'E"Xl t v

&Ix"| rCn8y0203.C中的模块, 由提供模块公开接口的头文件和提供对应实现的源文件组成.
*lal_{(hBj0★黑基空间★B H:eJ^n
204.对象的构造函数经常用来分配与对象相关的资源, 并初始化对象的状态. 函数一般用来释放对象在生命期中占用的资源.★黑基空间★-e4o [2[+^}Di

b.vsz3\7H ~ Rr0205.对象方法经常使用类字段来存储控制所有方法运作的数据(比如查找表或字典)或维护类运作的状态信息(例如, 赋给每个对象一个标识符的计数器).★黑基空间★7Rar.u2N/c8cR z T
★黑基空间★ _)~([ jpS d5uwm
206.在设计良好的类中, 所有的字段都应在声明为private, 并用公开的访问方法提供对它们的访问.★黑基空间★4uFh/dV'gJ

t F8K4EL1PX7Y7|0207.在遇到friend声明时, 要停下来分析一下, 看看绕过类封装在设计上的理由.
\;_-{ tG\0
4a%l'n9guJB|K3h0208.可以有节制地用运算符增强特定类的可用性, 但用运算符重载, 将类实现为拥有内建算术类型相关的全部功能的类实体, 是不恰当的.★黑基空间★Z)n.N'v2@7gyy

2zY2fA wJ1qn0209.泛型实现不是在编译期间通过宏替换或语言所支持的功能(比如C++模板和Ada的泛型包)来实现, 就是在运行期间通过使用数据元素的指针和函数的指针|或对象的多态性实现.
2e7cb{"Mt1i-Y.J0★黑基空间★U R1\6}~gm&[k
210.抽象数据类型经常用来封装常用的数据组织方案(比如树|列表或栈), 或者对用户隐藏数据类型的实现细节.★黑基空间★"b!@h"Lm;l-E^
★黑基空间★X;L ~+?2^](}X
211.使用库的目的多种多样: 重用源代码或目标代码, 组织模块集合, 组织和优化编译过程, 或是用来实现应用程序各种特性的按需载入.★黑基空间★5Y/e K y8I%dS"w t

,E:s}r3Osv0212.大型的|分布式的系统经常实现为许多互相协作的进程.
;X `]rCr.s0
[M2UFP3eT:So0213.对于基于文本的数据储存库, 可以通过浏览存储在其中的数据, 破译出它的结构.
#H+qJg9f8C0
^:T2bCP4rx%L8B0214.可以通过查询数据字典中的表, 或使用数据库专有的SQL命令, 比如show table, 来分析关系型数据库的模式.
IQ9V i4p w dk(?0
0aVnS|A0Nu0215.识别出重用的构架元素后, 可以查找其最初的描述, 了解正确地使用这种构架的方式, 以及可能出现的误用.★黑基空间★&x0Fx ZY0Eb1oe3ui/@

$R C(Qw+|)l0216.要详细分析建立在某种框架之上的应用程序, 行动的最佳路线就是从研究框架自身开始.★黑基空间★vt0`d$z+e

$Vv8HPjyn\&R0217.在阅读向导生成的代码时, 不要期望太高, 否则您会感到失望.★黑基空间★x~o#D3yV2s3B`%m$U
★黑基空间★:E.]xT"P
218.学习几个基本的设计模式之后, 您会发现, 您查看代码构架的方式会发生改变: 您的视野和词汇将会扩展到能够识别和描述许多通用的形式.
T+Vuy8?z4}"^'V)B0
8I0R4UrH;]3Y G:hh0219.频繁使用的一些模式, 但并不显式地指出它们的名称, 这是由于构架性设计的重用经常先于模式的形成.
;f;Q _-Th m#w0★黑基空间★.ZK-wzuf&ZD^
220.请试着按照底层模式来理解构架, 即使代码中并没有明确地提及模式.★黑基空间★*boT0|W5RD9a J2k$D$L
★黑基空间★+[$Aw(VI[ [8V-SM
221.大多数解释器都遵循类似的处理构架, 围绕一个状态机进行构建, 状态机的操作依赖于解释器的当前状态|程序指令和程序状态.
zr1t-b.Th1S0★黑基空间★"VF3wY`IR
222.多数情况下, 参考构架只是为应用程序域指定一种概念性的结构, 具体的实现并非必须遵照这种结构.★黑基空间★'X?'lS!z
+++++++++++++++++
@1bNA]c'o0
/X/N*X7@7D-Wc3x0第十章: 代码阅读工具★黑基空间★Sx*t'z&C3{

Yg1|tS*|{*p"|0+++++++++++++++++★黑基空间★C0CG\-B
★黑基空间★-t5ph8i*n%s,D(|o

:x"c%U x.]Y'M0★黑基空间★jO*`#q6z!y
223.词汇工具可以高效地在一个大代码文件中或者跨多个文件查找某种模式.★黑基空间★2O1I"\#U8Kfp

C:w/y6` z l O+e0224.使用程序编辑器和正则表达式查找命令, 浏览庞大的源代码文件.
hn%N(Et:R0K$tW0
AU+m,^"x7E m0225.以只读方式浏览源代码文件.★黑基空间★ s ^;wH#e9I$I)k

#}pD A$MY YB,J0226.使用正则表达式 ^function name 可以找出函数的定义.
*S2W,_ R hOzshHz'P!O0
![ti$~C V#T2l$v0227.使用正则表达式的字符类, 可以查找名称遵循特定模式的变量.★黑基空间★7e$]Ndp(W1}0bJ

Ge#^t'o'{ KJ?0228.使用正则表达式的否定字符类, 可以避免非积极匹配.★黑基空间★0v&U+];z-t5k]

#O3O8E^gI0229.使用正则表达式 symbol-1. *symbol-2, 可以查找出现在同一行的符号.
0N'OkG:Z#J?0
Bi;j+e%J"jl)A5T^0230.使用编辑器的 tags 功能, 可以快速地找出实体的定义.
,[;t#j#X@9E%L7I$e0
%F V@Sc8H0231.可以用特定的 tag 创建工具, 增加编辑器的浏览功能.★黑基空间★3X6^W;e1C6O Q

L~O-u$VE7R0232.使用编辑器的大纲视图, 可以获得源代码结构的鸟瞰图.★黑基空间★+\!jq Ld*y
★黑基空间★l7QubE
233.使用您的编辑器来检测源代码中圆括号|方括号和花括号的匹配.
G-TFtm-]0
7r)T@\)LK0234.使用 grep 跨多个文件查找代码模式.
F0k(]-a `\,Gw#n!p.F$z0★黑基空间★ k i-i B&`W!|6n
235.使用 grep 定位符号的声明|定义和应用.★黑基空间★%O gz0I3C1E
★黑基空间★x[(R^W_)]:l
236.当您不能精确地表述要查找的内容时, 请使用关键单词的词干对程序的源代码进行查找.★黑基空间★@$q O C?(om OLT
★黑基空间★+Tn2[ E#ayyi
237.用 grep 过滤其他工具生成的输出, 分离出您要查找的项.
(e$Rgn|nOt-E0★黑基空间★T2X.TR;r6j {
238.将 grep 的输出输送到其他工具, 使复杂处理任务自动化.
;bur*}$E9k'}{s0★黑基空间★(P` hDcYg
239.通过对 grep 的输出进行流编辑, 重用代码查找的结果.★黑基空间★/WE u rPpu!T

Gg fA8[F#^0240.通过选取与噪音模式不匹配的输出行(grep-v), 过滤虚假的 grep 输出.
&F jE+z3A6n!n#MyvV2L3C0★黑基空间★W u tA)Ty
241.使用 fgrep 在源代码中查找字符串列表.★黑基空间★ a%V.Y%h"s-l(H^!X
★黑基空间★)u,i^0\:[`-c
242.查找注释, 或标识符大小写不敏感的语言编写的代码时, 要使用大小写不敏感的模式匹配(grep -i).★黑基空间★O8y+H&Q9U:IZ'V-U
★黑基空间★3J4k)v4|3Z;L ?l
243.使用 grep –n 命令行开关, 可以创建与给定正则表达式匹配的文件和行号的检查表.★黑基空间★8U W`g/n @{.poQ

c$gvaykaRc0244.可以使用 diff 比较文件或程序不同版本之间的差别.★黑基空间★0z'iY }5^]7LE Z

)x#QP W"awM*^;RWL6g0245.在运行 diff 命令时, 可以使用 diff –b, 使文件比较算法忽略结尾的空格, 用 –w 忽略所有空白区域的差异, 用 –i 使文件比较对大小写不敏感.★黑基空间★$wYrfv6\-q:[i&g5}

])\I*lLP.Drm0246.不要对创建自己的代码阅读工具心存畏惧.★黑基空间★uXt0V@J[P
★黑基空间★7q w7I6|:} I?
247.在构建自己的代码阅读工具时: 要充分利用现代快速原型语言所提供的能力; 从简单开始, 根据需要逐渐改进; 使用利用代码词汇结构的各种试探法; 要允许一些输出噪音或寂静(无关输出或缺失输出); 使用其他工具对输入进行预处理, 或者对输出进行后期处理.★黑基空间★9U~5d"k"_caU c

c,FCT fm r$P fB0248.要使编译器成为您的: 指定恰当级别的编译器警告, 并小心地评估生成的结果.★黑基空间★4X,^x ?/m2fH

~ cE8_)`X0249.使用C预处理器理清那些滥用预处理器特性的程序.
c2fg IR$Vf[;OO0
6pcAB.Y0a~&l0250.要彻底地了解编译器如何处理特定的代码块, 需要查看生成的符号(汇编)代码.★黑基空间★}#~!xTjr W%n
★黑基空间★VD Bfd$B"s
251.通过分析相应目标文件中的符号, 可以清晰地了解源文件的输入和输出.★黑基空间★9}4K5Y Ay{3WD

*wl4qj&u!KO0252.使用源代码浏览器浏览大型的代码集合以及对象类型.
er)F$Hn0★黑基空间★M U:{ Q[!Q_6]
253.要抵制住按照您的编码规范对外部代码进行美化的诱惑; 不必要的编排更改会创建不同的代码, 并妨碍工作的组织.
zQ;q([h3Q'B$er(n0
8n*Nn2`'M+oX0254.优美打印程序和编辑器语法着色可以使得程序的源代码为易读.★黑基空间★6e8r0_d2k4|$R|
★黑基空间★5?\W8C L,j c xT
255.cdecl 程序可以将难以理解的C和C++类型声明转换成纯英语(反之亦然).
j@"l!vTY7P9T0
"@K,Q:{R n!`&G0256.实际运行程序, 往往可以更深刻地理解程序的动作.★黑基空间★g1Y$nB0E^K/H(g
★黑基空间★e9N_'_(x[
257.系统调用|事件和数据包跟踪程序可以增进对程序动作的理解.
b2u5a#k$B0
__3i$C.oM0258.执行剖析器可以找出需要着重优化的代码, 验证输入数据的覆盖性, 以及分析算法的动作.
"g0v[&?:W0
R!Z-bzw6l Xs6p0259.通过检查从未执行的代码行, 可以找出测试覆盖的弱点, 并据此修正测试数据.★黑基空间★-\XUX2F[
★黑基空间★+l j5Dm t*j
260.要探究程序动态动作时的每个细节, 需要在调试器中运作它.
#Z+Xd H`4R"n0★黑基空间★p9F2@}:A `
261.将您觉得难以理解的代码打印到纸上.
Q@K8kDK~h'v0
c/i#x/P@{p7Bmz0262.可以绘制图示来描绘代码的动作.★黑基空间★!Y+{[jG!?.E B
★黑基空间★P!wh uwmi
263.可以试着向别人介绍您在阅读的代码, 这样做一般会增进您对代码的理解.
3wt9y:[A5lN0★黑基空间★7VN6E#C!w*_ X.`j
264.理解复杂的算法或巧妙的数据结构, 要选择一个安静的环境, 然后聚精会神地考虑, 不要借助于任何计算机化或自动化的帮助.
;Bz5N y U(Y0★黑基空间★+o7X$S^*s7J+Q+K
★黑基空间★ nP!P8~~.h
★黑基空间★RRbZy2dsFD
+++++++++++++++++++++★黑基空间★:D cy"x Q T|Y

#is%s8`)B0第十一章: 一个完整的例子★黑基空间★S"EvY9b]!y1`-h

'}Q9X{%](w:K0+++++++++++++++++++++★黑基空间★B {WLw"ziV
★黑基空间★:oAV$t"_

Zc y4jd@;w jZE0Y[0★黑基空间★!sYc!~b
265.模仿软件的功能时, 要依照相似实体的线路(类|函数|模块). 在相似的现有实体中, 为简化对源代码库的文本查找, 应选取比较罕见的名称.★黑基空间★1~b{,}] m~ h,i#M1f
★黑基空间★HjBI Wx3e ],L
266.自动生成的文件常常会在文件的开关有一段注释, 说明这种情况.★黑基空间★[~'`7b)U["Ne

2V n1Z M*a'pKq4}"h5`$JH0267.如果试图精确地分析代码, 一般会陷入数量众多的类|文件和模块中, 这些内容会很快将我们淹没; 因此, 我们必须将需要理解的代码限定在绝对必需的范围之内.
S)CS2\(j^0★黑基空间★A0P`._;?h/e c
268.采用一种广度优先查找策略, 从多方攻克代码阅读中存在的问题, 进到找出克服它们的方法为止.★黑基空间★@b5Kn"O6F$R

TAG: 有用才行

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-10-26  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 280774
  • 日志数: 128
  • 图片数: 27
  • 建立时间: 2006-08-26
  • 更新时间: 2007-04-28

RSS订阅

Open Toolbar