My mind to your mind. My thoughts to your thoughts…
– Mr. Spock
什么是结对辅导
在前面的两篇敏捷咨询工具箱中,我分享了如何做读书写代码活动和 OO 训练营。认真的做好这两项活动之后,团队的开发设计能力会提升一个台阶。对于有经验和有能力的团队,他们可以直接把这些技术和思想直接应用到项目中。但有一些团队还需要进一步的跟进。那我们如何进一步的跟进,保证大家能把这些技术应用到项目中呢?
这对一个敏捷咨询顾问是一个很大的挑战。在很多人眼里,顾问就是那些能说会道,把事情说得天花乱坠,但都是只会纸上谈兵,站着说话不腰疼,为团队带来麻烦,却不解决实际问题的人。我承认,顾问的好名声就是曾经被这样的人给败坏了。那顾问如何才能深入团队,解决他们的真正问题呢?答案是把顾问放到一个具体的项目团队里面,为团队成员提供结对辅导。那什么是结对辅导呢?
结对辅导来源于极限编程的一个开发实践──结对编程:
“结对编程,就是两个开发人员用一台电脑一起编程。一个人操作键盘和鼠标,充当驾驶员的角色。另一个人在旁边观察和思考,提出建设性的意见,充当着领航员的角色。同时,两个人会频繁的进行角色互换。”
我们把这项实践运用到咨询中,我会去一个项目团队,和大家一起工作,用结对的方式对团队中不同角色的人进行辅导。我会和开发人员一起结对,指导他们如何做开发和设计 ; 我会和业务分析师一起结对,指导他们如何做写用户故事,如何做需求分析 ; 我会和项目的经理一起结对,指导他们如何管理项目和团队,如何系统思考,如何主持各种会议等等。下面分享我是如何对开发人员进行结对辅导,指导他们在真实项目中进行 TDD 开发和设计。
如何辅导一名主开发人员做 TDD 开发和设计
我在一个客户那里,结对辅导了一个主开发人员。我们一起用了三周时间,完成了一个完整的用管理功能模块,这个功能大致分为 6 个左右的用户故事。我们是在 C 语言的开发环境下,使用 TDD 的编程方式。下面将分享我是如何做的结对辅导。
梳理需求
在结对开发开始之前,我和她花了一天的时间,从下面几个方面对需求进行了梳理:
- 以前是否有用户管理功能,它的业务流程是什么样的?
- 为什么要做一个新的用户管理功能?
- 新的用户管理流程会是什么样的?
- 每个需求的内容是什么?它的功能范围是什么?背后的价值是什么?
- 有哪些验收用例,这些用例是否全面和具体?
- 测试人员如何验收?这些需求是否可以端到端的进行完整测试?
通过这样的提问和交流,我们完整的把这些需求梳理了一遍。同时也把遇到的一些不合理用户故事做了重新划分。
纠正错误的编程习惯
第二天,我们开始结对编程。刚开始结对的时候,发现她已经从别的地方拷贝了一堆代码,修改了一些,可以编译通过。她想在这碓代码的基础上开发,这也是典型的复制 & 粘贴式的开发方法。我们花了很长时间讨论了这个问题。复制和粘贴是邪恶重复代码产生的根源之一,这显然是错误的编程方法和习惯。可是她却习以为常,并不觉得有什么错,按照她的话说:有现成的代码,拷贝过来修改一下有什么错。激烈的讨论之后,最终以双方的妥协和各自让步达成了一致:
- 这些代码是有价值的,它只是用来做 Spike,验证一些功能是否可以实现
- 但是 Spike 之后这些代码需要扔掉的,作为妥协,她愿意把这些代码全部注释起来(舍不得这些破烂)
- 用 TDD 的方式写代码,先写测试后写代码,没有测试失败就不要写代码,重构代码除外
真正的 TDD 开发
我要求她使用 TDD 开发即测试驱动开发。先写一个测试,运行测试失败,然后再写业务代码。可是,她上来就反对:“费那事干吗,一次把所有的测试都写完了再写实现代码,这样岂不是更快?”。我先是无语,然后便开始说服她,告诉她这叫小步前进,就是把复杂问题分解开,从最简单问题的开始,一步一步的前进,这样开发才有节奏,每一小步都会有反馈(测试失败,实现业务代码,测试通过),整个开发过程可控可驾驭。我苦口婆心说了半天,她还是坚持自己的意见。于是我问她:“你为什么要一次写完所有的测试?”。她的回答让我恍然过来:“因为我想到了很多测试场景,如果没有写下来,我担心自己后面会忘掉”
啊哈!我终于搞明白了她的顾虑。这个好办,我们拿了一张卡片,然后把想到的测试场景全部写到卡片上。实现完一个小功能,就在上面做个标记。这样在做 TDD 开发的时候,就可以专注写一个测试,有了一个失败测试之后,让测试通过是压倒一切的任务。这样的开发过程很专注,思维不容易发散,任何时候想到了其它相关的问题,就及时的纪录在卡片上,等后面再实现。
在我的严格要求之下,她开始了 TDD 方法,先写一个测试再写业务代码。我的目标是把她培养出来,所以我们采取了是教练式的结对方法:我提出想法,她操作键盘和鼠标写代码(有时候我会为她写一些测试代码)。结对也是一个引导的过程,有了一个新的测试之后,第一步是要让测试通过,这时不用去追求代码的优雅,只要测试通过就可以了,然后我会提出代码中的坏味道,和她一起讨论,问是否有更好的方法?如何让代码更能表达业务意图?如何在同一个层次上编程等等?引导她一步一步的进行重构。
下面这张图是一步步用 TDD 方式产生的用户登录功能的测试用例:
就这样,用了三周左右的时间,我们一起完成了这个功能模块的开发。三个星期的结对下来,我也有了一些心得体会。
心得体会
- 在同一个经验丰富的开发人员进行结对辅导的时候,前面会有一个挑战的磨合期。因为他们一般都积累了自己的一套成功的编程方式和习惯,这样导致他们对新的 TDD 开发和简单设计有抵触的情绪。这样就需要顾问一步一步的引导说教,让他们切实体会到新开发方法的好处。
- 结对辅导需要两个人紧密的协作,刚开始肯定会有一些工作方法和习惯上的冲突。如果对方不认可敏捷的开发方法时,不要一味的说教,一定要先沟通和交流,询问为什么不愿意这样做,了解清楚对方的顾虑和担忧之后,对症下药,提供一些实践解决对方的顾虑。
- 有时候我们的建议遭到拒绝,往往并不因为是建议本身的问题,而是因为我们还没有建立好信任和领导力。
关于作者
钱安川,ThoughtWorks 公司高级软件咨询师、敏捷过程教练、资深讲师、Team Leader、开发者、 BeiJing Open Party 组织者和主持人。个人博客:敏捷开发训练。
评论