程序员修炼之道(The Pragmatic Programmer)

注重实效的程序员的特征


我们采集的是石头,但是必须时刻展望未来的大教堂。(即使对于不是处于高层的开发者,我们也必须时刻展望着你所处的整体,因为这样不仅有动力,而且能够让你在一些问题上面做出更好的判断)


持续做一些小改进,几年之后你会惊奇地发现你的经验得到了怎么样的发展,你的技能得到了怎样的提升


名称的内涵(在这里我所想到的就是,对于一个项目,我们必须对于一些关键概念作一些名称的定义,比如什么叫做用户处理请求单元,什么叫最小申请时间等这些更具开发的项目不同而含义不同的名词,应该进行统一的定义和规范,这样才能够很好在组内进行交流)


注重实效的程序员的特征是什么?我觉得是他们处理问题,寻求解决方案时的态度,风格,哲学。他们能够越出直接的问题去思考,总是设法把问题放在更大的语境中,总是设法注意更大的图景。毕竟,没有这样大的图景,你又怎么能够注重实效?你又怎么能够做出明智的妥协和有见识的决策呢?


在所有的弱点中,最大的弱点就是害怕暴露弱点(所以尽量所得暴露弱点并且去完善它,这样才会有进步)。为你的东西负责,提供各种选择,不要找蹩脚的借口


不要留着破窗户(低劣的设计,错误决策和糟糕的代码)不修。发现一个就修一个。如果没有足够的时间进行适当的修改,就用木板钉起来。或许你可以把出问题的代码加上注释,或是显示未实现消息,或是虚假的数据代替。采取某种行动防止进一步损坏,并说明情形处在你的控制中。同时破窗户可能会影响团队中其他成员的积极性


人们发现,参与正在发生的成功要更容易一些,让他们瞥见未来,你就能让他们聚集在你的周围。看来我也知道有时候应该做些什么事情了。偶尔时候展望一下未来,会让别人也觉得有信心。做一个项目的变化催化剂。(ok,2008年在百度实习时候做的项目,老板已开始给出的是一个很丑陋的方案,可以说没有任何用途,但是每次作完之后,老板总是提一些需求并且说以前的实现效果不是很好,慢慢的这样改进,软件最后开始可用了。如果你在领导一个项目,你的责任还包括鼓励其他的员工不断完善软件:-))


使质量成为需求问题。只有当质量成为一个需求问题,质量才会有明显的提升:-)


艺术家会告诉你,如果你不懂的什么时候止步,所有的辛苦劳动就会遭到损坏。如果你一层又一层,细节复细节地添加,绘画就会迷失在绘制中。


我们把程序员所知道关于计算技术和他们所工作的领域全部事实以及他们所有经验视为他们的知识资产(knowledge portfolios),管理知识资产与金融资产非常相似

目标:

与他人交谈还可以帮助你建立人际网络,而因为在这个过程中找到了其他不相关问题的解决方案,旧友的资产也在不断增长。

交流:


给予计算机两项自相矛盾的知识,是Captain James T.Kirk(from Star Trek)喜欢用来使四处劫掠的人工智能生命失效的方法。重复是有很大危害的,使得代码修改起来不方便就是不容易维护。但是在实际的商业商品中,软件可用也是一个很重要的问题,很多软件里面存在着很多重复但是没有人愿意去修改:-)


对于注释的编写,头文件最好就是编写接口的作用,而源文件就是编写具体的实现。


如果两个或者是更多的事物其中一个发生变化不会影响到其他事物,这些事物就是正交的。良好的系统数据库代码和界面代码正交,修改任何一项不会影响另外一项。


错误在于假定决策是浇铸在石头上的,同时还在于没有为可能出现的意外事件做好准备。要把决策视为写在沙滩上的,而不要把它们刻在石头上。大浪随时可能到来,把它们抹去。


