风之力科技
股票代码:781340
400-718-5885或13605745691
service@nwpit.com

技术资讯

25Mar2016
点击

《程序员修炼之道》读后感

  1.    注重实效的程序员的两个特点

  Care About Your Craft

  关心你的技艺

  编程技术就是程序员的手艺,你的程序就是你的艺术品。时刻关注自己的技艺,保持热情、保持好奇,争取做到富有专长而又多才多艺。

  关于程序员这个职业,引用 一段微博: 没哪个行业能像计算机行业这么活跃、刺激和有趣了。不仅是新兴工业革命的主力,又渗入到所有的行业中,干一辈子值了。 程序员首先是工程师,Professional,就跟律师,医生一样,给大家解决问题;但是另一面呢,又是艺术家,创造新奇好玩的东西。这样的职业做一辈子有什么问题?

  Think! About Your Work

  思考!你的工作

  虽然软件开发是工程学,但每个程序员并不是螺丝钉,而是活跃的造血细胞。我们要思考需求,推敲设计,展望愿景,打磨细节;我们要思考如果提高工作效率,如何成长;在对权威产生疑惑时,我们又要批判的思考而不茫然接受。除去工程技术以外, 逻辑思维能力才是程序员的核心竞争力,保持活跃、勤奋的思维。

  2.    我的源码让猫给吃了

  依据你的职业发展、你的项目和你每天的工作,为你自己和你的行为负责这样一种观念,是注重实效的哲学的一块基石。注重实效的程序员对他或她自己的职业生涯负责,并且不害怕承认无知或错误。这肯定并非是编程最令人愉悦的方面,但它肯定会发生——即使是在最好的项目中。尽管有彻底的测试、良好的文档以及足够的自动化,事情还是会出错。交付晚了,出现了未曾预见到的技术问题。

发生这样的事情,我们要设法尽可能职业地处理它们。这意味着诚实和坦率。我们可以为我们的能力自豪,但对于我们的缺点——还有我们的无知和我们的错误——我们必须诚实。

Provide Options, Don’t Make Lame Excuses

提供各种选择,不要找蹩脚的借口

这段对责任的描述并不只适用于程序员,但程序员可能会有自己的理解。面对历史遗留问题,是主动解决还是视而不见?问题发生时,是坦然担当还是去blame是猫吃了你的代码?

  Sign Your Work

  在你的作品上签名

过去时代的手艺人为能在他们的作品上签名而自豪。你也应该如此。“这是我编写的,我对自己的工作负责。”你的签名应该被视为质量的保证。当人们在一段代码上看到你的名字时,应该期望它是可靠的、用心编写的、测试过的和有文档的,一个真正的专业作品,由真正的专业人员编写。

  关于签名我们曾经在代码规范中推行过,在类的头文件中加入类似下面的注释。有签名在对自己是鞭策,其它工友也容易找到你咨询问题

  3.    软件的熵

熵是一个来自物理学的概念,指的是某个系统中的“无序”的总量。当软件中的无序增长时,程序员们称之为“软件腐烂”(software rot)。有许多因素可以促生软件腐烂。其中最重要的一个似乎是开发项目时的心理(或文化)。

  Don’t Live with Broken Windows

  不要容忍破窗户

不要留着程序中的“破窗户”不修,低劣的设计,临时的糟糕的方案等等。而往往我们又面对着诸多的“现实”,没时间重构,重构风险大没资源测试。可是我们会永远生活在“现实”里面,不可能有某一天万事具备、良辰吉日等着让你开始着手去修理这些“破窗户”。我们可以借助自动测试等手段来帮助我们降低风险。如果真的没办法立即修复,请一定要做到: 把发现的“破窗户”记入TODO List,并且定期Review它

  4.    重复的危害

  给予计算机两项自相矛盾的知识,是James T. Kirk舰长(出自Star Trek,“星际迷航”——译注)喜欢用来使四处劫掠的人工智能生命失效的方法。遗憾的是,同样的原则也能有效地使你的代码失效。

我们觉得,可靠地开发软件、并让我们的开发更易于理解和维护的惟一途径,是遵循我们称之为DRY的原则: 系统中的每一项知识都必须具有单一、无歧义、权威的表示。

  DRY – Don’t Repeat Yourself

  不要重复你自己

重复是代码中最坏的味道,大家可以回想一下,有多少Bug是因为重复代码漏改引起的,修改重复代码又浪费了多少时间。这么坏的东西一定要深恶痛绝!书中归纳了几种常见的重复类型:

强加的重复(imposed duplication)。开发者觉得他们无可选择——环境似乎要求重复。强加的重复细分为四类: 

l  信息的多种表示。

编写能编写代码的代码

