这本书里包含了很多的看似粗浅朴素的道理,实则是若干经验的心血总结。
比如谁都知道不要对自己家的破窗户置之不理,可实际中听到太多的妥协:这个代码已经这样了,只能继续在上面贴上丑陋的workaround,这其实是一种对责任的推卸和对未来的不负责,当然现实不是完美的,有时救火队员也不得不放下破窗户而迁就其他,但最为一个pragmatic程序员,保持追求完美的心态还是很有必要的,正因为这个心态,我们才会去追求代码的优美、设计/实现的正交、DRY(Dont' Repeat Yourself)原则...
我们看到太多重复造轮子的故事。
正如书中提到“鞋匠的孩子没鞋穿”,作为一个pragmatic程序员,合理地使用工具/库/以及自己积累的开发的轮子,会让自己的productivity不断提升。这让我想起公司里一个让人崇拜的“牛”,产品一直想把进程内cache做成多进程共享,正在大家还在讨论该怎么做的时候,“牛”已经用短短几天时间完成了,众人再次崇拜一把,原来“牛”是备有很多现成代码的,完成这个功能只是把之前积累的封装良好的模块重用就可以了。
记得四年前刚开始工作时从公司拿到的第一本书,就是这本《程序员修炼之道》(英文版),作为新入职员工study group的学习材料,当时在senior engineer带领下和其他同事一起学习了这本书。虽然之前就听说这是一本好书,但当时看的时候只是觉得,讲的都有道理,但这些是很自然的阿,干吗花这么大的篇幅说来说去?所以只是囫囵吞枣地翻过也就扔在一边了。
之后也看过很多类似的书籍,《修炼之道》也一直是公司新人的必备学习材料,而我却一直再没重拾这本书仔细通读一遍,直到最近周筠老师发给我中文电子版,我才又从书架上翻出当年的英文版,对照着中文电子版仔细通读了一遍。
此次重读,感受颇多,也颇能理解为何公司一直选用此书作为新人教材。
另外一个书中推崇的方法:曳光弹,自己之前用prototype,但一直犹豫于代码是否需要重用,原则上prototype的代码是应该抛弃型的,但在有时候前期做的一些工作其实是为了确定方案、构建框架,而这些其实是会作为后起工作的基础的。事实上在项目先期是值得仔细考虑究竟该采用prototype还是曳光弹,它们的适用场景会有所不同(对于产品开发,曳光弹的应用场景可能相对会更多一些)
当然,至于书中提到的对知识资产的管理(知识投资)、沟通和交流的重要性等等,我想这就不单单对于程序员适用了,任何一个人要想有所作为的,这些方面的重要性都毋庸多说了。而对于自动化和文本处理等方面的经验,也是在很多书中都提到的经验之谈(Unix编程艺术、卓有成效的程序员...)
最后,说一下这本书的翻译,译者马维达,最早是在学校时读过他翻译的ACE文档及相关资料,收益颇多,ACE可谓网络编程技术的集大成者,而这本《修炼之道》则可谓编程的集大成者,从项目管理、软件架构和设计、代码编写和测试,各方面在此书中都有精到的阐述。此书的翻译质量应该说很是准确,基本很实在真实地表达了原书的意思,但正因直译,可能有些语句理解上会有一点难度(比如P146, "只要对于那些被耦合在一起的模块而言,这是众所周知的和可以接受的,你的设计就没有问题。"),但细读这本书,这些有所晦涩的内容还是能理解的,当然一点建议是作者可以适当加些“译注”,这样会让理解更容易和顺畅(比如书中直接用古鲁来翻译Guru,如果能加些解释可能会更好,又比如Law of Demeter,原书没有解释得太清楚,如果能多加些解释可能会更便于理解)
感谢周筠老师让我有机会重温这本优秀的书籍,为了完成作业,也为了让自己认识提升。
其他的一些感悟:
正交性(高内敛,最后达到两个模块之间互补影响)
曳光弹或是原型(轻量级引导程序,直达目标,方便调整)
断言式编程,异常使用(暴露程序的问题,不要隐藏他)
解耦与墨忒尔法则(低耦合,减少依赖)
算法数率与重构(更优质的代码)
无处不在的自动化(减少重复代码,和无意义的代码,不仅会让编程更有趣,而且会减少错误)
这些算是比较高级的技巧了。对于初学变成的人其实不太友好。过多的限定总是会让新手止步不前。
不过《程序员修炼之道》还提到了几条对于任何阶段的程序员都应该遵循的法则
1.你的知识资产
你应该一直投资知识资产,这是你成长的根本
包括但不限与,定期读书,定期学习新的语言,尝试新的工具
2.破窗原则
任何时候你都应该使用你当时最高水品的技术去完成一个项目,如果你发现又不好的设计或实现应该修正它。就算时间不够你至少应该打上一个补丁,以警告和提示开发人员这个地方需要修补。
3.打上你的标签
不再怀有侥幸,在你负责和修改的地方打上标签。迫使自己编写更高水平的代码。
我的源码让猫吃了
对于工作勇于负责,正确评估自己的负责范围,别找一些蹩脚的借口。
Provide Options,Don't Make Lame Excuses.选择各种选择,不要找蹩脚的接口。
软件的熵
软件无序增长被称为“软件腐烂”(Software rot)
对于软件中错误应该及时修复,千万别把软件弄“脏”了,否则软件将迅速恶化。
Don't Live with Broken Windows.不要容忍破窗户
石头汤与煮青蛙
让他们瞥见未来,你就能让他们聚在你周围。
Be a Catalyst for Change.做变化催化剂
很多软件灾难都是从小事开始,以至于积少成多,影响了团队。
Remember the Big Picture.记住大图景
足够好的软件
所有系统都必须满足其用户的需求,才能获得成功。让用户参与到你的工作吧,让他们去权衡。但是过度修饰和过于求精,而损坏完好的程序就有点画蛇添足了。
Make Quality a Requirements lssue.使质量成为需求问题
你的知识资产(Knowledge Portfolios)
知识是有时效的资产(expiring asset)
经营知识资产:定期投资、多元化、管理风险、低买高卖、重新评估和平衡
Invest Regularly in Your Knowledge Portfolios.定期为你的知识资产投资
每年至少学一种新语言,每个月至少阅读一本书,阅读非技术书籍,上课,参加本地用户组织,试验不同的环境,跟上潮流,上网。
学习时,也要进行批判的思考。咕噜们和互联网不一定时最权威的。
Critically Analyze What You Read and Hear.批判分析你读到的和听到的。
交流(Communcation)
在说话前要做到以下准备:
1.知道要说什么
2.知道要对谁说
3.选择什么时候说
4.说话的风格(简报;论述;幽默;严肃)要让文档看起来漂亮说话是一个互动行为(Not noly Speaker but alse Listener)礼貌回复一切别人向你提出的问题。
It's Both What You Say and the Way You Say it.你说什么和你怎么做一样重要
重复的危害
DRY原则(Don't reapeat youorself):系统中的每一项知识都必须具有单一,无歧义,权威的表示
四种重复:
加强的重复(impsed duplication):环境似乎要求重复(信息多种表示,注释,文档与代码,语言问题)
无意的重复(inadvertent duplication):没有意识到信息的重复
无耐性的重复(impatient duplication):开发者偷懒,似乎那样更容易
开发者之间的重复(interdeveloper duplication):大家重复同样的东西
复用是解决重复一个最好的方法
Make it easy to Rease.让复用变得容易
正交性
如果两个或多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的。
Eliminate Effect Between Unrelated Things.消除无关事物之间的影响。
自足(self-contained)的组件:独立,具有单一,良好定义的目的。
正交的好处:提高生产效率,降低风险。
经常问问自己:如果我显著地改变某个特定功能背后地需求,有多少模块会受影响。
编码:让代码保持解耦,避免使用全局数据;避免编写相似地函数
可撤销性
如果某个想法是你的唯一的想法,在没有什么比这更危险的事情了。
一个灵活的框架随时适应变化的需求。
“薛定谔的猫”——任何结果都是可能的。
需求随时在变,而软件就变不起了,如果连软件框架都变来变去,那软件一定会失败。
曳光弹
做软件的时候可以时不时地抛出一个曳光弹,看看打中目标没有。
Use Tracer Bullets to find the Target.用曳光弹找到目标。
曳光弹代码并非用过就扔的代码,你编写它是为了保留它。
曳光弹代码有点:
用户能够及早看到能工作的东西;
开发者构建了一个他们能在其中工作的结构;
有一个集成的平台;
有了可用于演示的东西;
能感觉到工作的进展;
原型制作生成用过就扔的代码;曳光弹虽然简约,但却是完整的,最终构成系统骨架一部分。
原型与便笺
为工作流和应用逻辑等动态事物制作原理,便笺是一个很好的选择。
应制作原型的事物:
1.架构;2.已有系统中的新功能;3.外部数据的结构或内容;4.第三方工具或组件;5.性能问题;6.用户界面;
怎样使用原型:
在制作原型时可忽略的细节:正确性,完整性,健壮性,风格;
用一些“胶合剂”把组件粘起来
用便笺、索引卡片在白板上将系统建模;
原型嘛,又不是曳光代码,用完就扔了它。
领域语言
语言的界限就是一个人的世界的界限;
用业务的语言去描述业务问题,而不用编程语言,这样就不会钻牛角尖。
举个例子:在一组X.25线路上侦听由ABC规则12.3定义的交易,把它们转译成XYZ公司的43B格式,在卫星上行链路上重新传输,并存储起来,供
分析使用将来。
剪裁后的小语言:
From X25Line1 (Format=ABC123){
Put TELSTAR1 (Format=XYZ43B);
Store DB;
}
用户又添加一个需求:不应存储余额为负的交易,而应以原来的格式在X.25线路上发送回去:
From X25Line1 (Format=ABC123){
if (ABC123.balance<0){
Put X25Line1 (Format=XYZ43B);
}
else{
Put TELSTAR1 (Format=XYZ43B);
Store DB;
}
}
Program Close to the Problem domian(靠近问题领域编程)
使用小型语言扩展现有语言
估算
Estimate to avoid surprise(估算,以避免发生意外)
130工作日和6个月,哪个显得更精确呢?
估算来自:
理解提问内容,注意问题域的范围;
建立系统的模型;
把模型分解为组件;
给每个参数制定值;
计算答案;
追踪估算能力;
Iterate the Schedule with the Code.(通过代码对进度表进行迭代)
让工具变为双手的延伸
纯文本的威力
Keep knowledge in Plain Text.用纯文本保存知识。
文本的威力:不过时;杠杆作用(每一样工具都可以工作在纯文本上);更易于测试;
纯文本是永远的公共通信标准。
Shell游戏
别受限于GUI界面,回到文本操作吧,让Shell成为你的朋友。
Use the Power of Command Shells.利用命令Shell的力量。
Cygwin,UWIN是Windows下的Unix Shell工具实现。
强力编辑
Use s Single Editor Well.用好一种编辑器。
编辑器特性:可配置,可扩展,可编程;
Emacs是一个很好的编辑器,Vi也是,EditPlus也是。
源码控制
进步远非游变化组成,而是取决于好记性。不能记住过去的人,被判重复过去。
源码控制系统(SCCS)是一个长效的Undo功能。我们可以在主干上开发,也可以生成一些完整的分支提供给客户。如果分支情况良好,可以考
虑将分支和主支合并。
Always Use Source Code Control.总是使用源码控制。
无论怎么样,只要你在计算机上工作就要使用它。
VSS,CVS,PCVS,SVN都是很不错的版本控制系统,还有就是ClearCase.
调试
调试的目的:解决问题
Fix the Problem,Not the Blame.修正问题而不是指责。
面对Bug千万不要恐慌或者认为那是不可能的,既然发生了就要积极面对它。
如何暴露Bug:
1.最好可以和报告Bug的人面谈一下,这样可以搜集更多的数据;
2.人工合成测试不能足够地演练应用,必须设计测试边界条件同时实现在现实中用户地使用模式;
测试策略
别让Bug离你太远,否则会捉不到它地。
1.使数据可视化:Variable name = data value.(直观地数据表达方式)
2.跟踪:
a.把小诊断消息打印到屏幕上或者文件中,例如什么printf或者System.out.println之类的;
b.栈的踪迹(Stack trace)。
3.橡皮鸭:对着别人解释你的代码,说着说着Bug就出来了;
4.消除过程:找问题先找自己的问题,再找别人的问题;再提交Bug报告前,必须先消除你代码中的Bug.
造成惊讶的要素:发生了,就认了把,然后努力去解决它。
Don't Assume it-Prove it.不要假定,要证明。
以后就别在说:“ Oh,My god”了。
文本操纵
Learn a Text Mainpulation Language.学习一种文本操纵语言。
用途列举:数据库维护,属性访问,测试数据生成,写书,接口,生成文档……
代码生成器
Write Code that Writes Code.编写能编写代码的代码。
被动代码生成器:只运行一次来生成结果
1.创建新的源文件;
2.在变成语言只间进行一次转换;
3.生成查询表及其他运行时很昂贵的资源;
主动代码生成器:在每次需要其结果时被使用
取某项知识的一种表示形式,将其转换未你的应用需要的所有形式,说白了就是格式转换。
世界上没有完美的代码,也没有完美的程序员。只有防卫性地编码和注重实效地程序员。
按合约设计(DBC)
Design with Contracts.通过合约进行设计
用合约的方法帮助软件模块进行交互;
程序做它生命要做的事情,用文档记载这样的声明,并进行校验;
例程对世界状态的期望:
前条件(precondition):调用例程必须的条件;
后条件(postcondition):例程完成后世界的状态;
类不变项(class invariant):类确保从调用者角度看,条件总为真;
Liskov替换原则:子类必须要能通过基类的接口,而使用者无须知道其区别;
实现DBC:断言与语言支持(Java:iContract)
不变项的用法:1.循环不变项;2.语义不变项
死程序不说谎
Crash Early.早崩溃
有时候宁愿要程序崩溃,也千万不要让它把坏数据写入;
检查每一个可能的错误——特别是意料之外的错误——是一种良好的实践;
断言式编程
If It Can’t Happen,Use Assertions to Ensure That Won’t.
如果它不可能发生,用断言确保它不会发生
不能用断言代替真正的错误处理
Java断言类实现
import java.lang.System;
import java.lang.Thread;
public class Assert{
public static void TEST(Boolean conition){
if(!conition){
System.out.println(“Assertion Failed”);
Thread.dumpStack();
System.exit(1);
}
}
}
如何使用异常
Use Exceptions for Exceptional Problems.将异常用于异常问题
对于出错或可能出错的地方尽量使用异常抛出,if来if去多麻烦。
怎么配平资源
Finish What You Start.要有始有终
记得释放你的资源,否则世界会因为你占有太多资源不堪重负,最终崩溃;
嵌套分配
1. 以与资源分配的次序相反的次序解除资源的分配;
2. 在代码的不同地方分配同一组资源时,总是以相同的次序分配它们;
无论是谁分配的资源,它都应该负责解除该资源的分配;
在Java开发中使用完某个对象都,将其设为NULL,这可以使垃圾回收器将它自动回收。
解耦与得墨忒耳法则
好篱笆促成好邻居
对象间直接得横贯关系有可能很快带来依赖关系得组合爆炸:如果n个对象相互了解,那么对一个对象得改动就可能导致其他n-1个对象都需要改动。
函数的得墨忒耳法则
尽可能遵守得墨忒耳法则的“羞涩”代码
Minimize Coupling Between Modules.
使模块间耦合减至最少
元程序设计
再多天才也无法胜过对细节专注;
动态配置:对于算法、界面之类,应该使用配置选项,而不是通过集成或工程实现;
Configure,Don’t Integrate.要配置,不要集成
元数据驱动的应用
Put Abstractions in Code, Details in Metadata.将抽象放进代码,细节放进元数据
在一个复杂工作流系统中,你将通过编写规则,而不是修改代码来配置它。
时间耦合
Analyze Workflow to Improve Concurrency.分析工作流,以改善并发行
在多个消费者进程间进行快速而粗糙的负载平衡的一种途径:饥饿的消费者(hungry consumer)模型
Design Using Services.用服务进行设计
在并发设计时应该注意公共变量,对其加以保护。同时也要保证线程安全
Always Design for Concurrency.总是为并发进行设计
它只是视图
模块具有单一的,定义良好的责任
模块间不需要互相知道太多
一件事件就是一条特殊消息
发布/订阅:Subscriber只对感兴趣的话题向Publisher进行订阅,而Publisher负责监听并分发消息。
MVC架构:
模型:表示目标对象的抽象数据模型。模型对任何视图或控制器没有直接的了解;
视图:解释模型的方式。它订阅模型中的变化和来自控制器的逻辑事件;
控制器:控制视图,并向模型提供新数据的途径。它既向模型,也向视图发布时间;
黑板
黑板系统让我们完全解除了我们的对象之间的耦合,并提供一个“论坛”,只是消费者和生产者都可以在那里匿名、异步地交换数据;
对黑板进行分区并组织上面资料以防止组合爆炸;
黑板方式地编程消除了太多接口需要,从而能带来更优雅、更一致地系统
Use Blackboards to Coordinate Workflow.用黑板协调工作流
编程不是机械工具
靠巧合编程
避免靠巧合编程,不要依靠运气和偶然地成功,而要深思熟虑地编程;
巧合编程:实现地偶然;语境地偶然;隐含地假定;
Don’t Program by Coincidence.不要靠巧合编程
深思熟虑地编程
1. 总是意识到自己在做什么
2. 不要盲目地编程
3. 按照计划行事,不管计划写在哪里
4. 依靠可靠地事务
5. 为你地假定建立文档
6. 不要只是测试你的代码,还要测试你的假定
7. 为你的工作划分优先级
8. 不要让已有地代码支配将来的代码
算法的效率
推荐:Sedgewick关于算法的书
常识估算:
简单循环O(n);嵌套循环O(n*n);二分法O(nlgn);组合:效率失控
Estimate the Order of Your Algorithms.估算你的算法的阶
Test Your Estimate.测试你的估算
重构
重写、重做和重新架构代码合起来,成为重构(refactoring)
应该重构代码的条件:
1. 重复,违反DRY原则
2. 非正交设计
3. 过时的知识
4. 性能不好
Refactor Early,Refactor Often.早重构,常重构
如何进行重构:
1. 不要试图在重构的同时增加功能;
2. 在开始重构之前,确保你拥有良好的测试;
3. 采取短小,深思熟虑的步骤
易于测试的代码
单元测试是对模块进行演练的代码,也是针对合约的测试
Design to Test.为测试而设计
测试驱动法:先测试代码,再进行模块测试
Print法——>即兴测试
Test Your Software,Or Your Users Will.测试你的软件,否则你的用户就得测试
邪恶的向导
慎用设计向导,否则那些自动生成的代码会让你崩溃
Don’t Use Wizard Code You Don’t UnderStand.不要使用你不理解的向导代码
需求之坑
Don’t Gather Requirements—Dig for them.不要搜集需求——挖掘它们
挖掘需求
需求是对需要完成的某件事的陈述
“我能否在你们工作时在这里呆上一周”——注意不要妨碍别人工作
Work with a User to Think Like a User.与用户一同工作,以像用户一样思考
建立需求文档
将挖掘出来的需求建立需求文档;
看待用例的一种方式是强调其目标驱动;
把形式化的模板用作备忘录;
规定过度
制作需求文档时的一大危险是太具体;
需求不是架构,需求不是设计,也不是用户界面,需求是需要;
看远些
Abstractions Live Longer than Details.抽象比细节活得更长久
再摸一层薄薄的薄荷
许多项目的失败都被归咎于项目范围的增大——也称为特性膨胀,蔓延特性论或需求蔓延
维护词汇表
对用户和领域专家的属于进行有条例地记录并随时维护
Use a Project Glossary.使用项目词汇表
把话说出来,放在Web上,大家一起看。
解开不可能解开的谜题
自由度
Don’t Think Outside the Box—Find the Box.不要在盒子外面思考——要找到盒子
对于各种约束和条件边界,应该从更高角度看,忽略一些不适用的约束,并确定你确实拥有自由度。
一定有更容易的方法
对于“不能解决的问题”经常问问自己:
1. 它真的必须完成吗?
2. 它必须以这种方式完成吗?
3. 是什么使它如此难以解决?
4. 这件事为什么是一个问题?
5. 你是在设法解决真的的问题,还是被外围的技术问题转移了注意力?
6. 有更容易的方法吗?
等你准备好了
Listen to Nagging Doubts—Start When You’re Ready.倾听反复出现的疑虑——等你准备好再开始
是良好的判断,还是拖延?
对于无法判断项目是否拖延,可采取一种行之有效的技术构建原型,而对于有困难的地方,可进行“概念验证”(proof of concept)
最可怕的事情:花了几周认真开发,却发现原来只要一个原型。
规范陷阱
注:这里的规范通常就是我们平常说的设计
程序规范就是把需求规约到程序员能够接管的程度;规范也是与用户的约定,一份隐含的合约。
Some Things Are Better Done than Described.对有些事情“做”胜于“描述”
应把需求挖掘、设计以及实现视为同一个过程,而不要信任:需求分析、编写规则、编码是独立的分开进行的。因为这些步骤本身就是无缝的。
太细的规范可能会演变为“分析瘫痪”(analysis paralysis)
圆圈与箭头
盲目采用任何形式方法,其结果往往令人失望
形式方法缺点:
1. 大多数形式方法结合图和文字说明,但用户通常喜欢原型
2. 形式方法鼓励专门化,大家更希望了解整个系统,而不是冰山一角
3. 元数据让我们运行时改变应用特征,而大多数形式方法鼓励你在对象间建立静态关系
Don’t Be a Slave to Formal Methods.不要做形式方法的奴隶
批判地看待方法学而从中提取精华,融合到每项工作中。
Expensive Tools Do Not Produce Better Designs.昂贵地工具不一定能制作出更好地设计。
注重实效的团队
不要留破窗户——对软件质量负责,要及时修复缺陷和错误,可以考虑配置一个“质量官员”;
煮青蛙——确保每个人都主动监视环境变化,要不要设置一个“首席水情检测官”呢?
交流——沉默寡言的团队是最糟糕的团队,导致文档、设计、编码……一切工作的混乱;
不要重复你自己——还是要团队内的交流(项目资料管理员);
正交性——项目活动不会孤立发生,Organize Around Functionality Not Job Functions.围绕功能,而不是工作职务进行组织;
自动化——确保一致和准确的方式是使团队所做每件事情自动化;
给团队每个成员足够空间,支持他们,让他们在项目中以自己的方式闪亮。
无处不在的自动化
我们需要保证项目的一致性和可重复性,而人工流程不能保证一致性,也无法保证可重复性,因此我们应该尽可能的使用自动化。
一切都要自动化
Don’t Use Manual Procedures.不要使用手工流程
通过一些自动化工具,如cron等,使任务(例如备份、夜间构建等)在无人照管的情况下自动地、周期地运行。
让如makefile进行如项目编译、生成代码、回归测试、信息生成(包括Web信息)以及最终的构建等,此类工具还有Ant
构建自动化:在晚上进行完整构建,运行所有测试
自动化管理:包括了资料与网站自动生成,一些工作流程自动化等;
推荐书目《项目自动化之道-如何建构、部署》
无情的测试
Test Early,Test Often,Test Automatically.早测试,常测试,自动测试
测试如捕鱼,捕什么鱼用什么测试
好的项目拥有测试代码可能比产品代码还要多
Coding Ain’t Done ‘Til All the Test Run.要到通过全部测试,编码才算完成
测试种类:
1. 单元测试:对某个模块进行演练的代码
2. 集成测试:组成项目的主要子系统能工作,并很好协同
3. 验证和校验:满足客户需要吗?
4. 资源耗尽、错误和恢复
5. 性能测试、压力测试和负载测试
6. 由真实用户在真实环境条件下进行可用性测试
测试方法:
1. 回归测试:测试输出的对比
2. 测试数据:大量的、强调边界条件的、展现特征统计属性的数据
3. 演练GUI系统
4. 对策是进行测试:Use Saboteurs To Test Yout Testing.通过“蓄意破坏”测试你的测试。(故意引发一些测试)
5. 彻底测试:覆盖分析(Coverage Analysis)Test State Coverage,Not Code Coverage.测试状态覆盖,而不是代码覆盖
6. 测试时间:当项目开始后,随时测试,千万不要流到最后一分钟
Find Bugs Once.一个Bug只抓一次.
全都是写
文档和代码时同一底层模型的不同视图,不要让文档变成二等公民
将文档与代码进行结合,使用如JavaDoc之类的工具自动产生文档
Treat English(Chinese) as Just Author Programming Language.把英语(中文)当作又一种编程语言
Build Documentation In, Don’t Bolt It On.把文档建在里面,不要拴在外面.
匈牙利表示法:把变量类型信息放在变量名自身里.
不应出现源码注释:
1. 文件种的代码导出的函数列表
2. 修订历史
3. 该文件使用其他文件列表
4. 文件名
可执行文档:例如数据库Schhema或带有标记的纯文本
DocBook是一种机遇SGML的标记语言
极大的期望
项目的成功是由它在多大程度上满足了用户的期望来衡量
Gently Exceed Your Users’ Expectations.
温和地超出用户的期望
管理期望(managing expectations):主动控制用户对他们能从系统中得到什么应该抱有的希望.
如果你和用户紧密协作,分享他们的期望,并同他们交流你正在做的事情,那么当项目交付时,就不会发生多少让人吃惊的事情了.
傲慢与偏见
Sign Your Work.在你的作品签名
尊重别人的代码,对自己的代码负责,使自己的签名变成质量的保证。为自己的代码负责,告诉别人“这就是我的代码”。
其他的好书推荐:
推荐书籍目录如下,后续蛤蟆会陆续增加到本篇当中
1、《程序员修炼之道》
2、《重构》
3、 《设计模式》
4、《测试驱动发开》
5、《UNIX编程艺术》
6、《算法导论》
7、《计算机程序设计艺术》
8、《数据结构》 叫这个数目的书很多,推荐作者是:Ellis Horowitz, Sartaj Sahni, Susan Anderson-Freed
9、《代码大全》