原形制作生成用过就丢的代码。曳光弹代码虽然简约,但是却很完整,并且最终构成了系统的骨架一部分。你可以把原形制作视为第一次发射曳光弹之前的侦查和情报搜集工作.原形制作可以忽略那些细节1.正确性 2.完整性 3.强壮性 4.风格. 算法原形语言可以考虑Perl Python或者是Tcl而界面原形部分可以考虑Tcl/tk,Visual Basic,PowerBuilder或是Delphi。感觉脚本语言在不断的推出库的原因一方面是为了方便原形制作,同时也为语言成为非原形做好强力的准备。如果你觉得在你所在的环境或者文化中,原形代码的目的很有可能被误解,最好还是采用曳光弹的方法。你最后将得到一个坚实的框架,为将来的开发奠定基础


语言的界限就是一个人的世界的界限-维特根斯坦.对于一个问题的描述,最好使用一门特定的语言进行描述。这种语言无需是可执行的。一开始它只是用于捕捉用户需求的一种方式或者是一种规范,但是如果你想跟进一步实现该语言,你的规范变成为了可执行文件。这或许大概就是一门语言的形成过程


对于估算是一个很重要的能力,特别对于一些应用级的开发,估算是十分必要的。对于估算,下面是一个形式化的步骤,但是却很有效:-)


工具放大你的才干。你的工具越好,你越是能够刚好地掌握他们的用法,你的生产力就越高。从一套基本的通用工具开始,随着经验的获得,随着你遇到一些特殊的需求,你将会在其中增添新的工具。要与工匠一样,定期增添工具。总是寻找更好的做事方式。


纯文本并非意味着文本无结构,XML,SGML,HTML都是具有良好定义结构的纯文本。


GUI的好处是WYSIWYG,但缺点是WYSIAYG(what you see is all you get)


选择一种编辑器,彻底了解它,并将其用于所有的编辑任务。如果你用一种编辑器进行所有的文本编辑活动,你就不必停下来思考怎么样完成文本操作:必须的击键将成为本能反应。编辑器将成为你双手的延伸。


如果你目睹bug或者见到bug报告时的第一个反应是:”那不可能”,你就完全错了。一个脑细胞都不要浪费在“但那不可能发生”起头的思路上,因为很明显,那不仅可能,而且已经发生了注重实效的程序员会更进一步,他们连自己都不信任。知道没有人能够编写完美的代码,包括自己,所以注重实效的程序员针对自己的错误进行防卫性的编码


在自责中有一种满足感。当我们责备自己时,会觉得再没有人有权责备我们。奥斯卡·王尔德(或许这就是懦夫存在的原因)


嵌套的分配.对于一次需要使用不只一个资源的例程时,可以对资源分配的基本模式进行扩展。另外有两个建议

不管我们在使用的是何种资源,事务,内存,文件,线程,窗口等,都满足上面的建议:-)


再多的天才也无法胜过对于细节的关注 Levy’s Eighth Law(所以引入了抽象和模块)


作为开发者,我们也工作在雷区。每天都有成百的陷阱在等着抓住我们。记住士兵的故事,我们应该警惕,不要得出错误结论。我们应该避免靠巧合编程-依靠运气和偶然的成功-而要深思熟虑的编程.怎么样深思熟虑的编程.要想让编写代码所花的时间更少,想要尽可能地在开发周期早期抓住并修正错误,想要一开始就少制造错误。如果我们能够深思熟虑,那对于我们会有帮助


当你遇到绊脚石,代码不再合时,你注意到有两样东西其实应该合并或者其他任何对你来说是“错误”的东西,不要对改动犹豫不决。应该现在就做。无论代码具有下面哪些特征,你都应该考虑重新构造代码 1.重复 2.非正交设计 3.过时的知识。事情便了,需求转移了,你对问题的了解加深了,代码也需要跟上这种变化 4.性能. 重构你的代码-四处移动功能,更新先前的决策-事实上是“痛苦管理”(pain managemen. 显然重构是一项需要慎重考虑,小心进行的活动。关于怎么进行利大于弊的重构,Martin Fowler给出了以下简单的指示


芯片在设计时就考虑了测试,不只是在工厂,安装时,而且在部署现场进行测试。更加复杂的芯片和系统可能拥有完整的Built-In Self Test(BIST)特性,用于在内部运行某种基础级的诊断。或者拥有Test Access Mechanism(TAM),用以提供一种测试装备。允许外部环境提供激励,并收集来自芯片的响应。


构建测试窗口。对于大部分的单元测试工具,最终能够显示那些测试用例通过哪些没有通过并且能够很好的展现出来,但是如果我们需要进一步了解代码的运行状态的话,那么我们可以采用日志的方式看看测试的内容和具体的信息,所以日志还是很重要的:-)