l  代码中的文档。DRY法则告诉我们,要把低级的知识放在代码中,它属于那里;把注释保留给其他的高级说明。否则,我们就是在重复知识,而每一次改变都意味着既要改变代码,也要改变注释。注释将不可避免地变得过时,而不可信任的注释比完全没有注释更糟。逻辑清楚的代码自身就是最好的注释,除非是诡异的商业需求、不得已的临时解决方案抑或是在困难问题前屈服后使用的非常规方案。所以只有糟糕的代码才需要许多注释。

l  文档与代码。程序员们通常都有乖乖写文档的经历,但往往很难坚持,总有一天代码更新了,因为各种各样的理由,文档没有同步。所以在准备提供文档时请下定决心与做出承诺:保证要与代码进行同步的更新。

l  语言问题。就像C++的.h和.cpp文件,声明与实现就在重复着相同的内容。为了达到模块实现与接口分离的目的,就会出现这类重复。没有简单的技术手段避免,好在信息不一致编译期间会有错误。理想的做法是接口文件能通过实现文件自动生成。

无意的重复(inadvertent duplication)。开发者没有意识到他们在重复信息。

有时,重复来自设计中的错误。

   struct Line

{

     Point  start;

     Point  end;

     double length;

   };

  第一眼看上去,这个类似乎是合理的。线段显然有起点和终点,并总是有长度(即使长度为零)。但这里有重复。长度是由起点和终点决定的:改变其中一个,长度就会变化。最好是让长度成为计算字段。在以后的开发过程中,你可以因为性能原因而选择违反DRY原则。这经常会发生在你需要缓存数据,以避免重复昂贵的操作时。其诀窍是使影响局部化。对DRY原则的违反没有暴露给外界:只有类中的方法需要注意“保持行为良好”。

把DRY原则真正的消化,在设计时就会对这类无意的重复敏感,从源头上减少重复发生的可能。

无耐性的重复(impatient duplication)。开发者偷懒,他们重复,因为那样似乎更容易。

每个项目都有时间压力,你会受到诱惑去拷贝代码来实现相似的功能,总是没有时间去抽象出组件或者公用函数。如果你觉得受到诱惑,想一想古老的格言:“欲速则不达”,“磨刀不误砍柴功”。“想一想围绕着Y2K惨败的种种问题。其中许多问题是由开发者的懒惰造成的:他们没有参数化日期字段的尺寸,或是实现集中的日期服务库。”

开发者之间的重复(interdeveloper duplication)。同一团队(或不同团队)的几个人重复了同样的信息。

Make It Easy to Reuse

让复用变得容易

你所要做的是营造一种环境,在其中要找到并复用已有的东西,比自己编写更容易。如果不容易,大家就不会去复用。而如果不进行复用,你们就会有重复知识的风险。

  5.    时间耦合

  时间是软件架构的一个常常被忽视的方面,吸引我们的时间只是进度表上的时间。作为软件自身的一种设计要素,时间有两个方面对我们很重要:并发和次序。我们在编程时,通常并没有把这两个方面放在心上。当人们最初坐下来开始设计架构、或是编写程序时,事情往往是线性的,那是大多数人的思考方式——总是先做这个,然后再做那个。但这样思考会带来时间耦合:在时间上的耦合,方法A必须总在方法B之前调用,“嘀”必须在“嗒”之前发生。

程序在时序性上的依赖是客观存在的,我们需要做的是:1. 尽量减少不必要的时序依赖以提高并发能力;2. 保证真正需要的时序依赖不存在被破坏的可能。人们通常会通过文档说明时序的依赖,就像MSDN中会写明使用COM之前必须调用CoInitialize()一样。但实际开发中时序上依赖通常会成为潜规则,只有当初开发的人自己知道,对后面维护的人来讲这就会是定时炸弹。 对不得已的时序依赖一定要写入文档或者标明注释。

  6.    正交性

  正交性”是从几何学中借来的术语。如果两条直线相交成直角,它们就是正交的。在计算技术中,该术语用于表示某种不相依赖性或是解耦性。如果两个或更多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的。

  

  消除无关事物之间的影响

如果你编写正交的系统,你得到两个主要好处:提高生产率与降低风险。贯彻正交性原则可以促进组件化与复用;可以有效缩小错误代码影响的范围;更有利于单元测试。你也可以对项目团队的正交性进行衡量:只要看一看,在讨论每个所需改动时需要涉及多少人。人数越多,团队的正交性就越差。显然,正交的团队效率也更高(尽管如此,我们也鼓励子团队不断地相互交流)。

正交性与DRY原则紧密相关。运用DRY原则,你是在寻求使系统中的重复降至最小;运用正交性原则,你可降低系统的各组件间的相互依赖。这样说也许有点笨拙,但如果你紧密结合DRY原则、运用正交性原则,你将会发现你开发的系统会变得更为灵活、更易于理解、并且更易于调试、测试和维护。

