概述
花了几天时间看完了程序员修炼之道,有很多感悟,记录于此,供自己开发时参考,相信对其他人也有用。
值得一提的是,这本书写的非常好,很多大牛在走了很多弯路之后再读这本书都很感慨没有早些读。
注重实效的哲学
- 我的源码让猫给吃了
1.为你的行为负责是注重实效的哲学的一块基石。
2.除了尽你所能之外,你必须分析风险是否超出了你的控制。对于不可能做到的事情或是风险太大的事情,你有权不去为之负责。
3.要提供各种选择,而不是找借口;不要说事情做不到,要说明能够做什么来挽回局面。
- 软件的熵
1.熵指的是某个系统中的“无序”的总量。当软件中的无序增长时,程序员们称之为“软件腐烂”。
2.不要留着“破窗户”(低劣的设计,错误的决策,或是糟糕的代码)不修,发现一个就修一个。
3.按照同样的道理,如果你发现你所在的团队和项目的代码十分漂亮——编写整洁,设计良好,并且很优雅——你就很可能会格外注意不去把它弄脏,就和那些消防员一样,即使有火在咆哮(最后期限,发布日期,会展演示等),你也不会想成为第一个弄脏东西的人。
- 石头汤与煮青蛙
1.但请求许可去处理整个事情,你会遇到拖延和漠然。大家要设立委员会,预算需要批准,事情会变得复杂化。每个人都会护卫他们自己的资源,这叫做“启动杂役”。
2.这正是你拿出石头的时候,设计出你可以合理要求的东西,好好开发它,一旦完成,就拿给大家看,让他们大吃一惊,然后说要是我们增加**可能就会更好。俗话说,参与正在发生的成功要更容易。
- 足够好的软件
1.你可以训练你自己,编写出足够好的软件——对你的用户,对未来的维护者,对你自己内心的安宁来说足够好,你会发现,你变得更多产,而你的用户也会更加高兴。
2.艺术家告诉你,如果你不懂的应何时止步,所有的辛苦劳作就会遭到毁坏。不要因为过度修饰和过于求精而毁损完好的程序。
3.考察你使用的软件工具和操作系统的制造商。你能否发现证据,表明这些公司安于发布他们知道不完美的软件吗?作为用户,你是会(1)等着他们清楚所有bug,(2)拥有复杂的软件,并接受某些bug,还是会(3)选择缺陷较少的更简单的软件。
- 你的知识资产
1.你的知识和经验是你最重要的职业财富,遗憾的是,它们是有时效的资产。
2.经营你的资产:定期投资;多元化;管理风险;低买高卖;重新评估和平衡。
3.目标:每年至少学习一种新语言;每季度阅读一本技术书籍;也要阅读非技术书籍;上课;参加本地用户组织;实验不同的环境;跟上潮流;上网。
4.批判的思考你读到的和听到的,你需要确保你的资产中的知识是准确的,并且没有受到供应商或媒体炒作的影响。
5.感悟:每一种语言都有各自的应用场景,比如说java就用来开发软件,html就用来开发网页,perl就用来文本操作。所以就算是前端工程师,也需要了解其他语言的用法。
6.出去与你的当前项目无关的人,或是其他公司的人谈谈技术。
- 交流
1.只有当你是在传达信息时,你才是在交流,为此,你需要了解你的听众的需要,兴趣和能力。你想让他们学到什么?他们对你讲的什么感兴趣?他们有多富有经验?他们想要多少细节?你想要让谁拥有这些信息?你如何促使他们听你说话?
2.要记住,你也是交流事务的一方。如果有人说,他们需要你用一段话进行描述,而你觉得不用若干页纸就无法做到,如实告诉他们。记住,这样的反馈也是交流的一种形式。
3.在匆忙的日常生活中,你应该总是做出回应,即使内容只是“我稍后回复你”。随时通知别人,会让他们更容易原谅你偶然的疏忽。
4.将你的电子邮件(收到的重要文件和发送的邮件)加以组织并存档。
注重实效的途径
- 重复的危害
1.我们都是在一个时间和资源有限的世界上工作。如果你善于估计出事情需要多长时间完成,你就能更好的在两者都很匮乏的情况下生存下去。
2.DRY原则:系统中的每一项知识都必须具有单一,无歧义,权威的表示。
- 正交性
1.如果两个或更多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的。
2.正交性的另一个有趣的变体是面向方面编程,Aspect-Oriented Programming,AOP。
- 可撤销性
1.我们不必做出许多关键的,不可逆转的决策,所以我们的代码需要有可撤销性。
- 曳光弹
1.曳光弹与常规弹药交错装在弹药带上。发射时,曳光弹中的磷点燃,在枪与它们击中的地方之间留下一条烟火般的踪迹。如果曳光弹击中目标,那么常规子弹也会击中目标。
2.曳光弹的优点:用户能够及早看到能工作的东西;开发者构建了一个他们能在其中工作的结构;你有了一个集成平台;你有了可用于演示的东西;你将更能够感到工作进展。
3.原型制作生成用过就扔的代码;曳光弹虽然简约,却是完整的,并且是构成最终系统的一部分。
- 原型与便笺
1.我们也以同样的方式构建软件原型,为了分析和揭示风险,并且大大降低代价。
2.原型的设计目的就是回答一些问题,所以与投入使用的产品应用相比,他们可以忽略不重要的细节,开发便宜得多。
3.你可以为下列事物制作原型:架构;已有系统中的新功能;外部数据的结构或内容;第三方工具或组件;性能问题;用户界面设计。
- 领域语言
1.计算机语言会影响你思考问题的方式,以及你看待交流的方式。
2.如果用户有一些做了良好限定的陈述,你可以发明一种为应用领域进行了适当裁剪的小型语言,确切的表达他们的需要。
3.我们已经看到若干不同的文法,范围从简单的面向行的格式到更为复杂的看起来像真正的语言的文法。既然实现更为复杂的文法需要额外的努力,你又为何要这样做呢?权衡要素是可扩展性与维护。所以有时候我们也可以考虑用其他语言,在保证可扩展性与维护的前提下。
- 估算
1.但有人要你进行估算时,你要问自己的第一个问题就是,你解答问题的语境是什么?他们是需要高度的准确性,还是在考虑棒球场的大小?
2.“130天”和“6个月”表示相同的时长,但“130天”却可能暗含了比你的感觉更高的精确程度。
3.除了精确度问题外,你还需要把握问题域的范围。比如说:假定没有交通意外,而且车里还有汽油,我会在20分钟内赶到那里。
4.把估算分解为小估算,然后给每个小估算的参数赋值,最后合并为大估算。
5.在被要求进行估算时可以说:我等会儿回答你。
基本工具
- 纯文本的威力
1.工具是你双手的延伸。
2.纯文本格式,就是没有任何文本修饰(粗体,下划线,斜体,图形等),也没有影音、图像、样式、超链接、表格等的文本。
3.提供“锋利”的小工具,其中每一样都意在把一件事情做好——Unix因围绕这样的哲学进行设计而著称。
4.纯文本的好处:保证不过时;杠杆作用;更易于测试。
5.使用你喜欢的语言,用直接的二进制表示设计一个小地址簿数据库。
6.XML是纯文本的好例子。
- shell游戏
1.GUI的好处是WYSIWYG,所见即所得;缺点是WYSIAYG,所见即全部所得。通常,任何一样工具的适用范围都局限于该工具预期要完成的任务。
2.你是否曾将一些说明发给同事,其中涉及许多“点这个按钮”,“选哪一项”之类的步骤?他们能自动化吗?
3.每当你迁往新环境,要找出可以使用的shell,并且调查各种可用于替换你现在shell的选择。
- 强力编辑
1.语法突显非常有用;能够在编辑器环境中进行编译,并直接转到出错处非常方便;自动缩进是另一种有用的特性,编辑器在比如敲入左花括号时为你进行缩进。
- 源码控制
1.源码控制系统(sccs)能做的远比撤销错误要多。好的sccs让你追踪变动,回答这样的问题:谁改动了这一行代码?在当前版本与上周的版本之间有什么区别?在这次发布的版本中我们改了多少行代码?哪个文件改动最频繁?
- 调试
1.人很容易恐慌,但非常重要的事情是,要后退一步,实际思考什么可能造成你认为表征了bug的那些症状。
2.编译器只能帮你找出部分bug。
3.bug报告的准确性在经过第三方之手时会进一步降低——实际上你可能需要观察报告bug的用户的操作,以获取足够程度的细节。
4.我们想要的不是能够通过长长的步骤再现的bug;我们要的是能够通过一条命令再现的bug。
5.找到问题的原因的一种非常简单却又特别有用的技术是向别人解释它。
6.当你遇到让人吃惊的bug时,除了知识修正它以外,你还需要确定先前为什么没有找出这个故障。考虑你是否需要改进单元测试或其他测试,以让他们有能力找出这个故障。还要考虑造成这个bug的条件是否存在于系统中的其他任何地方?
- 文本操纵
1.学习一种文本操纵语言,比如说perl。
- 代码生成器
1.当木匠面临一再地重复制作同一样东西的任务时,他们会取巧。他们给自己建造夹具或模板。一旦他们做好了夹具,他们就可以反复制作某样工件。夹具带走了复杂性,降低了出错的机会,从而让工匠能够自由地专注于质量问题。
2.主动代码生成器和被动代码生成器。
3.你可以用代码生成器生成几乎任何输出:html,xml,纯文本——可能成为你项目中别处输入的任何文本。
注重实效的偏执
- 按合约设计
1.注重实效的程序员连自己也不信任,知道没有人能编写完美的代码,包括自己,所以注重实效的程序员针对自己的错误进行防卫性的编码。
2.什么是正确的程序?不多不少,做它声明要做的事情的程序。
3.如果任何一方没有履行合约的条款,某种补偿措施就会启用,例如引发异常或是终止程序。
4.继承和多态是面向对象语言的基石,是合约可以真正闪耀的领域。
5.在设计时简单的列举输入域的范围是什么,边界条件是什么,例程允诺交付什么——或者,更重要的,它不允诺交付什么——是向着编写更好的软件的一次飞跃。
6.不变项也是一种合约。
7.一定不要把固定的需求,不可违反的法则与那些仅仅是政策的东西混为一谈,后者可能会随着新的管理制度的出台而改变。
- 死程序不说谎
1.尽早检测问题的好处之一是你可以更早崩溃。而有许多时候,让你的程序崩溃是你的最佳选择。
2.为什么要设计抛出异常?因为在遇到异常的时候我们一般会终止程序,但是在终止程序之前我们还要做很多其它的事情,比如说记录log啊释放变量啊什么的。
- 断言式编程
1.在自责中有一种满足感,当我们责备自己时,会觉得再没人有权责备我们。
2.不要用断言代替真正的错误处理,因为断言检查的是绝不应该发生的事情。
- 何时使用异常
1.即使用异常编程可能会更简洁,但是不要把异常用作正常处理的一部分程序,因为他们破坏了封装:通过异常处理,例程和它们的调用者被更紧密地耦合在一起。
2.不支持异常的语言常常拥有一些其他的非局部控制转移机制。
- 怎样配平资源
1.为什么有栈?因为以与资源分配的次序相反的次序解除资源的分配的话,如果一个资源含有对另一个资源的引用,你就不会造成资源被遗弃。
2.死锁:如果进程A申请了resource1,并正要申请resource2,而进程B申请了resource2,并试图获得resource1,这两个进程就会永远等待下去。解决办法之一是在代码不同的地方分配同一组资源时,总是以相同的次序分配他们。