• 2004-04-08

    可怕的习惯

    最近和一个同事一起在做一个模块。我的这个同事是后加入项目组,对整个系统不是很熟悉,为了加深对系统的理解,他主动要求独自承担这个模块的开发,对我的要求是时不时的帮一把。

    我们这里大多数人的开发习惯并不好。我希望通过这次的合作,能把我认为好的一些东西带给他。我并不是说自己的习惯就有多么好,我只是不想让他犯我以前翻过的错误。

    我们的合作从测试驱动开发开始。我以项目中实际需要的一个功能为例,给他演示了如何先写测试再写功能,把“红、绿、重构”的开发节奏告诉给他。

    第二天,我从CVS update出他接着我的演示继续编写的代码,虽然还有些不尽人意的地方,但比起我在项目中看到其它一些代码漂亮了许多,而且测试用例写得也不错。

    今天看他在编写测试用例,根据之前他问我的问题,我觉得他已经写完了功能代码。我问他为什么还要先写功能,后写测试,他的答案是习惯。

    我的这个同事为人十分谦虚,开发的过程中经常向我问一些问题,这倒充分满足了我好为人师的虚荣心。

    我并不想越俎代庖把每一个细节都替他做决定,那种代码会写得很痛苦,我希望给他留下自己发挥的空间。但在实际的开发过程,几乎每一步到了最后都是我在做决定。

    每次我的答案都是点到为止,剩下的问题只要自己稍微思考一下完全可以解决。每次也都是用不了多长时间,他就跑过来问我更细节的该如何来做。

    从前与他的一些交流里,类似的情况屡有发生。
    我给他解释了一个问题之后,向他推荐一本相关的书。之后不久,再与他交流,当我问起他是否读了那本书的时候,我得到的几乎总是“没有”。

    我是一个坚定交流支持者,但我确实不喜欢这种事事靠别人的态度。我的这位同事现在几乎养成了一种有问题就问的“好”习惯,而渐渐放弃了自己独立思考和学习的能力。

    习惯的力量多么可怕,更可怕的是不那么好的习惯。

  • 2004-04-07

    引导在哪里?

    Tag:向下走

    操作系统讲什么?快翻开你那本落满灰尘的操作系统教材看看。
    我的答案来自给了Linus开创世纪动力的《Operating Systems: Design and Implementation》(中文版《操作系统:设计与实现》)。除了前面的引言和后面的代码,书中讲到了进程、输入/输出系统、存储器管理、文件系统。

    不知道你有没有想过这样一个问题,操作系统如何开始自己的旅程。
    想当年,我兴致勃勃的准备以“好好学习,天天向上”的态度认认真真的学学操作系统。结果没有几天,我就被这个问题捆住了,久久不得解脱。

    当我通过各种渠道对操作系统的启动过程有了些许的认识时,另一个问题又冒了出来。既然启动是操作系统必不可少的一部分,那为什么各种操作系统教材对它却如此不屑。
    我能想到的答案只有平台差异。不是吗?大家有着各自的机器结构、有着各自的汇编。胆敢涉足此处,千差万别的细节足以让所谓的权威论断碰得头破血流。

    如果不是听说了Multiboot Specification,我一定会坚持认为自己得到就是标准答案。

    在Multiboot Specification出现之前,几乎每个OS都拥有自己的boot loader。也许你知道Boot loader要占据你可爱的硬盘上唯一的MBR(Master Boot Record,主引导扇区),如果每个OS要有自己的boot loader的话,那结果只能是只有一个操作系统可以启动。想像现在这样既装Linux又装Windows显然是不现实的。

    如果能够制订一套游戏规则,大家按照统一的方式启动,上面的问题也就迎刃而解了。在众多自由操作系统开发者的共同努力之下,Multiboot Specification应运而生。
    可能Multiboot Specification现在还只是在你眼前闪亮的新名词。如果我请出GRUB和LILO两个大名鼎鼎的名字,不知能否让你产生一丝亲切感。它们两个就是遵循Multiboot Specification的boot loader,Multiboot Specification的制订者之一就是GRUB的创始人Erich Boleyn。正是GRUB和LILO这样的boot loader的存在,我们才能过上Linux和Windows和平共处的生活。这样的boot loader替我们完成了本来要由我们自己的工作,对于我们的PC而言,这些工作可能加载内核、切换至保护模式、设置内核参数等等。

    回头看看我先前的问题。
    Multiboot Specification的出现,使得大家可以共享一个boot loader,于是boot loader变不再是操作系统的一部分了。
    这是由于这个原因,后来的开发者可以将更多的把精力集中在操作系统内核的开发上,至于那些繁琐的引导细节,我们就当它不存在吧!
    也许有人要说,不自己开发boot loader,我如何掌控全局?
    即便自己开发boot loader,加载MBR的过程依然由机器完成,我们不可能100%的掌控全局,支持不自己开发boot loader的另外一个理由就是众所周知的“不要重新发明轮子”。自己学习当然例外。

    这就是开放的力量,没有开放,累傻小子去吧!
    说到开放,不得不再说微软几句。尝试过Linux和Windows共存的朋友一定体会过重装Windows找不到Linux的悲惨。原因很简单,Windows的boot loader不符合Multiboot Specification,一旦它抢占了MBR这块高地,其它系统就只能忍气吞声了。
    微软霸道,无处不在!

  • 2004-04-06

    朋友和敌人

    微软和SUN和解了!
    我想起了《三国演义》中的那句名言,“天下大势,合久必分,分久必合”。昔日大打出手的敌人今天把手握到了一起。

    TheServerSide上有一幅非常有趣的漫画,因为Linux的威胁,Bill Gates和Scott McNealy走到了一起。不知道是作者是有先见之明,还是对此事早有耳闻,这一幕果然上演了。

    国共合作始于外族入侵,微软和SUN和解缘起Linux和IBM。

    微软对Linux的仇恨已经不是一天两天了,早在1998年,Eric Raymond披露的万圣节文档中,微软就已经把Linux划入了敌人的行列。如果说在桌面应用上Linux的威胁多少还是来自于微软的未雨绸缪,在服务器市场上,Linux对SUN的威胁却是实实在在的,更何况觊觎这块肥肉已久的微软了。

    IBM是无论何时都不能小觑的。没有它,我们恐怕没有与计算机亲密接触的机会。虽然它犯了一些险些送命的错误,但今天,我们看到的是一只翩翩起舞的大象。到我们最熟悉的developerWorks走一遭,除了IBM自家的东西,我们看到的是Linux、Java这样一个个熟悉的名字。显然,IBM已经找到了PC之外的另一条霸主之路:Linux+Java,微软不会涉足的市场。

    时至今日,谁也无法否认SUN推出的Java是难得的好东西,多少公司在这个微软不愿涉足的领域获得了成功。遗憾的是,Java的自家人只有眼见别人数钞票的份。同施乐著名的Palo Alto研究中心(PARC)全心奉献不求回报不同,SUN琢磨的更多的是怎么用Java赚钱。如此心态换得如此结果,SUN显然无法满足。IBM一次又一次的呼唤SUN开放Java,要知道,在一次调查中,Java的品牌已经超过SUN本身。面对蓝色巨人步步紧逼,SUN何去何从。
    微软推出.NET为的就是和Java抢市场,毕竟.NET还年轻,加之微软的霸道,于是太多人选择了站在Java一边。IBM PC当年的取胜法宝是什么?开放。开放了,大家都有的玩,于是跟进的人也就多了,虽然最终无法避免弱肉强食,至少大家都还可以在初始阶段趁乱捞一把。这就叫人多力量大。而其中,蓝色巨人扮演了重要的角色。

    面对着Linux和IBM两个强敌,本着“敌人的敌人是朋友”的原则,两个曾经的敌人走到了一起。

    CSDN上有网友评论,与微软合作多半没有好下场,SUN呢?起码刚开始不会,毕竟大敌当前。至于以后,谁知道呢!

  • 下面是dequator对《代码阅读》的评论:
    代码阅读,你真的有必要花费大量的心血,甚至还专门买本书吗?
    诚然,好的代码习惯会使整个项目得益,但是你从阅读代码的方法中是否真正能够得益?你所面临的代码,是否真能够像你所想象的那样去阅读?

    代码阅读,各人有各人的目的,《Code Reading》将代码阅读的动机整理了一番:
        将代码作为文献(Code as Literature)
        以代码为范例(Code as Exemplar)
        维护(Maintenance)
        演进(Evolution)
        重用(Reuse)
        审查(Inspections)

    由此可见,代码阅读既有主动为之,也有被动而行。但结果是一样的,阅读代码。
    出于自愿自觉的目的,我们并不会选择那些自己都觉得恶心的烂代码来读,但如果是工作需要呢?我们别无选择。

    再来说说我买书的目的。
    我是个书虫,不愿意错过任何的好书。而《Code Reading》这本书的价值,Productivity大奖应该是最好的一个诠释。当然,我购买的目的并非完全的盲目崇拜,更多的还是个人的需要。

    曾几何时,我企盼的是一步登天。不做好日常工作就能办好大事需要何等的天才。

    如果给自己一个评价的话,我觉得自己是个资质平庸的程序员。身边没有那种笑傲江湖的绝顶高手,更不用说那些高山仰止的大师级人物了。一个优秀的程序员会如何来做呢?我不知道,大多数时间,只有自己摸索。

    我对敏捷方法有着特别的好感,除了广告般的理由,我对更感兴趣的是其中一些个人实践方法,比如重构、比如测试驱动开发。有机会向世界级的程序员学习做事和思考的方式,这难道不是一种令人兴奋的事情吗?
    我所处的位置决定了敏捷方法对我而言,只能从一些个人实践开始。作为一个普通程序员,首先要扮演好自己的程序员角色,不是吗?

    对我而言,《Code Reading》这本书拥有着同样的意义。我不是没有自己阅读代码的方法。但运用自己的方法时,我发现自己很难对程序有一个很好的把握,常常是只见树木,不见森林。人为什么要学习,不就是为了少走一些弯路吗?我知道自己的方法一定算不上好方法,所以,我选择了这本书。
    通过向世界级程序员学习阅读源码的方法,我就可以省去了自己慢慢摸索的时间,何乐而不为!

  • 2004-04-03

    代码阅读

    我眼中的Spring》成功的作了一块引出玉的砖。这块玉是founder_chen的《Spring is comming》。
    谈及使用Spring可能遇到的一些问题时,founder_chen多次提及“代码阅读”。刚好今天买了拿走今年一个技术类图书Productivity大奖《Code Reading: The Open Source Perspective》(中文版《代码阅读方法与实践》),于是今天准备信口开一条关于代码阅读的河!

    Donald Knuth和Richard Stevens这两位大师级人物分别在在自己的旷世之作中点明了代码阅读对于程序员成长的重要意义。我想我是无论如何不可能再锦上添花了,于是我选择不再赘述。

    大多数程序员(包括我自己)在研究代码的时候,都希望准确的弄清楚来龙去脉。
    在我身处C世界的那个年代,从平铺直叙的C代码挖掘自己所需的一切是那么轻松。走进Java,知晓OO,遭遇设计模式,事情突然发生了改变。

    面向对象程序设计中一个很重要的方法就是面向接口编程,这种做法的好处无需我多言。在我沉浸于设计模式之美,程序设计之妙的同时,代码阅读的问题浮出了水面。
    从前阅读Tomcat的启动代码,配置文件加载完毕,然后Server启动,完了。Server是什么?一个接口。单从这段代码本身来说,它的功能我已经看明白了,但究竟这个instance的具体类型是什么,它是如何同Server联系到一起的,一头雾水。当然,后来我弄清楚了Tomcat利用commons digester完成系统配置的手法。
    这是接口编程的好处,完全不关心具体实现。但对于喜欢刨根问底的人来说,绝对是一种折磨。
    前不久,项目组的一个同事问我,为什么我的代码有这么多层,以致于无法一下子看清楚究竟实现了哪些功能。这么做当然有理由的,我还没有疯狂到平白无故增加层次的份上,但结果是无法清晰看透全部。

    眺望未来,如果AOP真能走入寻常百姓家,代码阅读的问题可能会再度加重。采用AOP思想的代码,将不同的逻辑进行了分离,造成的结果就是,仅仅阅读一部分代码根本无法获得全部的信息。

    难道我是在支持C的风格?我可没这么说。
    我和我的那位同事都是以C起家,所以,拿到一段代码的时候,情不自禁就会以C的那套思想往OO代码上套,毕竟抢扭的瓜不甜。入乡要随俗,阅读OO代码之前,我们需要了解一些OO代码的基本习惯,设计模式就是一种OO习俗。对于Java之类可以动态干许多事的语言,动态配置的手法也是基本功之一。
    阅读OO代码,和编写OO代码一样,也应该有个层次概念在那里,关注这段代码的时候就暂时不要考虑其它部分的所作所为,一切都混杂在一起,那就乱套了。
    最近和几位做C的同事交流,探讨的过程中,我发现他们总是喜欢问上面的结构的同时又要了解底层实现。我不是说多了解东西不好,而是说混杂在一起不好。不知道为什么有这个东西,管它怎么做干什么?
    仅仅“看”是看不出多少好处的,如果真行的话,我们的代码也就不必调试了。代码只有运行起来才具有生命力,就像猴毛在孙悟空身上只是毛,而吹了那口仙气它们就能活起来一样。所以,阅读代码之前,先让它编译运行起来,否则,我们只能看到猴毛。
    阅读代码讲求技巧的,这也是我购买《Code Reading: The Open Source Perspective》的原因。我希望通过这本书的阅读,学习别人一些的经验。

    平铺直叙的代码最清楚,所以,我们系统1.x版本中代码获得了“很清楚”的称号。一篇平铺直叙的文章能赢得你多少的好感?如果我以标准中国式教材的语言写这篇blog,你能坚持看到现在吗?
    同样,如果1.x真的那么好,我们也就没有开发2.0的必要了。
    用Java不见得写出的就是OO代码。现实情况是,许多人用Java写出的是C代码,结果是这些可能看着清楚的代码为后期的扩展维护带来不知道多少的麻烦。

    如果你经常在自己参与的项目中看到一个个长达数千行的函数,恭喜你!你在和一群勤劳的程序员一起工作。能把代码写得如此冗长,需要有非常好的耐心。
    对了,Perl语言的发明人Larry Wall说过,程序员的三大美德是:傲慢、急躁,以及懒惰(hubris,impatience and laziness)。