• 2010-02-10

    孤独的人是可耻的

    今天,偶然,又一次听到这首歌,才发现已经匆匆数年。

    那些曾经的事,曾经的人,曾经的回忆,都慢慢的逝去。

    Tag:
  • 2010-01-31

    做正确的事

    做正确的事是TaoWen最经常说的话,然而真正去探究“什么才是正确的事”时,却是无比艰难。有些事是我们不知道的,有些事是我们无能为力的。不知道什么才是正确的事是极其不爽的,更不爽的是你知道了,却无法实现;最最不爽的是,你认为你找到了,也做了,最后却发现,你错了。

    Tag:
  • 2009-09-19

    Git & Hg

    这几天看了一下Git和Hg,补习了一下DSCM,感觉比SVN确实好很多。

    现在分布式开发团队很多,有时SVN服务器在国外,访问速度非常的慢。如果还要通过VPN连接,那简直就是遭受非人道的痛苦。在上一个项目中,就曾经用了一上午的时间来merge,之中真正解决conflict的时间非常少,大部分都花在了download代码了。因为不管是log还是diff都需要从服务器端下载数据。DSCM通过本地Repository可以解决这个问题,只需要将服务器上新提交的代码down下来,就可以在本地使用log和diff了。而且也避免了出国网断掉时,无法提交的问题。

    相比之下,我觉得Git更好用一些,Hg稍微有点复杂。不过本质上还是一样的东西,工作流程上有些不同,喜欢哪个完全看个人的喜好了。

    Tag:
  • 2009-09-15

    命名与抽象

    好的名字总是能为代码的可读性做出重大贡献,而这种贡献是通过对事物进行抽象实现的。

    想想一下我们平常说话时所用的语言,比如说“我家的狗跑的很快”,“家”、“狗”和“跑”都是抽象,它们分别代表了不同的含义,如果不适用这几个抽象的词汇,而是直接说它后面所代表的含义,恐怕几十句话都说不完。不信的话,你可以试试定义一下什么是狗,什么是跑,保证不是那么容易的事。

    抽象可以说是软件设计和开发中的核心概念,对变量、方法、类、接口、包等元素的命名,都包含了抽象过程。例如方法,方法的名字应等价于方法内部所有代码的功能,也就是说方法的名字是方法内代码功能的抽象。于是,不管是在交流还是记忆上,我们都可以使用方法名来指代它内部的功能。

    由于人的记忆力和理解能力都是有限的,据研究称,人最多之能同时处理7个左右的事物。因此对于复杂的软件系统,抽象就成为让人能够理解的重要手段。在代码量较小的系统中,可能抽象也比较少,理解起来比较容易,变量、方法和类基本就能处理了;而在大一些的系统中,由于抽象较多,因此需要更多的抽象层次,使得在每一个抽象层次上都能有比较少的抽象概念,以利于理解,于是出现了诸如分层、子系统、组件、库等等。同时在类和方法内部,也会有分层次的抽象,继承就是类的一个抽象层次关系,而方法之中调用其它方法,也是抽象层次的一种表现。

    例如,狗这个类可以有很多不同子类,每一种代表不同品种的狗。从上往下看,子类是父类的泛化,是在父类上添加更多的细节;而从下往上看,父类则是子类的抽象,集合了更多子类的相同之处。在类的层次结构中,每一级的父类都会包含更多的抽象和更少的细节。因此往往父类比子类更能表达这个层次结构的核心概念,也就应该更谨慎的选择一个好的名字,来表达这种核心概念。同时子类的名字应该能够体现它的子类的共性,同时还应能够区分与其它同级子类的不同。

    而在方法中,我们有一种使方法更具可读性的方式,就是让方法中的每一行代码都处于相同的抽象级别。例如,“我家的那只会叫的哺乳类四腿……动物跑的很快”这句话就很难理解,因为你的思维需要在不同的抽象级别上跳来跳去,“家”和“跑”都是可以马上理解的概念,而“会叫的哺乳类四腿……动物”则是需要思考一下才能理解的。因此比较简单的做法就是将这个细节抽象称一个名字“狗”,将之提取出来,形成另一个概念(也就是方法)。于是,系统中的方法本身也就有了不同的抽象层次,有些关注与调用语言和平台的API来实现某些操作,有些则会调用这些方法实现更高层次的逻辑。在面向过程的设计中,最后的结果就是main函数,而在OO设计中,可能是某个类的public方法。

    命名好坏对可读性的影响,实际上是抽象方式对人的思维方式造成的影响。如果你找不到一个好的名字,通常就意味着你对问题的抽象是不恰当的,隐含的意思就是你对问题的理解不够深入或者理解错误。

     

     

    Tag:
  • 2009-09-14

    代码习惯

    前天在AgileChina2009上听了Fred George的演讲,他说他以前拿自己的代码给Kent Beck看,结果Kent说这代码很垃圾,你去看看我写的Smalltalk best practice patterns吧。然后Fred George就看了这本书并且完全按照书上的要求去做,5年后当他再给Kent看自己的代码时,Kent说很漂亮的代码。

    考虑到Fred比Kent要老,可以看出Fred是非常虚心的,听了Kent的评价不仅没有生气,而且还完全听从了建议。当然这也可能是Kent太出名的缘故,若是我说他的代码不好,或许他就不会这样做了。

    这让我联想到有一次和8x一起面试,8x的手工重构让我很是惊讶。虽然我也看过《重构》,虽然我平时也重构,但是不论从步伐还是安全性上,都相差深远。我读《重构》的时候对如此小步伐的改变是不太赞同的,因为效率比较低。我认为书中之所以把条目分的很详细,每个条目的步骤很小很谨慎,完全是为了可以让支持重构的工具得以实现,对于人来说,保持这样小的步骤太难了,不管是从记忆还是从操作的角度来看。然而8x的表现让我改变了看法,不仅速度并不慢,而且安全性非常的高。回想起我的重构经常出现改错以后没法返回的问题,不禁感叹--差距啊。

    经常在国内的论坛上看到各种讨论设计、架构的帖子,然而每每show代码的时候却发现一塌糊涂。当然他们自己不觉得,可是我觉得很不好。最近Kent Beck和Robert C.Martin出的两本书《Implementation Patterns》和《Clean Code》都是讨论一些很细节的东西的,如何命名、方法应该要多长、注释怎么写、格式怎么排等等,这些东西早在《The Element of Programming Style》中其实都有对应的东西,只不过语言不同了,细节方面也不同。然而为何这么多年来,一直有人不停的写本质上相同的东西呢?我觉得还是大家不重视,没有养成良好的习惯,自然就需要有人去写这些东西,反反复复的提醒大家。

    这里再一次很惭愧的说,我没有好好去读,也没有按照书中的东西认真去做,总是以为大概了解个概念,知道怎么回事,然后差不多做到了就行了。然而现在想来,却完全不是那么回事。记得XP中有很多非常“极限”的要求,都是“一定”要如何如何,可实际上很多人都不以为然,认为太过激进,实际操作不现实或者不必要,因此在实施的时候,做了一些妥协和变通,最后失败了还说XP不好。当然XP不可能是包治百病的灵丹,在某些情况下确实也不应该用它,但是很多人明明可以从中获益,却因为没有领悟到其中的精髓而早早放弃。

    比如说TDD,看起来与一般的单元测试的不同只是把写测试的工作放在了写代码之前,而Pair Programming也不过就是两个人坐在一起写程序罢了。然而在实际应用中,却会发现TDD并不是那么简单,它带来的好处是你在使用之前完全想不到的,甚至很多都和Test是无关的。而Pair也不简单的就是两个人干一份工,如何根据技能的不同组合Pair,两人如何分工都有很大的讲究,甚至一般的对于Pair目的的理解可能也是错误的。因此要想证明一件东西能不能起作用,首先要完全按照他要求的方式去做,等到你真的把该遇到的问题都遇到了,你才能真正知道它是什么,能做什么,不能做什么,最后才知道它到底能解决什么问题,不能解决什么问题。

    在说回到代码习惯的问题,软件开发中包含太多东西了,需求的、设计的、测试的、管理的、文化的、心里的、沟通的……要想掌握这么多东西是很大的挑战。如何将一件事记住而不忘掉,最好的办法就是将之变成习惯,就像呼吸一样自然,不需要刻意去想就能做到。良好的代码习惯是一个开发人员最基本的技能,使之成为习惯,会获益很多。

    决定在看一遍《重构》和《实现模式》并完全按照其中的要求去做,争取也能在5年之内将之养成习惯。

    Tag:
  • 2009-01-22

    To be foolish

    最近在做一个开源的项目,是从另一个java的开源项目做porting。当我读代码的时候,就觉得这个项目的代码不怎么样。庞大的类,难懂的代码,基类居然还有对派生类的依赖关系。因此在做了一段时间的translation后,我忍不住从头开始阅读spec,根据自己的理解和从java版本的代码里得到的信息,从头开始设计类结构,从头开始写c#的代码。然而随着代码越来越多,前进的脚步也越来越困难。当初看起来不舒服的地方,到最后却发现我不得不做同样的事才能前进。

    回想起上一个项目中,有一个同事是从项目中期加入的,当时他看代码的时候就是看那都不顺眼。命名不清晰,结构不优美等等。于是他花了大量的时间用在改名字,改结构却没有做出任何的功能。

    在项目中,我们都想追求完美,然而受到种种因素的制约,我们无法达到。有时是因为时间紧迫,有时是因为技术限制。如果你在读别人的代码的时候感觉有不顺眼的地方,千万不要着急修改,一定要先了解一下为什么会出现这些问题。要知道,你并不比别人聪明多少,你能看到的,别人也能看到,你能想到的,别人也能想到。一定要等到对代码和项目的历史有了足够的了解之后,在计划如何修改。

    现在,我又会过头来耐心的做着translation的工作,不管做的时候碰到很烂的命名,混乱的结构,还是难懂的代码,我一率忍住,老老实实的做苦力。这样当我做完translation的时候,首先我能得到一个可以工作的软件,其次我对系统的理解将大大加深,然后我再进行重构的工作就要简单安全多了。

    To be foolish, don't be too smart!

    Tag:
  • 2008-12-24

    代码与健康

    任何一个有经验的程序员都知道,保持良好的架构和可读性是保持代码健康长寿的秘诀之一,然而对于身体的健康,好像没有多少人真正的注意过,很多人都受到颈椎疾病的困扰。

    现在很多的键盘和鼠标的说明书上都会附带健康使用指南,告诉你怎么坐着才健康。简单地说就是,椅子不要太高,脚要能着地;椅子的靠背应该使你保持身体直立,并给与背部一定的支撑;胸部离桌子要一拳远;显示器略低于眼睛,使视线略向下倾斜;双手自然放在键盘上。

    不过在我看来,这简直就不可能实现。在自己家里或许你可以配置一套符合这个指南的桌椅,但是在公司几乎不可能做到,办公桌椅都是统一购买的,可能有些人感觉很舒适,而另一些人则感觉很别扭。

    我的习惯与这些指南完全不同,而且这些年也从来没出过什么问题。我通常会把椅子放到最低,如果椅背可以向后活动的话,一定要让它活动;然后半躺在椅子里,调整姿势直到感觉腰部背部和颈部获得足够的支撑,不需要额外使劲来获得良好的视野;椅子离桌子越近越好,这样我可以不费力的找到键盘和鼠标;如果机箱正好放在桌子下面,再把腿放在机箱上;这样身体的各个部分都获得了足够的支撑,双腿不会因为长时间坐着而感到麻木,脖子不会因为长时间低头而酸疼,双手自然向下弯曲的,不会给手腕太大的压力。这样的坐姿虽然有点难看,不过我觉得是很舒服的,唯一需要注意的是,不要坐在椅子边上,要不然屁股会很受罪的。

    “大哥”和我一起pair的时候说我应该再搞个铁架子,把显示器挂在上面,这样我就可以真正的躺下写代码了,我觉这这事很靠谱,如果那天有条件,我一定要试一试。

    Tag:健康
  • 2008-12-18

    Pair Programming

    掐指一算,到TW已经快5个月了, 每天都是结对编程,已经感觉很习惯了,以至于自己一个人写代码的时候感觉没个人一起聊天很别扭,这里说说自己的感受。

    首先说说好的地方:
    可以使你更专注,两个人一起写代码,想开个小差都不行,眼睛要跟上,思路也要跟上。直接的好处就是生产率提高了。

    可以不那么枯燥,写代码写烦了可以聊聊天,休息休息,没思路的时候可以让另一个人思考 :p。

    解决问题更有效,一个人的想法难免有偏颇,当一个问题拿不定注意的时候,两个人之间的讨论往往能互相启发,从而找到更好的解决办法。有的时候我们甚至会花大半天的时间用来讨论一个问题,什么代码也不写。这样看起来好像很没有效率,很浪费时间。但是它可以使两个人想法统一,在真正写代码的时候思路会更清晰,写的也会快很多,在涉及到系统架构的时候尤其必要。

    有利于知识传播,最有效的学习方式就是一对一的教授,结对编程恰恰就是一个一对一的过程,你可以从别人身上学到不同的思考方式和技术,别人也同样可以从你这里获益。我觉的就凭这一点好处,就应该尝试一下结对编程。

    当然有好的就会有不好的地方,不好的就一个字:累。每天下班都感觉疲惫,主要是高强度的思考和交流使得“嘴”和“心”都很累,要是这一天说的还都是英语,就别提多累了。不过随着对结对编程的熟悉与适应,加上经常的短暂休息作为调节,累的感觉会慢慢消失,你就可以好好的享受结对编程了。

    结对编程可能会给你好的体验,但是也可能会让你觉得很困扰。我觉得这取决于和你结对的人。如果这个人很open,善于表达,能够接受别人的想法,同时也能表达自己的想法,一切讨论都是基于客观事实,那么结对时感觉就会很好。如果这个人很固执,不肯采纳别人的想法,一直坚持自己的想法,那和他结对就是灾难,还不如自己干自己的。当然也要想想你是什么样的人,是否适合结对编程。

    最后,结对编程对沟通和表达能力的要求也比较高,两个人的能力水平最好也能够相似,这样沟通才会比较有效率。

    Tag:agile