Skip to content

Latest commit

 

History

History
190 lines (108 loc) · 12 KB

The_Pragmatic_Programmer-程序员修炼之道.md

File metadata and controls

190 lines (108 loc) · 12 KB

0:前言

我记得有人说,看书前最好想想自己为什么要看这本书,看这本书是为什么追求什么答案。

然而,看这本书前,其实我没有什么疑问的。或者说,我还不会编程。

很显然,我十分赞同前言中所述:编程并非只是敲入某种语言的行为。

回想起来,到目前为止,我所有的敲代码的行为都是为了自己,为了取乐或者其他目的。

但即使如此,我依然希望能够写出更赏心悦目的代码。

我怀着好奇之心阅读此书。

即便只获益一鳞半爪,依旧令我心怀感激。

提示1:关心你的技艺。

提示2:思考!你的工作。

1:我的源码让猫吃了

其实在我看来,在事前应承某些要求之前,“分析风险是否超出你的控制”,“对不可能做到的事情或是风险太大的事情”,在我看来,“不去为之负责”本身就是我们的责任。

坦白告知对方自己力有不逮,能够在造成损失前规避风险。

只有在接受任务并且犯错之后,才需要考虑提示3:提供挽回局面的各种选择,而非找蹩脚的借口。

经过多年撒谎的经验以后我得出一个结论,撒出一个近乎完美的谎言/借口的可能性实在是太小了。

相信我,谎言在多数情况下其实都是漏洞百出的。

提示3:提供各种选择,不要找蹩脚的借口。

10&11:曳光弹 与 原型与便笺

曳光弹的做法在多数情况下比费力计算的方法更为行之有效,且更为经济。

所以一接到任务就埋头苦干的哥们其实你们做的不算错,当然,如果能分出一点时间来先分析一下就更好了。

如同提示15所言,曳光弹的主要用场还是在于找到目标。

在我看来,它与原型的区别也在于此:

已经有了方向,为了测试与寻求解答而制作的,用过即废,并且可以帮助我们推迟考虑细节的方法应该就是原型的方法。

而在探索时所做的,拥有完整结构(异常处理,文档等等),制作的目的是为了真正将代码写入项目代码中去的方法应该就是曳光弹方法。

其实说了等于没有说,因为很简单,我没有参与过大的项目,对我而言,我几乎所有的工程都是用类似曳光弹方法做的。

所以我来阐述两者的区别意义不大。

提示15:用曳光弹来找到目标。

提示16:为了学习而制作原型。

33:重构

关于重构其实可以说很多,比如 酷壳 ,比如 黑客志 ,有很多文章提到这件事。由此可见,重构确实是在码代码时相当常遇到的事情了。(废话,你会不讨论面向对象,会不讨论设计模式,会不讨论算法优劣,但是我难以想象竟然存在程序员没有重构过代码)。

当然,既然可以说的多,褒贬也就不一定了,毕竟这方面没有真理部,没有有关部门统一口径。

有文章说不到确实必要时不要去重构代码,也有文章(譬如本书提示47)说要“早重构,常重构”。

我所做的无疑都是一些小东西,代码量最大的也不过是几百行代码,所以我的所作所为比较符合书中的说法,我也确实认同书中举出的认为重构必要的原因:

如果它现在有损害,那么以后的损害就会更大。

当然,这不代表我不赞同黑客志里文章的说法。 其实我喜欢的是书中提到的“怎样重构”(P186):

  • 不要试图在重构的同时增加功能。(我记住了……)
  • 在开始重构前,确保你有良好的测试。尽可能经常运行这些测试。这样,如果你的改动破坏了任何东西,你就能很快知道。(好吧,我知道这个叫做测试驱动开发,但是我还真没尝试过……从来没有写过单元测试什么的……当然,主要还是程序小。)
  • 采取短小、深思熟虑的步骤:把某个字段从一个类移往另一个,把两个类似的方法融合进超类中。重构常常涉及到进行许多局部改动,继而产生更大规模的改动。如果你使你的步骤保持短小,并在每个步骤之后进行测试,你将能够避免长时间的调试。

最后还有一点,当然,做不做随便你,反正我是不怎么会去做:

确保对模块作出剧烈改动——比如以一种不兼容的方式更改了其接口或功能——会破坏构建,这样很有帮助。也就是说,这些代码的老客户应该无法通过编译。于是你可以很快找到这些老客户,并做出必要的改动,让它们及时更新。(这个直接要求更新就好了吧 Orz)

提示47:早重构,常重构。

8:正交性

书中说到,正交性的概念很少被直接讲授。就我个人所见而言确实如此。但它的另一个名字却多有被人提及——高内聚,低耦合。

在计算技术中,该术语用于表示某种不相依赖性的或是解耦性。如果两个或更多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的。

其实刚看的时候我以为说的只是低耦合的原则,后来看见一道习题,说两个用于把输入行拆分胃字段的类,A的构造函数读入文件流,B读入字符串,问哪个是更为正交(低耦合)的设计。

书中的答案是B,说它“更专注于自己的任务,拆分输入行,同时忽略像输入行来自何处这样的细节。这不仅使代码更易于开发,也使得代码更为灵活。拆分的行可以来自文件、可以由另外的例程生成、也可以通过环境传入”。

我之前说过,看这本书是为了写出更赏心悦目更易维护效率更高(似乎又多了几个要求?不管它了……)的代码,于是乎,正交性自然就成了其中的标准之一。

有人说,好的代码,很多时候代码即注释。我认为这应该也是正交的代码带来的好处之一。(当然,函数名与变量名也很重要 ;D)