问题并不在于你是在盒子里面思考还是在盒子外面思考,而在于找到盒子-真正的约束(找到真正的问题,然后解决它,这才是最重要的.就像TP告诉我为什么脚本语言好,是因为你能够真正的找到问题而不被内存管理,如何实现低级的数据结构所分心。但是我觉得使用低级语言一样,只要我能够站在高层面的角度上思考问题而不被这个语言所限制).这正是你会退一步,问问你自己以下问题的时候

很多时候,当你设法回答这些问题时,你会有让自己吃惊的发现。你所需要的知识真正的约束,令人误解的约束还有区分它们的智慧


你是一个了不起的表演者。你也需要倾听内心的低语声:“等等”如果你坐下来开始敲击键盘,在你的头脑里面反复出现某种疑虑,要注意它(要深思熟虑的编程)。倾听返回出现的疑虑,等你准备好再开始


有些事情是不适合描述的。尤其是对于一些细节的问题,过度的描述反而容易限制开发者的编写效率。所以可以这样说,对于高层次的问题,我们必须要对其进行一些描述,而对于低层次的问题,比如如何实现我们就不要再施加更多的限制了:-)。


我们是否应该使用形式方法,绝对应该。但是始终记住,形式开发方法知识工具箱里面的又一种工具。如果在仔细分析之后,你觉得要使用形式方法,那就采用它,但要记住谁是主人,不要变成方法学的奴隶注重实效的程序员批判地看待方法学,并从中提取精华,融合成自己的习惯。


形式方法在开发中肯定有其位置。但是如果你遇到一个项目,其哲学是“类图就是应用,其余的只是机械编码时”你知道,你看到的是一个浸满水的项目团队和一个路途遥远的家(这或许就是我觉得那些软件工程课根本没有用的原因,因为讲这些课的老师就是这么一群人)


花30分钟设计一个滑稽的标识,并且把它用在你的备忘录和报告上面,越别人交谈时,大方地使用你团队名字。这听起来很傻,但是能给你的团队一个用于建设的身份标识,并给世界某种难忘的,可以与你们工作相关联的东西(体现团队荣誉感)


这里有一层隐含的关系,按照对你的授权,你越接近用户,你的级别就越高。离代码的用户有两三层远的程序员不大可能注意到它们的工作的应用语境,因此他们也将无法做出有见识的决策


自动化使每个项目团队的必要组成部分。为了确保事情得以自动化,制定一个或者多个团队成员担任工具构建,构造和部署使项目中的苦差事自动化的工具,让它们制作makefile,shell脚本,编辑器模版和实用程序


对于一些好的项目拥有的测试代码可能比产品代码还要多。编写这些测试代码所花的时间是值得的。从长远来看,它最后会便宜得多,而你实际上有希望制作出接近零缺陷的产品:-)


注重实效的程序员会把文档当作整个开发过程的完整组成部分加以接受。不进行重复劳动,不浪费时间,并且把文档放在手边。如果可能,就把文档放在代码中。并且把英语当作另一种编程语言,这样你就会努力去维护你的注释了


注释代码给你了完美的机会,让你去把项目的那些难以描述,容易忘记却又不能够记载在任何别的地方的东西记载下来:工程上面的权衡,为何作出这种决策还有放弃了那些替代的方案:-)


用户高兴得的特征


不得不说这里面提供了相当多的资源,有兴趣的话真的值得查阅

comments powered by Disqus