- 浏览: 489230 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
turingbooks:
本书预计下个月左右出版。
一本名副其实的 Web架构“圣经”——关于《HTTP权威指南》 -
superonion:
什么时候出版?
一本名副其实的 Web架构“圣经”——关于《HTTP权威指南》 -
yoyo837:
第11章是不是可以跳过不看哟...
《JavaScript高级程序设计》(第2版)上市 -
zsjg13:
对于“第二,技术要好,有开发经验,熟练掌握书中所涉及的相关技术 ...
为什么翻译类计算机图书的质量这样差 -
lzxz1234:
[b]方案五[/b]
选出您心目中理想的封面——《Spring揭秘》
代码要清晰地表达意图
—— 高效程序员的 45 个习惯之一
Hoare 谈软件设计
设计软件有两种方式。一种是设计得尽量简单,并且明显没有缺陷。另一种方式是设计得尽量复杂,并且没有明显的缺陷。
我们大概都见过不少难以理解和维护的代码,而且(最坏的是)还有错误。当开发人员们像一群旁观者见到 UFO 一样围在代码四周,同样也感到恐惧、困惑与无助时,这个代码的质量就可想而知了。如果没有人理解一段代码的工作方式,那这段代码还有什么用呢?
开发代码时,应该更注重可读性,而不是只图自己方便。代码被阅读的次数要远远超过被编写的次数,所以在编写的时候值得花点功夫让它读起来更加简单。实际上,从衡量标准上来看,代码清晰程度的优先级应该排在执行效率之前。
例如,如果默认参数或可选参数会影响代码可读性,使其更难以理解和调试,那最好明确地指明参数,而不是在以后让人觉得迷惑。
在改动代码以修复 bug 或者添加新功能时,应该有条不紊地进行。首先,应该理解代码做了什么,它是如何做的。接下来,搞清楚将要改变哪些部分,然后着手修改并进行测试。作为第 1 步的理解代码,往往是最难的。如果别人给你的代码很容易理解,接下来的工作就省心多了。要敬重这个黄金法则,你欠他们一份情,因此也要让你自己的代码简单、便于阅读。
明白地告诉阅读程序的人,代码都做了什么,这是让其便于理解的一种方式。让我们看一些例子。
coffeeShop.PlaceOrder(2);
通过阅读上面的代码,可以大致明白这是要在咖啡店中下一个订单。但是, 2 到底是什么意思?是意味着要两杯咖啡?要再加两次?还是杯子的大小?要想搞清楚,唯一的方式就是去看方法定义或者文档,因为这段代码没有做到清晰易懂。
所以我们不妨添加一些注释。
coffeeShop.PlaceOrder(2 /* large cup */);
现在看起来好一点了,但是注释有时候是用来对写得很差的代码进行补偿的(见第 105 页中习惯 26 : 用代码沟通 ) 。
Java 5 与 .NET 中有枚举值的概念,我们不妨使用一下。使用 C# ,我们可以定义一个名为 CoffeeCupSize 的枚举,如下所示。
public enum CoffeeCupSize
{
Small,
Medium,
Large
}
接下来就可以用它来下单要咖啡了。
coffeeShop.PlaceOrder(CoffeeCupSize.Largxe);
这段代码就很明白了,我们是要一个大杯 [① ] 的咖啡。
作为一个开发者,应该时常提醒自己是否有办法让写出的代码更容易理解。下面是另一个例子。
Line 1 public int compute(int val)
- {
- int result = val << 1;
- //... more code ...
5 return result;
- }
第 3 行中的位移操作符是用来干什么的?如果善于进行位运算,或者熟悉逻辑设计或汇编编程,就会明白我们所做的只是把 val 的值乘以 2 。
PIE 原则
所写的代码必须明确表达你的意图,而且必须富有表现力。这样可以让代码更易于被别人阅读和理解。代码不让人迷惑,也就减少了发生潜在错误的可能。代码要清晰地表达意图。
但对没有类似背景的人们来说,又会如何 —— 他们能明白吗?也许团队中有一些刚刚转行做开发、没有太多经验的成员。他们会挠头不已,直到把头发抓下来 ② ] 。代码执行效率也许很高,但是缺少明确的意图和表现力。
用位移做乘法,是在对代码进行不必要且危险的性能优化。 result=val*2 看起来更加清晰,也可以达到目的, 而且对于某种给定的编译器 来说 ,可能效率更高(积习难改,见第 34 页的习惯 7 )。不要表现得好像很聪明似的,要遵循 PIE 原则:代码要清晰地表达意图。
要是违反了 PIE 原则,造成的问题可就不只是代码可读性那么简单了 —— 它会影响到代码的正确性。下列代码是一个 C# 方法,试图同步对 CoffeeMaker 中 MakeCoffee() 方法进行调用。
Public void MakeCoffee()
{
lock(this)
{
// ... operation
}
}
这个方法的作者想设置一个临界区( critical section ) —— 任何时候最多只能有一个线程来执行 operation 中的代码。要达到这个目的,作者在 CoffeeMaker 实例中声明了一个锁。一个线程只有获得这个锁,才能执行这个方法。(在 Java 中,会使用 synchronized 而不是 lock ,不过想法是一样的。)
对于 Java 或 .NET 程序员来说,这样写顺理成章,但是其中有两个小问题。首先,锁的使用影响范围过大;其次,对一个全局可见的对象使用了锁。我们进一步来看看这两个问题。
假设 Coffeemaker 同时可以提供热水,因为有些人希望早上能够享用一点伯爵红茶。我想同步 GetWater() 方法,因此调用其中的 lock(this) 。这会同步任何在 CoffeeMaker 上使用 lock 的代码,也就意味着不能同时制作咖啡以及获取热水。这是开发者原本的意图吗?还是锁的影响范围太大了?通过阅读代码并不能明白这一点,使用代码的人也就迷惑不已了。
同时, MakeCoffee() 方法的实现在 CoffeeMaker 对象上声明了一个锁,而应用的其他部分都可以访问 CoffeeMaker 对象。如果在一个线程中锁定了 CoffeeMaker 对象实例,然后在另外一个线程中调用那个实例之上的 MakeCoffee() 方法呢?最好的状况也会执行效率很差,最坏的状况会带来死锁。
让我们在这段代码上应用 PIE 原则,通过修改让它变得更加明确吧。我们不希望同时有两个或更多的线程来执行 MakeCoffee() 方法。那为什么不能为这个目的创建一个对象并锁定它呢?
Private object makeCoffeeLock = new Object();
Public void MakeCoffee()
{
lock (makeCoffeeLock)
{
// ... operation
}
}
这段代码解决了上面的两个问题 —— 我们通过指定一个外部对象来进行同步操作,而且更加明确地表达了意图。
在编写代码时,应该使用语言特性来提升表现力。使用方法名来传达意向,对方法参数的命名要帮助读者理解背后的想法。异常传达的信息是哪些可能会出问题,以及如何进行防御式编程,要正确地使用和命名异常。好的编码规范可以让代码变得易于理解,同时减少不必要的注释和文档。
应该让自己或团队的其他任何人,可以读懂自己一年前写的代码,而且只读一遍就知道它的运行机制。
平衡的艺术
- 现在对你显而易见的事情,对别人可能并不显然,对于一年以后的你来说,也不一定显然。不妨将代码视作不知道会在未来何时打开的一个时间胶囊。
- 不要明日复明日。如果现在不做的话,以后你也不会做的。
- 有意图的编程并不是意味着创建更多的类或者类型。这不是进行过分抽象的理由。
- 使用符合当时情形的耦合。例如,通过散列表进行松耦合,这种方式适用于在实际状况中就是松耦合的组件。不要使用散列表存储紧密耦合的组件,因为这样没有明确表示出你的意图。
发表评论
-
《你不可不知的50个建筑学知识》之哥特式建筑
2013-08-16 09:49 766[+]查看原图 你不可不知的50个建筑学知识 一听到哥特 ... -
精益创业实战
2013-02-25 09:10 1068要想用好一套系统的方法,你必须先透彻地理解这套方法的“道”和 ... -
用编程工具实现数据可视化的几个选择
2012-11-29 11:55 820本文摘自《鲜活的数 ... -
程序员生活智慧集——卓越程序员密码
2012-10-26 09:57 618这本小书名叫《卓越程序员密码》,但大部分内容讲的不是具体的技 ... -
C语言与C++不得不说的那点事
2012-09-25 10:17 549说到C语言, ... -
不是告诉你新闻,而是告诉你怎样拥有远大前程
2012-09-06 09:56 946玛丽莎•梅耶尔(Marissa Mayer),曾是Google ... -
不能跳过的《程序员的职业素养(The Clean Coder)》中的一个章节
2012-08-27 15:08 430我猜,你之所以拿起这本书,因为你是程序员,“职业素养”这个 ... -
《iOS应用开发攻略》试读样章
2012-08-21 09:48 758内容简介: 本书涵盖了应用开发及构建优雅解决方案的必备 ... -
《30天自制操作系统》样章 多任务(1)——挑战任务切换(harib12a)
2012-08-02 14:04 1070多任务(1) --挑战任务 ... -
《30天自制操作系统》试读
2012-08-01 13:33 1205只需30天从零开始编写一个五脏俱全的图形操作系统,肯坚持,你一 ... -
60秒学脑科学常识——《科学美国人》专栏文集
2012-07-16 16:42 801------------------------------ ... -
程序员世界中的真金白银——Erlang的容错架构
2012-07-02 15:21 643在现实世界中容 ... -
大道至易——"刺秦与灭秦"个人、团队的前途与未来
2012-06-15 10:24 780张良是位儒生,手无 ... -
跨平台次世代游戏引擎Unity 3D
2012-06-15 10:06 10751.Unity简介 Unity是一款标准的商业游戏引擎 ... -
软件从业人员如何激发敏捷团队?
2012-06-14 17:26 614集中办公 怎样才能极大地提高团队的生产效率呢?答案 ... -
Android攻略之入门
2012-06-14 15:36 8731.Android简介 Android Dev ... -
步入正轨——以客户的视角审视软件交付
2012-06-14 11:26 613暂时忘记一会儿敏捷,假设你就是客户。资金和项目可都是你自 ... -
CSS的核心选择器
2012-06-14 10:32 723我们能真切地感觉到,选择器是CSS的核心部分。如果没有 ... -
使用和学习PHP有多难
2012-06-13 17:55 658PHP不是什么复杂高深的技术,但同时,你也不要期望能够在 ... -
消费者承担消费税真的吃亏了吗?
2012-06-13 17:16 590像小老鼠一样享受,才不管消费税呢 其实 ...
相关推荐
【优秀程序员的十个习惯】 1. 持续学习与跟进新技术:作为优秀程序员,保持对新知识的渴望至关重要。不断学习新的编程语言、框架和工具,关注行业动态,参与专业社区讨论,如CSDN、ITPUB、CHINAUNIX、digg.com等,...
本书名为《高效程序员的45个习惯 敏捷开发修炼之道》,由Venkat Subramaniam和Andy Hunt两位作者共同撰写。书中所提到的45个习惯,不仅涉及软件开发过程、编程和调试工作,还包括了开发者的个人态度、项目和团队管理...
以下是对标题和描述中提到的十个程序员习惯的详细解释: 1. **学无止境**:持续学习是优秀程序员的基石。随着技术的快速发展,必须不断关注新出现的语言、框架和编程实践,通过阅读专业文章、参加在线讨论和社区...
优秀程序员的45个习惯.rar ok good
优秀程序员的45个好习惯,看看总有好处的
高效程序员45个习惯,为你的个人拓展提供发展方向
优秀程序员的好习惯共2页.pdf.zip
高效程序员的45个习惯 英文完整版 V.Subramaniam, A.Hunt - Practices of an Agile Developer - Working in the Real World. 2006.pdf
标题中的“程序员的45个良好习惯”是一个旨在提升编程技能和团队协作效率的指南,描述强调了通过培养良好的习惯来提高自身编程水平,成为优秀的程序员。这些习惯涵盖了态度、学习、开发流程、用户、编程、调试和团队...
如何成为一个优秀的程序员:深入解析与实践指南 在IT行业,成为一名优秀的程序员是众多技术追求者梦寐以求的目标。在《如何成为一个优秀的程序员》一文中,作者罗伯特·L·里德(Robert L. Read)列出了多达一百条...
优秀程序员之路 Java开发经验及技巧大汇总优秀程序员之路 Java开发经验及技巧大汇总优秀程序员之路 Java开发经验及技巧大汇总优秀程序员之路 Java开发经验及技巧大汇总优秀程序员之路 Java开发经验及技巧大汇总优秀...
【Java优秀程序员编程规范】 Java编程规范是提升代码质量、可读性和维护性的关键,它指导程序员编写清晰、一致且易于理解的代码。遵循规范能够提高团队协作效率,减少后期维护的成本,也是专业程序员的基本素养。 ...
在《优秀程序员面试攻略》中,你可以找到以下几个关键知识点: 1. **基础理论**:这部分涵盖了计算机科学的基础概念,包括数据结构(如数组、链表、树、图等)、算法(排序、搜索等)、操作系统原理(进程、线程、...
### 程序员成长路线图:从入门到优秀 #### 一、程序员的梦想与现实 ##### 1.1 程序员的梦想——中国的比尔·盖茨 在IT行业中,很多程序员都有着一个共同的梦想——成为中国版的比尔·盖茨。这种梦想不仅仅是对...
程序员成长路线图 从入门到优秀