• 2008-05-12

    客户来了

    敏捷软件开发中,与客户的沟通是一项必不可少的内容,因为只有客户才知道他们自己想要的是什么,只有他们才真正了解自己的业务流程。于是,在ThoughtWorks,客户来访是很常见的,这不,我们的客户今天就来了。

    一大清早,客户就到了办公室,他们给我们做了一个关于项目的介绍,让我们有机会聆听一下真正使用这个系统的人究竟如何看待这个系统,他们为什么会有这样的业务流程,在他们看来,哪些东西才是最有价值的部分以及他们希望这个系统未来会在他们的工作中起到怎样的作用。虽然在这个项目也工作了一段时间,但我也只是知道有哪些东西,对于为什么是这样,完全没有概念。今天客户的到来算是给我们补上了欠缺的一课。

    对于开发者而言,客户到来的作用很直接的体现在某些细节问题的确定上。通常,我们有了问题会问我们的BA(业务分析师),但BA不能给出答案的部分,就只能等待客户的回答了。原本因为时差的关系,一旦涉及到客户,这个过程至少需要一天。而如今客户就在身边,一旦我们有了问题,几乎瞬间就可以得到解决,开发周期大大的缩短。当然,客户不会一直在这里,所以,趁着客户在的这几天,我们要充分发掘他们的作用。

    以前也曾经历过客户到来,但这次给我留下的印象却特别深刻。因为,客户让我们近距离的接触到他们的业务。

    我们的项目是一个关于宾馆审计的项目,简而言之,有人制定标准,有人按照标准进行检查。虽然听起来很简单,但是系统里面的概念却离我们很远,很难想象究竟是什么样子的。今天,客户就带着我们亲身体验了一下做审计的感觉。

    我们去的是客户旗下的一家五星级宾馆,宾馆的总经理带着我们在宾馆内部进行参观,过程之中,还为我们解释了很多真正的检查过程中会出现的问题,在这个过程中,一个个曾经因为写程序而听说过的名词不断的出现在耳边,那个曾经遥不可及的概念,一下子变得异常清晰。上午的讲解和晚上的参观让这个系统变得更加真实了。以前只是住过宾馆,还从来没有从其他角度想过问题。今天的参观,明显是抱着“找茬”的心理。顺便说一下,我们的“审计”还真起到了一定作用,有人在宾馆的游泳池边上的宣传牌上发现了错别字。

    客户到来,还有一个很直接的好处,那就是,给了我们一次team building的机会。即便单从这个角度说,我们也总是欢迎客户来访的。^_^
  • 又到周末了,由于CodeJam的原因,这已经是我连续第十二天的工作了,有些许疲惫。在这个即将到来的周末,要好好让自己放松一下。

    这周开始了一个新的项目,一个Ruby on Rails的项目,一个让我期盼了很久的项目,也是我之前学习Rails的最重要原因。不过,Rails是我最近的blog中出现频率很高的字眼,所以,我并不打算在这里聊Rails的话题。

    既然不谈技术,那就不妨聊一些与自己之前做项目不同的体验吧!

    在我们这里开发的准确的说是这个项目的第二阶段,也就是这个项目已经有了很多东西,之前这个项目是由美国那边的团队来做,所以,我得到了一个观察国外的ThoughtWorker如何做事的机会。原来参与过的项目里面,更多的是中国这边的ThoughtWorker,所以,我饶有兴致去观察一下二者之间的差异。由于参与这个项目的ThoughtWorker大多是有经验的开发者,所以,很多方面做得成熟许多。

    这个项目的自动化程度很高,显然,这些ThoughtWorker在开发之初做了很多工作,把许多可以自动化处理的部分都放到的Rakefile里面。所以,我们得以把更多的精力放在开发本身上,少了很多繁琐的操作。一个简单的例子是,我们提交代码只要简单敲一个命令,首先会到SVN进行更新,然后重做数据库,运行测试,随后,把增加的部分找出来添加到SVN中,最后,它会问我们Pair的人,Story的编号,以及做了哪些工作,以便生成SVN提交的日志。和大多数自动化的工作一样,这些工作本身没有任何技术难度,但有了这些之后,我们可以少敲一些命令,更关注开发本身。其实,之前的几个项目也有一些自动化,比如用Cruise Control做持续集成,但这个项目应该是我经历过的自动化程度最高的项目,差不多常见的重复性工作都自动化了,看看那长长的Rake任务列表便可见一斑。

    每天早上,Standup之后,我们会把所有的Dev召集到一起,一起来看一下昨天的工作。我们用SVN diff把代码的差异列出来,大家一起来过。如果恰好是自己做的代码,编写代码的人就会站出来,为大家简单解释一下做了些什么。这样,这样保证大家都会了解到项目的进展。这样做还有另外一个原因,因为我们是一个分布式团队,除了我们在中国这边,还有几个人在美国开发,这样过代码,便可以大致了解到美国那边在我们睡觉的时候干了些什么。

    这个项目还有一个做得我觉得不错的地方,就是Story做得很细致。我们在Mingle里面的Story,很多都会有完成这个Story要做哪些步骤的描述。我们只要按照这些步骤一步步做下去就可以了,每完成一个步骤,就做一个简单的标记,这样,几乎不会有遗漏。除了Mingle上的Story,我们还会有专门的文档对这个Story进行比较详细的解释,包括一些验收条件。显然,这个项目的BA做了大量的工作,让我们后续的开发更容易。

    这个项目从美国过来了一个BA和两个Dev,而Pair的过程,让我不得不每一天都以英语进行交流。私下里,我经常说,我的英语水平代表了TW的最低水平。当年面试的时候,我自认为表现的最差的就是结对编程,因为一个英国同事高高兴兴搬了把椅子做在我边上,害得我不得不英语解释我在做什么,思路一下子就乱了。不过,少了面试的压力,这时候和人用英语Pair,效果还算可以接受,至少我还可以思考。实在不理解的,就让自己的Pair多解释几次,好在ThoughtWorker们都是很好的人,我的Pair总是不厌其烦的为我解释,直到我确切的直到了我们要干什么。

    在这个项目里面,我很高兴的扮演起学生的角色。一方面,我们不是很了解需求,需要向“过来人”学习,另一方面,来这边工作的两个Dev确实都有很长时间的工作经验。和他们在一起工作,我乐得把控制权交到他们手上,自己虚心的观察他们如何思考,如何解决问题。和他们在一起工作,会让人感觉很放心。正如我在《与高手共事》中提到的,他们做的那些工作都很简单,经过一步步简单的工作,一个个Story就完成了。

    对我来说,这个项目才开始一个星期,已经学到了不少的好东西,值!
  • 周末没得闲,因为参加了一次CodeJam。

    CodeJam,是公司组织的一个编程活动,就是要在周末两天时间内开发出一个东西,据说此类的活动在其他的办公室举办过。这是我第一次参加类似的活动,参加这次活动的Dev都是公司内比较优秀的程序员,平时很难把这些人都放到一个团队里面,有机会和这些人在一起工作,本身就是一件令人期待的事。

    这次活动的目标是为一个支援乡村教育的组织开发一个分享平台。在活动开始之前,我们对需求一无所知,所以,几乎就是看两天内能够写出多少东西。因为这个项目要开发的是一个Web应用,从生产率的角度来看,我们当仁不让的选择了Rails作为开发工具,这也是我最近在学习Rails的原因之一。

    万事开头难,这次CodeJam也不例外。在一群Dev准备甩开膀子大干一场的时候,我们发现了一个问题,没有需求。需求,是冰云(BA)和QQ(QA)在之前一天和我们的客户谈好的。QQ在离开办公室之前,把从需求整理出的Story卡片锁到了自己的抽屉里,结果,第二天,她闹肚子了。好在冰云临危不惧,顶着我们的巨大压力,把部分Story重写了出来。直到QQ重新归队,打开宝箱,需求问题才得到了彻底的解决。

    正式开工,场面那是相当壮观。一群ThoughtWorker,一群快手,一帮人抢着提交代码。做用户登录部分的高喊着,他们应该是第一个提交数据库表的,结果,更新代码时,已经有了数据库版本已经到了3。那是我和WPC干的,因为我们俩负责搭建开发环境,所以,先下手为强了。不过,我们高兴得有些过,用scaffold生成的代码出现了一个拼写错误。这时我们才发现,修改这些生成代码是多么痛苦的一件事。

    在这里,我们用的典型的ThoughtWorks工作方式,一对Pair,拿到一张Story卡,然后,小步前进:测试、编码、重构、提交。正是因为步幅很小,所以,就出现了大家争抢着提交代码,因为稍微慢一点,就会更新下来一片代码,这种时候,便要重新运行测试。运气不好的话,破坏了别人的测试,还要帮别人修复。其实,在一个大的开发团队中,这种现象很常见,尤其是测试多到不能很快运行完,比如有集成测试的时候,常常是运行测试之后,又来了新代码。

    典型的ThoughtWorks工作方式,还有另外一个含义。一群人一边写着代码,一边互相开着玩笑。在我的印象中,ThoughtWorks开发团队从来就不缺少笑声。其实,这次参加CodeJam的人,有很多我并没有直接在一起工作过,所以,这也是一个很好的了解大家的机会。比如,在我的印象中,WPC一直是闷着头写代码的家伙,和他Pair才知道,他原来也是那么有才,可以让人笑得肚子疼。至于像徐Xgigix这种平日里就给大家很多欢乐的家伙(也许也包括我自己)就更不用说了。当然,也有比较安静的,亮亮和来自加拿大的Ricky被我评为“最安静的Pair“。

    两天下来,从无到有,一个具备基本功能的网站就建立了起来。showcase的时候,看着这个小网站,心里还是很有一丝满足的。对我而言,这是我第一次做Rails项目,第一次尝试用TextMate去开发。

    这次CodeJam,是在公司内部进行的,希望将来有机会把这个面扩大一些,让其他公司的人来和我们一起来做,一方面我们可以从其他人身上学习到一些东西,另一方面,也让别人了解一下ThoughtWorks是如何工作的。我相信在如何进行软件开发这个问题上,ThoughtWorks做得足够好。

    UPDATE
    其他的ThoughtWorker也有对这次活动发表了自己的看法。
    冰云:Beijing Code Jam - 2 days agile development project
    Ricky:CodeJam@Thoughtworks Beijing

  • 不知道算是幸运,还是不幸,我参与的多数项目,如果不是从头开始,我也是最开始加入的几个人之一,所以,我通常对项目的来龙去脉都比较清楚。这次,我有机会尝试一下在一头雾水的情况下开始一个项目。

    这个项目已经进行了超过一个月,因为客户需要在赶在最近的一次发布之前,增加一些功能。老板按照目前的进度估算了一下,如果不加人,这个任务很难完成,于是客户很合作的同意增加两个人。就这样,我成了临时工。事实上,在这个阶段进入,项目早就过了最初的阶段,远远望去,没有几百也有几十的程序文件屹立在那里。虽然有最熟悉项目的人为我们介绍了项目的背景和架构,但这些宏观层面上的东西,对于编写代码这样“微观”的操作而言,几乎是没有任何直接的帮助。作为一个新人加入到项目,除了发呆,我还能做什么呢?

    回想在以前公司的情形,大多数新进项目的人多半是得到一大堆文档,然后,有人语重心长的说,先把文档看了吧!且不说这些文档这种东西几乎写出来就过时,单单读完这些文档就需要花费很多时间。运气好的话,还有代码可以对应,但千万不要指望你能够一下子读懂这些代码。也许,你会想找别人来问,如果不出意外,大多数人都会不明就里的非常忙,忙到有时间上网聊天却没有时间给你讲这些东西。事实上,很多人即便自己做了很多东西,也不一定能够清晰的描述出来,所以,即便找到一个“闲”人,成功从他那弄明白这些东西的概率也很低。其结果是,我们经常会看到一些人在那对着电脑上的文档发呆。

    在ThoughtWorks,我也恨不得找到一堆这样的无聊文档来打发时间,以此来享受偷懒的时光。遗憾的是,完全没有这种机会。因为那些“文档”会被视为浪费,这在以消除浪费为己任的敏捷来看,是无论如何不能接受的。于是,我在找不到任何借口的情况下,进入项目的第一天,就开始写程序了。不了解项目,怎么写程序?这是个问题。

    敏捷实践中,有一个叫做Pair Programming的,从字面上来看,就是两个人一起开发。对于ThoughtWorker们来说,Pair是一种常态。所以,我在开发时也会有一个Pair,虽然我对项目一头雾水,但我的Pair已经在这个项目上工作了很长一段时间,所以,他很清楚这个项目的一切,差不多一切,因为代码是集体所有,所以,他在开发过程中会接触到各个部分。

    拿到我们要做的Story,我的Pair会结合这个Story给我介绍上下文,并结合代码大致描述一下我们要做的事情。虽然在这个项目上我是新手,但我并不是对编程一无所知。有了这些基本的信息,我至少对我们要做什么,以及如何来做,在心里已经形成了一个大致的印象。刚开始时,基本上是我的Pair在主导开发,一边做一边告诉我,我们已经走到了哪里。渐渐的,我已经对我们在做的代码有了一些认识,开发也开始由一个人主导转向两个人讨论。随着开发的深入,我也发现了现有做法的一些不足,于是,我提出对代码进行重构,并给出了自己的分析和建议。我的Pair在听了之后,认为这是一个可行的建议,于是,我们毫不留情的将那段大家看着不舒服的代码改掉,这段代码从此清净了。

    这就是在加入项目前几天所做的事情,虽然我目前还不能对整个项目有个很好的把握,但是,我相信,我已经开始在这个项目中起作用了。我想,Pair Programming是主要原因。正如前面所说,虽然我对项目很无知,但我的Pair很好的弥补了我的不足。正是两个人的协调工作,让我可以在对项目没有完整认识的情况下,可以很快入门,以最快的速度融入到开发之中。

    曾几何时,我对Pair Programming的认识还停留在大家一起写程序和知识分享上,原来它对半路出家的人帮助也很大。虽然《人月神话》教导我们说,加人起不了很大的作用,但Pair的方式至少可以在相当大的程度上发挥新人的价值,削弱加人带来的负面影响。

  • Fluorida是一个Flash的功能测试工具。如果你听说过Selenium,那么可以把Fluorida理解为它对应的Flash版本。

    前不久,gigix对我说,他打算做一个Flash的功能测试工具。我说,从语言的角度来说,我不喜欢Action Script,因为它缺乏美感,但我喜欢这个方向,所以,我觉得这件事靠谱。

    上周末的Open Party,听了Michael Chen一个关于Rich Client的session,顺便清理了一下关于Rich Client发展的思路。C/S年代,最大的问题在于部署,升级起来很困难,进入到B/S年代,浏览器的广泛存在解决了部署的问题,不过,简单的页面表现力受到了极大的限制,所以,才有Ajax这样技术的流行。把部署和UI表现力一下子都解决了,那么服务器和客户端的威力就可以得到极大的提升。显然,一些公司看到了这方向,比如MS,它们祭出了Silverlight,不过,从目前的状况来看,在这个领域的领跑者无疑是Adobe的Flash。因为几乎所有拥有浏览器的计算机都安装了Flash Player,这是一个压倒性的优势。

    最初的Flash,是为设计者而存在的,所以,谈到Flash,人们首先想到的是“炫”,显然,这不是程序员的强项,所以,大多数开发人员并不会和Flash太亲近。Adobe认为Flash应该扮演更重要的角色,比如成为前面提到的新一代C/S结构的领军人物,但是,想做到这一点,必然需要大量开发人员的支持,所以,Adobe不断的让Flash进化着,比如,Action Script从2到3,发生了巨大的变化,用Action Script 3加入了面向对象,用它写程序,感觉和用通常的程序设计语言并无二致。Adobe甚至更近一步推出了Flex,实际上,它就是为开发人员提供的Flash。再在Eclipse的基础上,打造出Flex Builder,所有这一切都是为了亲近开发人员。Adobe AIR的推出,让Adobe在这方面野心显现无疑。可以看到的是,Adobe的脚步并未停止,它还打算让更多的语言运行在Flash上,显然,它们要提供的是一个新的平台,用以抗衡.NET和Java。

    站在开发者的角度,我们更关心怎么让自己的开发工作更舒服一点。作为一个ThoughtWorker,没有测试的日子是让人难以忍受的。在之前的一个进行Flash开发项目中,FlexUnit成功填补了Flash开发拼图的单元测试框架这块,而功能测试这块却一直没有很好的做起来,有人尝试过FunFX,但总觉得不爽。

    当gigix要写一个Flash集成测试工具的时候,我知道,参与过Selenium开发的他,对于功能测试应该是什么样子,心里应该很有数。事实就是这样,从接口上来看,Fluorida与Selenium如出一辙。

    欢迎任何对这个项目感兴趣的人加入,0.0.1意味这个项目中有许多事可做,你可以给出你的建议、意见或是代码,甚至你觉得这个项目的名字不好也可以建议修改。因为这个项目最开始叫做Fluorine,由于与一个Remoting框架相同,gigix把它改成了现在的Fluorida。