这本书花了很大的篇幅讲述 DRY原则和 正交性(也就是解耦),也提供了很多有实践意义的方法。回想一下设计模式,很多模式也正是为了解决这两个问题。这两个原则大家一定都耳熟能详,这里引用序言书评中的一句话:“ 能不能让正确的原则指导正确的行为本身,其实就是区分是否是高手的一个显著标志”。知道很容易,尝试在日常开发中去实践从而真正内化,最终达到运用自如。

我们认为违反这两个原则的设计和实现就是“破窗户“。在确保自己不产生的同时,也要留意现有代码,发现问题抛出来,大家一起讨论如何优化何时优化(优化有风险,重构需谨慎)。最终要么消灭,要么确保一定被记录在案(把破窗口先用木板暂时封起来)。千万不要看到糟糕的代码皱皱眉、抱怨两句就结束了,把它放到TODO List里面!

  7.    重构

  随着程序的演化,我们有必要重新思考早先的决策,并重写部分代码。这一过程非常自然。代码需要演化;它不是静态的事物。

无论代码具有下面的哪些特征,你都应该考虑重构代码:重复;非正交的设计;过时的知识(最典型的就是需求已经下线、方案已经改变,但过时代码却还残留甚至运行);性能问题。

人们通常用肿瘤来比喻重构的必要性,在现实的时间压力面前,需要做出正确的选择。追踪需要重构的事物。如果你不能立刻重构某样东西,就一定要把它列入计划。确保受到影响的代码使用者知道该代码计划要重构,以及这可能会怎样影响他们。

Refactor Early,RefactorOften

早重构,常重构

    书中给出了几点重构实践上的指导:

1.    不要试图在重构的同时增加功能。

2.    在开始重构前,确保你拥有良好的测试。

3.    采取短小,深思熟虑的步骤。把整体重构工作认真的分解为独立、轻量的几个步骤,每个步骤完成都可以进行测试,这将有助于快速定位问题。

  8.    无处不在的自动化

  让计算机去做重复、庸常的事情——它会做得比我们更好。我们有更重要、更困难的事情要做。

  Don’t Use Manual Procedures

  不要使用手工流程

  自动化为我们带来两个显而易见的好处:避免重复劳动提高效率;保持可靠的一致性与可重复性,排除人工作操作可能产生的错误。可以自动化的项目包括但不限于:项目编译,回归测试,构建与发布,通过单一数据源生成数据的其它表示。

    “鞋匠的孩子没鞋穿”。我们是程序员,是否在的日常工作中经常制作自动化工具?至少掌握一门高级脚本语言用于快速开发自制工具。

  9.    可撤销性

  我们让本书的许多话题相互配合,以制作灵活、有适应能力的软件。通过遵循它们的建议——特别是DRY原则、解耦以及元数据的使用——我们不必做出许多关键的、不可逆转的决策。这是一件好事情,因为我们并非总能在一开始就做出最好的决策。我们采用了某种技术,却发现我们雇不到足够的具有必需技能的人。我们刚刚选定某个第三方供应商,他们就被竞争者收购了。与我们开发软件的速度相比,需求、用户以及硬件变得更快。

  不存在最终决策

  没有人知道未来会悄怎样,尤其是我们!所以要让你的代码学会“摇滚”:可以“摇”就“摇”,必须“滚”就“滚”。

  需求变更,是永恒的话题。变更往往又总是不可避免、总是迫在眉睫。在设计与编码时尽可能的注意并应用以上几个原则,会让我们面对变化从容不迫,甚至可以达到“中流换马(change horses in midstream)”的灵活性。

  10. 元程序设计

细节会弄乱我们整洁的代码——特别是如果它们经常变化。每当我们必须去改动代码,以适应商业逻辑、法律或管理人员个人一时的口味的某种变化时,我们都有破坏系统或引入新bug的危险。所以我们说“把细节赶出去!”把它们赶出代码。当我们在与它作斗争时,我们可以让我们的代码变得高度可配置和“柔软”——就就是,容易适应变化。

要用元数据(metadata)描述应用的配置选项:调谐参数、用户偏好、安装目录等等。元数据是数据的数据,最为常见的例子可能是数据库schema或数据词典。

  Configure,Don’t Integrate

  要配置,不要集成

  但我们不只是想把元数据用于简单的偏好。我们想要尽可能多地通过元数据配置和驱动应用:为一般情况编写程序,把具体情况放在别处——在编译的代码库之外。

Put Abstractions in Code,Details in Metadata

将抽象放进代码,细节放进元数。

  “与其做个半成品,不好做好半个产品”,因为, 一个半成品会让人绝望,而半个好产品会让人有所期望,这就是其中的不同。