Chinaunix首页 | 论坛 | 博客
  • 博客访问: 22177
  • 博文数量: 22
  • 博客积分: 960
  • 博客等级: 准尉
  • 技术积分: 260
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-06 12:49
文章分类
文章存档

2011年(1)

2009年(21)

我的朋友
最近访客

分类: IT职场

2009-10-06 13:18:10

最近读了《卓有成效的程序员》,感觉收获颇大。这是一本写给程序员的难得的好书。书中大都是一些浅显的道理,但作者将这些东西加以收集、归纳、总结,并最终成书。作者为了收集各种提高效率的工具和方法,东奔西走,可谓费了一番苦心。

我觉得此书第一部分总结的一些法则非常好,我提取了一下:

法则:

1.加速法则

关注本质,而非形式

一个应用程序列表的有用程度与它的长度成反比

程序员的很多时间都浪费在找东西上

华而不实的东西中看不中用

键盘输入总比导航快

首选键盘而非鼠标

地址栏是Windows资源管理器界面中最高效的部分

花点时间来学习你手边的所有隐藏的快捷键

环境切换会消耗时间

成批复制粘贴要比反复多次复制粘贴快

忘记历史就意味着你得再输入一遍

嵌入图形化工具的命令提示符让你鱼与熊掌兼得

在上下文中学习IDE快捷键,而不要去背长长的列表

当你第二次输入一个复杂结构时,将它做成模板

如果要对多行文本做同样的操作,就应该找出其中的模式,并把它记录为一个宏

不要总是重复输入相同的命令

每天花一点点时间来使每一天都更高效

2.专注法则

精力越集中,思维越缜密

排除干扰:隔离策略,关掉不需要的提示,创造安静时间

草堆越大,从中找到一根针就越难

不要问文件树,要搜索

使用多显示器

虚拟桌面可以让原本杂乱无章的一大堆窗口变得整洁

3.自动化法则

不要重新发明轮子

用Selenium浏览网页

不要浪费时间动手去做可以被自动化的事情

用Windows Power Shell替代批处理文件

驯服Subversion命令行

以创造性的方式解决问题,有助于在将来解决类似的问题

是否应该自动化的关键在于投资回报率和缓解风险

研究性的工作应该放在时间盒里做

别给牦牛剪毛

4.规范性法则

    对于任何你不自己去构建的东西,只在版本控制中保存一份副本

使用标准的构建服务器

通过复制粘贴来复用是邪恶的,不论你复制粘贴的是什么

利用虚拟平台使项目依赖标准化

不要让对象 - 关系映射工具(O/R映射器)违反规范原则

通过扩展。开放类(open class),或者部分类(partial class) 来为生成的代码增加行为

始终保持代码和数据结构的同步

过时的文档比没有文档更糟,因为它会主动误导你

任何需要费劲创造的东西,都让它的创造者欲罢不能

白板 + 数码相机强过任何CASE工具

尽量生成所有技术文档

重复是软件开发中最大的阻力

工具:

书中,还提到了大量的提高效率的工具,都是非常不错的。相信很多人都有自己的一个列表,下面是我电脑中必不可少的几款软件:

1. FireFox 及其各类插件

2. Launchy启动加速器

3. Total Commander

4. ClipX多重剪切板

5. EmEditor文本编辑器

6. Vistual Studio的VA插件

7. Search And Replace

8. Everything

9. Miranda IM

10. ....

感触:

1. 愤怒的猴子

在书中的第二部分,提到了很多实践相关的内容。让我感触最深的是“愤怒的猴子”的故事:

早在20世纪60年代(那时候科学家们可以做任何疯狂的事情),行为科学家们进行了一项实验。他们把五只猴子和一架活梯放在一间屋子里,并在天花板上挂了一串香蕉。这些猴子很快就想到它们可以爬上梯子去吃香蕉,但每当它们靠近活梯的时候,科学家们就用冰水浸满整个屋子。我想你能猜到会发生什么:一群愤怒的猴子。很快,再没有一只猴子会去靠近那个梯子了。

之后,科学家们将其中一只猴子替换成另一只没有忍受过冰水折磨的新猴子。这只新猴子所做的第一件事就是直奔那架梯子,但当它这么做时其他所有猴子都痛打它。它不明白为什么,但很快就学乖了:不要去靠近那架梯子。科学家们逐渐将最初的那些猴子都替换成新猴子,直到这群猴子中谁都没有被水浸泡过,然而它们还是会去攻击任何靠近梯子的猴子。

这说明了什么?软件项目中许多惯例之所以存在,就因为”我们一直是那样做的“。换句话说,是因为愤怒的猴子。

我们小组在制定C++相关的代码规范时就遇到过无数类似的问题。比如,在制定变量的命名规范时,我们针对是否采用匈牙利命名法争论了很久。有的人认为, 几乎以前看到的所有C++代码都采用了匈牙利命名法,甚至,微软定义的所有API都使用了此类命名法。刚开始,我也是有同样的疑惑。

后来,我们经过仔细分析C++匈牙利命名法由来,渐渐感觉我们就是那些愤怒的猴子,盲目跟从前人的方式,缺乏打破传统的勇气。C++有着其特殊的历史原因,很多标准一直沉淀下来并很少改变。我们再看看后来新生的那些编程语言,C#, Python…… 都抛弃了匈牙利命名法,同时再看看现在C++前沿的C++ 0x以及现在出版的一些书中,也渐渐放弃了对匈牙利命名法的使用。因为类型的意义在对象模型中越来越弱化。因此,最后我们放弃了匈牙利命名法这个老古董。

2. 敏捷开发

