• 不知道从什么时侯开始,周边的人把我当作一个老手,尽管有些自己不那么情愿,但现实是和我在一起工作的人大多比我工作经验少。

    新手之所以为新手,是因为他们的经验较少,所以,不可避免的会犯一些错误。记得别人还在用新手标准要求我时,有一次出差,到了现场,项目负责人要我去安装我们的程序,可我根本就没把我们的程序带来,结果可想而知,项目负责人劈头盖脸的把我骂了一顿。

    换我扮演老手的角色,我会尽我所能把项目中的一些不确定问题解决掉,然后,让新手们去解决那些确定性问题,通常,他们的能力应对这样问题会游刃有余。最近一年多的项目里面,涉及到了很多探索新技术的工作,我会从项目中挑出一个最简单的情形用新技术实现出来,这个例子可以帮助我弄清楚技术背后的来龙去脉。之后,我就可以把他解释给其他人。我的同事们都很聪明,理解了基础结构,加上一个现成的例子,他们就完全可以继续进行下面的工作了。

    或许单独看起来,我的做法并没有什么特别的地方。刚好最近项目里面有两件点要去探索,我自己做了一个,把另外一个分给另外一个同事。他很快就做完了,而就是这个最简单的例子,我也做了好几天。探索的工作结束,进入到正式的开发工作,其他同事很快就可以接着我的工作继续开展。就是这个最简单的例子,除了了解技术的目的之外,我还写所有相关的脚本,万事俱备,只欠东风。而当我了解另外一个同事的工作时,我发现,他真的只做了一个最简单的例子,了解了一些基本概念。真正把这些内容运用到项目里时,左一个困难,右一个麻烦相继出现,我陪着他一个个克服了这些点,又把脚本预备好,几天之后,才真正进入到可以开发的状态。

    有人曾经问过我,你把有趣的工作都做了,把无聊的工作留给别人是不是合适呢?毕竟每个人都希望在项目中成长。前面说过,我的工作是削除项目中的不确定因素。是的,很多人喜欢的就是解决不确定问题带来的快感。但不确定对每个人来说是不一样的。只要最基础的例子跑通了,这项技术的不确定性对我而言就解决了,但实际上,在具体使用这项技术中还会有一些不确定的问题等待解决,解决这样的问题,同样可以提高。

    谈到成长,每个人都希望自己能够不断的成长,但是,即便是做同样的项目,每个人得到的机会也是不一样的,这样的差异实际上对应着各人不同的表现。和其他人一起工作的过程中,通过观察,我会把不同的工作交给不同的人来做。像前面说的那个同事,我之所以肯把一个探索的机会交给他,是因为他在之前的工作中表现出的态度和能力,虽然他的探索并不完全令人满意,但是,有了之前的信任,我会告诉他,怎么做才会做得更好。

    之所以会想起这个话题,是因为一个同事与我聊起他项目焦头烂额的状态。他在那个项目组中,扮演着和我类似的角色,他感觉自己做得非常累,项目进展也有些问题,于是,我们俩聊起了如何发挥其他人的作用,既让新人感觉自己得到了锻炼,也让自己轻松一些。

  • 2009-06-19

    月度演讲

    RubyConf China,我认识了Robin Lu。我们俩有种一见如故的感觉。我半开玩笑的对他说,有机会请你到我们公司讲点东西。

    回到北京,我向老大汇报RubyConf China情况时,提到了这句话。老大说,我们不妨建立一个Monthly Speaker制度,每个月从外面请一个人到公司来讲些东西。

    Robin Lu有着很强的分享精神,于是,他成了我们的第一个Monthly Speaker。

    今天,我们第一次月度演讲,主题是iPhone开发故事。

    Robin Lu为我们分享了他自己从事iPhone开发的一些经验。从他了解iPhone开发到成为一个iPhone开发者,再到,他将自己的软件放到AppStore上销售。最后,他又分享了自己对于iPhone开发的一些建议。中间很多的故事,只有亲身经历过的人才能讲得出。

    一如既往,Robin Lu的演讲是那样平实,那样吸引人。他不是那种靠技巧取胜的演讲者,但他却很能抓住听众,凭借的就是内容。他留给人的印象是含而不露,没有咄咄逼人的气势,但却可以把问题深入的讨论下去。

    Robin Lu为月度演讲开了一个好头,我开始期待后面的Monthly Speaker。

  • 2009-06-11

    Ant雕虫技

    Tag:ant 向下走

    当构建脚本变得复杂,分离变化这样编程思路同样可以应用其上。

    下面是一份简化过的构建脚本:
    <project basedir="." default="war" name="my_project">
        <target name="config">
            <property name="prop" value="prop_value"/>
        </target>

        <target name="build" depends="config">
            <echo message="build ${prop}"/>
        </target>

        <target name="war" depends="build">
            <echo message="war ${prop}"/>
        </target>
    </project>

    世界变化快,新需求来了,我们要进行一些安全设制。这份构建脚本即要支持安全版本的构建,也要支持非安全的构建。

    冲入大脑的第一个想法自然是重写一个支持安全war任务。不过,稍加分析不难发现,安全版本和非安全版本的策略差异最终体现出来就只是一些属性的差异,也就是从config开始,二者就开始走上了两条不同的路。如果构建一个安全的war任务,那意味着,我们也同样构建一个安全的build任务,一个安全的config任务也是不可或缺的。这是一个经过简化的构建脚本,在真实的项目里面,task数量不会这么少,task执行的任务不会这么简单的。顺着这个思路想下去,得到就是一个让人抓狂的结果。

    策略的差异只是影响到一些属性,如果根据不同的策略,只是配置相关属性,似乎生活就可以轻松许多。下面就是按照这种思路编写的一个新脚本:

    <project basedir="." default="war" name="my_project">
        <target name="sec">
            <property name="isSec" value="true"/>
        </target>

        <target name="nosec">
            <property name="isNoSec" value="true"/>
        </target>

        <target name="defaultStrategy">
            <condition property="isSec">
                <not>
                    <isset property="isNoSec"/>
                </not>
            </condition>
        </target>

        <target name="configSec" depends="defaultStrategy" if="isSec">
            <property name="prop" value="sec_value"/>
        </target>

        <target name="configNoSec" depends="defaultStrategy" if="isNoSec">
            <property name="prop" value="no_sec_value"/>
        </target>

        <target name="config" depends="configSec, configNoSec"/>

        <target name="build" depends="config">
            <echo message="build ${prop}"/>
        </target>

        <target name="war" depends="build">
            <echo message="war ${prop}"/>
        </target>
    </project>

    需要基于安全的版本时,
        ant sec war

    而非安全版本是
        ant nosec war

    这样,属性的配置和真正任务就成了两个独立的维度,不必因为属性的变动对任务进行大幅度修改。

    在这个例子里面,我们用到了一些ant的特性,比如像configSec、configNoSec这样基于条件执行的任务,比如像defaultStrategy任务中,在没有指定参数时选择缺省的策略。

  • 2009-06-05

    环境的力量

    和WPC聊天,提起了之前的工作岁月。听我说完当年的情况,WPC突然问了一句,你当时为什么不努力改变一下周边的人呢?

    是啊!我为什么不寻求改变呢?

    进入ThoughtWorks之前,我并不相信改变的力量。因为我周边的人向我传递的信息多半是一成不变,虽然那时的我已然是特立独行了,但改变其他人,我是压根没有想过的。大多数人给我的印象是,工作只是为了糊口,只要能够完成眼皮底下的工作,就不会再多花一点时间。我习惯了忍耐,我所能做的,只是把自己该做的事做好。

    在ThoughtWorks工作的两年时间里,我听到过很多这样的声音:我们可以这么做,这样就更好了。每个人都倾向于把事情做到它应该俱备的好样子,而不仅仅是完成。在外做咨询的那段日子里,我看见了我们几个人给那个团队带来的改变,虽然不是如何巨大,但它真的改变了。慢慢的,我意识到,原来,我可以改变。

    环境,可以影响到一个人的成长。

    之所以,我在那样一个绝大多数人都沉寂的环境下,依然努力提升自己,是因为,我的身边曾经有Darwin和founder_chen这样的家伙,他们让我见识到另外的一种存在方式,点燃了我对软件开发的热情,所以,我才能一往无前。

    现在,我的身边,有一些毕业就在ThoughtWorks工作的人。有的才工作一两年,他们的编程能力和对软件开发的理解远远超过我在同样阶段时的水平。偶尔想想,我会嫉妒他们,自己在黑暗中摸索和探寻了许久的东西,他们轻轻松松就得到了。可以预期,几年之后,他们的水平都会非常高,因为他们前面已然有这样的榜样了。

    大多数人愿意和比自己强的人在一起:所以,读书的时候,好学生那么受欢迎;所以,有人会抱怨,我没有机会和某某一起工作过……

    好的成长环境可以让人更快的成长,但成长的真正驱动力是自己。

    这一点从毕业生观察会体现得尤为明显。同样加入公司,一段时间之后,有的就已经可以独当一面,有的却只能在别人指导之下工作。我和很多人聊过,那些我认为优秀的人,都会有很多额外的付出,好的环境加上自身的努力让他们与众不同。

    在招聘的过程中,我们遇到过这样的应聘者,他的编程习惯都特别不错,但真正探讨起技术来,却显得不那么深厚。通过分析,我们发现,这样的应聘者通常是在一个很不错的环境中工作,这让他们养成了良好的工作习惯,但他们个人却并没有太多的额外付出,所以,他们对问题理解只停留在表面。

    物以类聚,人以群分。你的群在哪里?

  • 此刻,我,在上海。

    距离上次离开上海还不到两个月,之所以重返大上海,是为了RubyConf China。

    刚听说RubyConf China要举办的消息时,我就在想,找个怎样的借口才能到上海参会。所以,当我们负责市场同事找到我,说需要一个演讲人的时侯,我毫不犹豫的就接受了任务。

    接受任务是喜悦的,完成任务却是烦恼的。先是gigix和WPC讨论演讲的主题,最终定下分享我们在Ruby项目的一些经验,接下来,就是具体的准备了。每次准备演讲对我来说,都是一个痛苦的过程:一方面,我希望自己的演讲对听众来说,有一些价值,另外一方面,我还要保证思路顺畅,不让人感到突兀。这一次的准备,尤其困难,因为得到确切消息距离大会只有一个星期了,而且我还在项目上。感谢gigix和WPC等人,在他们的帮助之下,我对要讲的内容逐渐有了一个更加清晰的认识,也是因为如此,演讲稿也迟迟达不到可以拿出手的标准。负责联系演讲者的Daniel几次催我提交演讲稿,我何尝不想啊!演讲前夜,我依然在不断修改。

    这次RubyConf China最大的主角,自然是Ruby之父Matz先生。从他进场时那经久不息的掌声中,就可以看得出他到底有多受欢迎。他的演讲《Why Ruby?》介绍了他开发Ruby的一些历史,以及他在设计程序设计语言的一些考虑。很多想法也与我的一些观点不谋而合,听得我频频点头。Ruby原来是一个失业者的产品,时值日本经济不景气,失业在家的Matz利用这段难得的空闲,写出了Ruby。另一个失业者著名产品BT。很多人内心难以接受的失业原来也是一个巨大的资源。Matz说,如今这样一个不景气的光景,说不准就会产生出下一个影响深远的语言。

    借助演讲者的身份,我让会议的组织者引荐我认识了Matz。时间关系,我只和Matz做了一个非常短的交流,介绍了自己在Ruby实现上的一些工作,算是和Matz彼此相识了。最后,我邀请Matz到我们的北京办公室去做客,Matz欣然应允,“只要你们邀请我就好”。

    这次大会的内容还很扎实,robbin的《JavaEye网站架构深度解密》和robinlu的《Ruby and Rails Pitfall》是两个亮点,拳拳到肉。只有真正的经历过这样的问题,才能讲得出这样的话。从演讲技巧上来说,他们两个都算不上优秀,但扎实的内容让人已然忘却了外在,全心全意追随他们的内在。

    koz的《岛根县政府的挑战 - 在日本地区政府和社区当中使用Ruby的案例》是一个介绍,让我们了解Ruby在日本的发展,很开眼。让我惊讶的是,他——一个日本人用中文完成了整个演讲。Ruby的流行程度超乎了我的想像,可以说Ruby教育,从娃娃抓起。原来,岛根县就是Matz居住的地方,岛根县对于Ruby的推动,让我想起了鸟山明,政府为了让他送稿方便,而修了一条高速公路。

    其它几个演讲带给我的冲击相对来说要小得多。至于我自己的演讲,留给别人评价吧!

    最后的Q&A环节,说实话,我更想坐在下面做一个可以提问的听众,而不是一个回答问题的演讲者,因为对于其他人的演讲,我还是希望有更多的交流。在这个环节中,有一个人用日英中三种语言提问,成了大家关注的焦点。

    整体来说,这次RubyConf China还是很成功的,考虑到组织者只用了一个月时间,这样的结果已经让人非常满意了。robbin说,争取下半年在北京在办一次。北京的Ruby开发者们,期待吧!