对于正交设计,有一种很简单的测试方法。一旦设计好组件,问问你自己:如果我显著地改变某个特定功能背后的需求,有多少模块会受影响?在正交系统中,答案应该是“一个”。

当然,这在现实生活中简直有点天方夜谭。但我以为这依旧是一种不错的测试方法(其实主要是想不到其他方法了Orz……) 我很喜欢文中的,对第三方工具箱与库的选择之道:

是否需要以一种特殊方法才能使用,如果是,那就是非正交的,因为这不易于在将来更换供应商。

我认为他想说的是——如果没有这个库或者换个库,你的代码是否需要大幅修改?如果是,那就不正交。

以及,如何维持代码的正交性:

  1. 编写“羞怯”的代码
  2. 避免使用全局数据
  3. 避免编写相似的函数

文中提到了项目团队的正交性:

如果要对项目团队进行非正式的衡量。只要看一看,在讨论每个所需改动是需要涉及多少人。人数越多正交性自然越差。

然而,我还知道一个理论,似乎称作“巴士效应”:你的团队在被巴士压死多少人以后就无法正常运作了?人数越少,你的团队的结构就越危险。

解除与现实世界变化的耦合:

还要问问你自己,你的设计在多大程度上解除了与现实世界中的变化的耦合?你在把电话号码当作顾客标识符吗?如果电话公司重新分配了区号,会怎么样?

提示13:消除无关事物之间的影响。

26:解耦与得墨忒耳法则

在“正交性”和“按合约设计”中提到,编写“羞怯”的代码是有益的。

“羞怯”的工作方式有两种:不向别人暴露自己,不与太多人打交道。

具体的做法可以参照间谍的组织方式,即:几个人(代码)组成一个最小组织单位(函数),单位与单位之间依靠预先约定好的渠道进行信息的交换。这样,即使一个最小组织单位被发现了,也不会危机到其他的单位。

为了实现提示36,我们就需要尽可能地遵守得墨忒耳法则:

某个对象的任何方法都应该只调用属于以下情形的方法: * 它自身 * 传入该方法的任何参数 * 它创建的任何对象 * 任何直接持有的组件对象

使用得墨忒耳法则能够缩小调用类中的响应集的规模,出现的错误往往最少,也能够使代码适应性更好、更健壮。

但这也有代价,因为这意味着你需要编写大量包装方法,这些包装方法既会带来运行时代价,也会带来空间开销。在有些应用中,“这可能会有重大影响”

提示36:使模块之间的耦合减至最少。

2:软件的熵

这一节讲的是如何保持项目代码的整洁与优雅。

熵是一个来自物理学的概念,指的是某个系统中的“无序”的总量。软件的熵与热力学定义的熵一样,总是倾向于最大化。

当软件中的无序增长时,程序员们称之为“软件腐烂”。

文中提到,很多因素会引发这种情况,其中最重要的似乎是开发项目时的心理。

有一种心理效应被称作“破窗效应”。

一扇破窗户,只要有那么一段时间不修理,就会渐渐给建筑的居民带来一种废弃感——一种职权部门不关心这座建筑的感觉。于是又一扇窗户破了。人们开始乱扔垃圾。出现了乱涂乱画。严重的结构损坏开始了。……

开发也是如此。一段设计低劣的代码,团队必须在整个项目开发过程中加以忍受的一项糟糕的管理决策就足以使项目开始衰败。在这样的项目里工作,会很容易产生这样的想法:“这些代码的其余部分也是垃圾,我只要照做就好了。”(这样的事情我也遇到过,当时真的是重构的想死啊,三番两次的出现了这样的想法)

与此相反,如果你发现你所在的团队和项目的代码十分漂亮——编写整洁、设计良好、并且很优雅——你就很可能会格外注意不去把它弄脏。就和我们走进一个干净整洁的房间一样,你不会想成为第一个弄脏东西的人。

提示4:不要容忍破窗户。

3:石头汤与煮青蛙

这一节讲的是,创造与推动变化,警惕偏离你的图景。

在有些情况下,你或许确切的知道需要做什么,以及怎样去做。整个系统就在你眼前——你知道它是队的。

然而请求许可去处理这件事情时,你可能会发现,拖延、漠然、以及该死的官僚主义如此面目可憎地挡在你的前路上。与此同时,你可能还会遇到莫名其妙的委员会。而且,如果涉及到预算,每个人都会开始护卫他们自己的资源。

有时候,这叫做“启动杂役”。(这翻译的名字很古怪啊……)
这个时候,设计出你可以合理要求的东西,好好地开发它。一旦完成,就拿给其他人看,让他们大吃一惊。然后告诉他们说:“要是我们增加……可能会更好。”

让人们参与正在发生的成功显然要更容易(看看XX工厂的产品你就全懂了。)

接下来我们看那只被煮死的青蛙——和写书的人一样,我也没有做过这个。不过根据 奥克拉何马大学的动物学教授霍奇森的研究 ,青蛙还是会跳出来的,当然,那其实和文章要说的无关紧要。

“我们都看见过这样的症状。”项目慢慢地、不可改变地完全失去控制。

大多数软件灾难是从微不足道的小事情开始的——想想上一节《软件的熵》——大多数项目的拖延都是一天一天发生的。系统一个特性一个特性偏离规范,一个又一个补丁打到某段代码上……常常是小事情的积累破坏了士气和团队。

留心大图景,持续不断的观察周围发生的事,而不是你正在做的。

提示5:做变化的催化剂。

提示6:记住大图景。