这本书带有强烈的ThoughtWorks色彩,敏捷的思想贯穿全书,包括测试驱动设计,白板,结对编程。这也让我对敏捷产生了更加强烈的兴趣。 其中有一段测试驱动开发TDD的一段故事:

记得第一次和一些已经习惯于单元测试的开发人员一起动手开始修改代码时,我也是非常紧张,因为大量的修改往往会破坏很多东西,但他们看起来丝毫没有犹豫。逐渐地,我也放下心来,因为我慢慢地认识到:有了测试的保证,完全可以放心大胆地去修改代码。

3. 有趣的故事

书中还有一些有趣的故事,比如作者的一个朋友在和别人结对编程时,为了养成同伴使用快捷键的习惯,每当同伴未使用快捷键时,他都会要求将操作撤销,然后要求使用快捷键再重复操作3次。然后,在其凶狠的眼神中,同伴很快掌握了快捷键。

总结:

这本书很薄,蕴藏的道理却不少,相信每个读过它的人都会从中收获。读过之后,我们不应该局限于书中提到的某些小技巧, 或是书中某一个细节,毕竟,提供效率的方法有很多很多,法则也有很多很多,一本书很难将其穷举完。我们应该从书中吸取其思想,并在实际工作和学习中不断总结,做一个真正的“卓有成效的程序员”!

正则表达式 - 你必须掌握的
很多人不愿意修改公共代码,因为公共代码一修改,将可能影响到别的工程代码,必须同时修改大量的别的工程代码。对于简单的修改,比如函数名修改,使用简单的批量查找替换就可以完成。但如果遇到更加复杂的情况,很多人手足无措,只能一个一个的手工修改。《卓有成效的程序员》里有这么一个故事:

“事情发生在一个项目中,那个项目已使用了1000个EJB(Enterprise Java Bean),当时决定所有的非EJB方法(就是说除了EJB托管的回调方法之外的所有方法)都需要一个额外的参数。原本估计需要一个人花6天来手工完成。但一个熟悉正则表达式的开发人员,用他信赖的编辑器(Emacs)仅使用两个小时就完成了所有的替换。也就是那一天开始,我决定好好学习正则表达式。”

可以想象一下,一个原本6天的手工工作量, 最后只需要两小时。(1小时58分钟建立正确的语法,然后不足两分钟时间去执行。)

一、学习正则表达式

曾有人总结了程序员的七种武器,其中就有“正则表达式”。如果你现在对正则表达式还是一知半解,好好的静下心来,用心花上2个小时,仔细学习和研读一下正则表达式语法规则,是绝对值得的。要学习正则表达式,资源非常多。 如果想要系统的学习,建议看《精通正则表达式》等书。如果你想要快速入门,我推荐一下园里最近很火的Jimmy Zhang曾经写过的一个简易教程:

学习资源:


http://www.cnblogs.com/jimmyzhang/archive/2007/10/24/936151.html (花上1-2个小时仔细学习,然后反复实践,能够很快上手)

正则表达式工具:


我首推RegexBuddy了。下面这个地址里有RegexBuddy3.2.1完整版的下载地址(如果你仔细浏览这个网站,会发现此人是一个正则表达式狂热分子):

http://iregex.org/blog/regexbuddy321.html

二、实例
接下来,我们回到开头讲到的修改公共库的问题。我来举一个的例子,我们设计了一个Game类,提供Start实例方法如下:


public class Game
{
    public void Start(int totalTime, string gameName)
    {
        //
    }
}

然后,该方法被大量其他代码使用。直到某一天,我们决定将Start方法的两个参数顺序对换,因为gameName作为第一个参数看起来更加顺眼。。。然后,我们观察了一些使用到Game类的代码,发现有非常多的地方使用到了该代码,但几乎的代码都使用了类似如下的方法调用Start方法:


Game game = new Game();
game.Start(1, "NancyTetris");

Game myGame = new Game();
int totalTime = 10;
string gameName = "NancyGLine";
myGame.Start(totalTime, gameName);

当然,实际情况下,调用该方法的代码千奇百怪,对于某些复杂情况,想要通过一个正则表达式达到完美的批量替换确实很难。这里,我就将问题简化一下,只是给大家提供一个思路。我假设所有调用该方法的代码都使用了如上的方法进行调用。(为了简化正则表达式,易理解,我假设调用代码都遵循代码规范,不会去多出一些多余的空格,也不胡乱换行。)

那么,一个怎样的正则表达式能够将上面的一段代码中的Game实例的Start方法的两个参数调换呢?


答案:

搜索:Game (\w+) = new Game\(\);([\W\w]*?)\1.Start\(([\w\"]+), ([\w\"]+)\);

替换:Game $1 = new Game();$2\1.Start($4, $3);

这个例子很常见,也很有用,如果你还不会,请耐心花上2个小时学习,然后解决它!


在实际的批量搜索替换过程中,你肯定会遇到各种各样的麻烦,因为你会发现,调用它的代码风格千差万别,比如上面的例子,可能有人将Game实例做为一个参数传递到了另外一个函数(甚至这个函数在另外一个文件里),如:


public void Do()
{
    Game game = new Game();
    Foo(game);
}

// Foo方法可能在另外一个文件里
public void Foo(Game game)
{
    game.Start(1, "NancyTetris");
}

甚至,某些人不符合代码规范的怪异写法也会让你非常头疼。你会发现一个正则表达式已经不能一次性做完所有事情,这时,你也许需要编写一定的脚本进行更加复杂的处理,假如正则表达式这把武器在你的手上运用自如,你是否会感觉一切都变得那么简单呢?如果你有更多实际的正则表达式批量替换的经验,欢迎分享!

阅读(257) | 评论(0) | 转发(0) |
0

上一篇:JAVA类库手册

下一篇:你会用自己的QQ吗?

给主人留下些什么吧!~~