本文介绍了典型的 coderetreat 的结构、内容和意图。文章的内容来自于多次 coderetreat 活动之后的反馈意见,反映出了这些活动的优点和不足,并对它将来的发展方向提出了一些建议。
Coderetreat 是什么?
在过去几年里,每到周末,在全世界的各个城市中,就会有软件开发者成群结队地聚在一起,他们会在一整天的时间内不断尝试编写代码,以解决某个给定的问题,但不会完整地实现一个解决方案。如果你认为这听上去有些疯狂,那大概是因为你从来没有参与过 coderetreat 吧!
这里为那些没有参与过 coderetreat 的读者解释一下:coderetreat 是一种通常在周末举办的活动,软件开发者成群结队地聚在一起,在为期一天的时间内为自己编写代码,以真实地反映自己的代码水平,并且互相学习。这种活动专注于实践(敏捷)软件开发中的基本元素,强调简单设计的基本原则,即让测试驱动编码,消除代码重复、保持代码的表达能力,并且不包含任何不必要的特性(稍后会进一步进行分析)。
这一思想是Gary Bernhardt、Patrick Welsh、Nayan Hajratwala 和 Corey Haines 在2009 首先提出的。从那之后,这种思想得到了发扬光大,以至于现在已经举办了三届“全球Coderetreat 日”,在这一天时,全世界各地都会分别举办coderetreat 活动,有数以千计的开发者参与其中。 2014 年的全球活动日在全球近 150 个城市中展开了 coderetreat,参与者超过了两千人。
一个典型的 coderetreat 通常(正如在 coderetreat.org 网站上所概述的一样)包括以下内容:
- 要解决的代码问题(或 kata)是创建一个虚拟的康威生命游戏(Conway’s Game of Life),它通过应用一些简单的规则,对跨越多代的细胞的生命和死亡进行模拟。
- 编码活动一共会举办五或六场,每一场的时间是 45 分钟。中间的休息时间可以进行交谈、用餐和饮酒,整场活动的时间需要一整天。
- 在具体过程中需要同时应用结对编程和测试驱动开发方式。
- 在每场编码活动结束后,所有的代码必须被删除,并且在下一场活动开始时要更换拍档。
- 参与者并不一定要在活动中实现一个完整的解决问题的方案。
- 可以在活动中加入不同的限制(例如:“方法不能够返回伤任何值”、“不可交谈”等等),因此,你可以从不同的角度对问题空间本身、以及与他人合作的方式进行重新探索与解读。
虽然这种推荐的 coderetreat 形式相当普遍,但也存在着许多可以灵活变通的地方,这取决于 coderetreat 的组织者打算强调参与者对于哪一方面的理解。比方说,在遗留coderetreat 中,测试是针对一段“糟糕”的现有代码片段进行创建的。尽管如此,对以上这些指导原则的选择有着很好的理由,因此,如果你希望活动不要丢失原本的好处,为了避免这样的风险,最好还是不要过于偏离这些指导原则。当然,对其中某一方面的改动不会减弱活动的基本原则的,那就是使用一个完全不同的kata(例如选择生命游戏之外的项目)。选择要活动中要加入哪些限制条件同样也完全取决于组织者。比方说,第一场 活动中可以选择完全不加入任何限制,或者可以在某场活动的中途加入某种新限制条件。每种限制所造成的难度可能是完全不同的,这取决于参与者本身的经验。比方如,如果在学生中间举办coderetreat 活动,我们会选择只加入一些较简单的限制条件,例如“ping pong”,它指的是每组中的成员之一(请记住,我们始终进行结对编程!)去编写测试(只编写测试代码),而另一名成员将努力让测试通过(让两位成员在活动中互换角色也是一个不错的主意)。
在coderetreat 网站上,有许多建议提出了各种不同类型的限制条件。比方说,对于一组更资深的参与者来说,你可以尝试 TDD as If you mean it 方式,这是一种由 Keith Braithwaite 最早提出的一种高级测试驱动开发实践。另一种常见的限制条件是“不得使用可变的状态。”不过你也要当心,有些限制条件是有问题的,它们可能会使编码过程陷入停顿而无法继续,稍后我们会对此展开讨论。
你可能已经注意到了,标准的指导原则中并没有提到编程语言方面的限制。有些时间,活动中可能会提议使用某种语言,但大多数的 coderetreat 活动都会让参与者打开他们自己的笔记本电脑、使用任何他们所熟悉的语言和测试框架。因此,在一场 coderetreat 活动中常常会出现多种不同的语言,这也意味着在结对的过程中,你可能会发现你完全不了解你的拍档所使用的语言。这种现象会让你感到兴奋或是受挫,以及程度如何,完全取决于你个人的偏好,以及你的拍档是怎样的人。不过,这一点或许也对我们使用的语言提出了一个疑问,即它能够在多大程度上表现出我们的设计思路。
Coderetreat 带来的好处
那么,参与 coderetreat 活动到底有什么好处呢?总的来说,它的好处在于你能够发掘出作为一个程序员的真实水平,而无需担心在工作中常常面对的项目期限和上司的期望。因为没有人强迫你必须在一次活动中完成一个解决方案,因此你可以自由地发掘新的思路,并对自己处理该问题的方式进行反思。因为你的拍档总是在变换,并且每场活动中总是出现新的、具有挑战性的限制条件,经常会促使你以不同的方式看待并解决问题。
对于 coderetreat 来说,回顾是必不可少的重要环节。在每场活动之后都会进行简单的回顾,而在全天的活动结束后,每个参与者都会面对以下三个问题:
- 如果今天你学到了某些东西,那么你学到了什么?
- 如果今天有什么事让你感到吃惊,那是什么样的事?
- 如果你打算在下次活动中进行某些改变,那是什么样的改变?
Coderetreat 活动应该对于提高你作为软件从业者的水平起到帮助,并帮助你深刻地理解自己和其他人的实践能力。本质上,当你结束一次 coderetreat 活动时,你应该成为一个更加优秀的,或者至少是更加具有思考能力和反思能力的开发者。
在过去的几年中,我与我的一些同事共同参与并举办了一些 coderetreat 活动,并且也通过多种渠道从 coderetreat 的参与者那里获取到了大量的反馈,不过主要的渠道还是在线调查问卷,因为全球的开发者都可以参与这种问卷。进行这种调查的原因之一在于,我们想看看,将 coderetreat 作为一种提高参与者对软件设计的认识这一思想是否得到了证明。我们也希望了解能够通过哪些方式改善 coderetreat,或者至少是对标准的指导原则作出一些有意义的变化。
从 coderetreat 参与者那里收到的问卷调查中,我们看到人们的反馈非常积极,他们普遍认识 coderetreat 是一种很有价值的实践经验。以下这些典型的回复令我们感到相当振奋。
- 这是一次令人难忘的体验,我希望能够马上再次参加。我会把它推荐给软件开发组织。在活动结束后我感到筋疲力尽了,感觉就像是进行了一次大脑运动。
- 它为我了解其他人如何看待这些问题和解决方案提供了一次良好的机会。
- Coderetreat 太棒了。经过最近几次活动,我觉得对于自己的专业度具有了一种责任感,而且我经常从中获得比我想象中更大的价值。
- Coderetreat 一定要成为面试过程中的一部分。J
以上这些留言来自于专业的开发者,但新手也表现出了同样的热情,正如以下这些来自于还是学生的参与者的留言所表现的一样:
- 这是一次优秀的活动,它让学生们为将来做好了准备
- 这种活动对我产生的作用连我自己都感到吃惊
- 它确实对我产生了很大的帮助,我也从中获得了许多乐趣
- 参与的次数越多,越容易上手,并且还能收获不同的点子,这真是太棒了
根据从全球各地收集到的 coderetreat 活动参与者的反馈来看,很显然它已经成功地帮助参与者看到,对于某个相同的问题,存在着多种不同的设计方案。实际上,通过人们对于那些标准的回顾性问题的回应,也可以了解到参与者从 coderetreat 活动中得到了哪些收获。在所有回应中,最常见的有以下几个方面的收获:
- TDD 与(或)单元测试
- 其它语言
- 结对编程
- 处理相同问题的不同方式
- 设计
很显然,对于设计与解决问题这方面的回应仅次于对于敏捷开发中的基本元素的回应。有一个结论或许令人感到有些吃惊,那就是许多参与者在活动之间在 TDD 和结对编程方面的经验还十分有限。不过,从调查问卷的统计中可以看到,有 35% 的参与者在软件开发方面的经验少于五年,而超过 65% 的参与者的经验少于十年,因此活动参与者的主体来自于学生或初级程序员。
关于参与者在哪些方面最感到吃惊,以下的回应是最常见的答案:
- TDD
- 编程语言与范式
- 与他人合作
- 乐趣
- 限制条件所带来的影响
从这些回应中,我们可以认为 coderetreat 起到了良好的作用。人们聚在一起,收获了令他们感到吃惊的乐趣,共同学习敏捷开发中的某些核心技术(TDD、结对编程),并且通过在不同的设计限制条件下开展工作,探索出了寻找解决某个编程问题的解决方案的不同方式。不过,改善的空间始终是存在的。毕竟,如果我们不能够保持总是寻求对设计进行重构的机会,并且拥抱变化,那我们就无法成为真正的敏捷开发者。因此,coderetreat 社区正在产生变化,从一种单一的形式转变为某些专注于特定类型问题的活动。其中包括遗留系统的 coderetreat(前文已经提到过这一形式),以及函数式编程的 coderetreat。我们相信,探索更有针对性的 coderetreat 活动是很有价值的。
Coderetreat 有哪些不足之处?
虽然 coderetreat 本身是个很出色的概念,并且大多数参与者都从中收获了乐趣和价值,但有些方面或许还可以进行改进。在整个活动中,我们观察到了以下一些情况:
- 尽量事先已经提供了大量的信息,但参与者还是经常搞不清楚要做些什么,或是如何开始。
- 虽然已经表示过所有代码都要按照 TDD 的方式进行编写,但要让每个人真正接受这种方式,往往还是要在一次活动之后。
- 当你参与了多次 coderetreat 活动之后,你会希望所解决的问题不再是针对新手的。具体地说,你可能已经对生命游戏感到厌倦了。
- 虽然 coderetreat 有意识地专注于简单设计的四个原则,但未必能以一种明确的方式表现出这些原则。
我们从反馈中也注意到,一次 coderetreat 活动的举办方式,将对整个活动的成功起到巨大的影响,正如某位参与者所说的一样:
对于 coderetreat 活动日的成功,以及参与者能够从中得到多少收获,举办者会起到巨大的影响。
不过,我们也不认为 coderetreat 的成功完全取决于举办者本身的技能与个性,它还取决于 coderetreat 活动的组织方式。以上所提到的四个可改善之处都或多或少与 coderetreat 的组织有关联。
首先来看一下第一个问题,即参与者经常会表现得毫无准备。好吧,你可以选择事先将所有信息都发布在网站上,并提醒参与者做好准备,但它起不了多大的作用。毕竟,你是在要求他们在一星期的工作之后,牺牲一个周六的时间进行参与。参与者来到这里的目的是从中获得乐趣,而不是参与一次测试,并且为了这次测试预先进行准备。你能做到的唯一一件事就是,作为举办者,为你的工作做好准备,让参与者能够尽快上手,并且在简单的过场后快速进入状态。
实际上,我们发现这一点将直接导致第二点问题的存在,即让每个参与者使用测试驱动开发。调查表明,在第一场活动中,有超过 10% 的小组完全不写任何测试!实际上,只有进行到第三场活动时,才能做到让每个参与者使用 TDD。我们相信,如果能够提供一个初始的测试桩(Stub),就能够解决准备不足和 TDD 的接受过慢的情况,正如我们上面所描述的一样。
解决第三个问题是比较困难的,虽然我们已经为 coderetreat 中要解决的问题提出了一系列建议,包括业务类型的问题,比如镀金玫瑰(Gilded Rose)问题,它是有关于某种产品的库存系统,其中包含了销售日期等信息;或是模拟一个轮胎压力监控或比赛计分系统。这些问题都无法做到像生命游戏那样:问题本身很简单,而面对的挑战很多。某个参与者也提到,康威游戏的算法给他留下了深刻的印象。
我是第一次接触【生命游戏】,并且十分惊讶地发现,一个简单的算法竟然能够产生如此神奇的效果。
不过,很明显,如果 coderetreat 活动打算进一步壮大与成长,那我们就不能够始终停留在生命游戏这一问题上,而必须探索一些新的点子。或许 Boids Flocking 算法模型是一个不错的选择,虽然我们还没有在任何一次活动中尝试过这个点子。
第四个问题是让我们感到最有挑战性的一个问题。我们如何保证 coderetreat 活动能够像它本身所宣称的那样,强调简单设计的四个原则呢?我们的研究表示,这一点或许是标准 coderetreat 结构中最弱的一个环节。虽然有许多问卷调查的回应都表示出了通用意义上的设计的重要性,但很少有回应表示出他们对简单设计的四个原则有所收获,至少没有明确地表明这一点。多数的回应显得更为广泛,例如以下这一条。
简化的问题能够让你专注于使你的解决方案能够运行,并且会产生更清晰易懂的代码
对于设计问题的回应太少,或许意味着 coderetreat 在某些方面应当表现得更为有效。
重构 coderetreat
通过对全球的 coderetreat 参与者进行的问卷调查,我们已经致力于对应那些可能会降低该活动的参与者体验的问题。我们组织了一次包含四场活动的 coderetreat,致力于更明确地应对简单设计中的四个规则,同时也确保让参与者能够更容易地开展工作,并实践 TDD。
在第一场活动中,为了确保‘让测试驱动代码’,我们为所有参与者提供了一个完整的单元测试集,以及一个推荐使用的单元测试集。我们明确地要求参与者使用测试驱动开发技术完成余下的代码。在第二场活动中,为了鼓励参与者将他们的代码改得更加清晰,我们提供了一个待测部件,以及部分测试,但有意地将这两者的代码质量写得很低。我们要求参与者对它们进行重构(当然,依然要应用测试驱动开发原则)。在第三场活动中,我们将应用某个设计原则,即移除重复代码。我们依然会提供一个待测部件和一些单元测试,其中的代码包含了某些不必要的重复,并且要求参与者在重构过程中消除这些重复。最后,在第四场活动中,我们会使用一些遗留代码(将活动的方向转变为遗留 coderetreat),并且没有任何单元测试。代码中包含了某些不必要的特性,参与者需要在重构过程中移除它们。
最终的结果令我们非常满意,尤其是整个小组能够快速地上手并实际使用 TDD。当然,我们并不是说每个人都应该采取同样的方式举办 coderetreat。有些人可能会觉得,我们的方式已经偏离了 coderetreat 常见的形态,已经不是一种真正的 coderetreat 了。但实际上,我们遵循了所有的通用原则。我们所建议的是,如果你是一位开发者,并且能够找到一个在你附近举办的 coderetreat 活动,那么就不要错过这次机会。而如果你不具备这种条件,那么我们建议你自己搞一次这样的活动。这种活动不一定必须是公开的,如果你的组织中的开发者够多(如果少于 10 人,就会减少可能的结队数量),那么也可以在自己的住所举办一次(前提是你的房间要足够大……)。我们就成功地在住所办过由我们的学生参与的 coderetreat 活动。
如果你确实打算自己举办一次 coderetreat 活动,我们有以下一些建议,至少在首次活动中可以尝试一下。
不要偏离本文之前所提到的标准形式,除了以下一些建议以外。
- 在首次 coderetreat 将生命游戏作为 kata,但可以考虑在接下来的活动中选择其它 kata。你甚至可以选择在一次 coderetreat 中挑选多个 kata。
- 如果可能的话,事先确定一种统一的编程语言,确保你的参与者们在注册时都了解这一信息。
- 如果可能的话,预先在房间中的所有电脑上都安装好必要的语言和测试工具(这一点大概只适用于在住所内举办 coderetreat)。
- 先提供第一个测试,并且为第二个测试提供建议。如果你的 coderetreat 支持多种语言,不一定要以代码的方式提供它们,伪代码就足够了。
- 不要选择一些有可能会破坏参与者的动力的限制条件。比方说,如果你为新手程序员设定了“不允许使用循环和条件语句”这样的限制,那他有可能会因此裹足不前。另一方面,有经验的开发者会享受挑战。请考虑一下你的参与者的情况,如果有所疑虑,不妨让他们自行选择合适的限制条件。
- 留下足够的时间以进行讨论和反馈,让他们有机会从其他人身上进行学习。不要因为活动的时间太长,就压缩回顾的时间。
我们希望,如果你积极参与 coderetreat 社区的活动,那么你应该尽量找到某些方法,让它使你对软件开发感到更有乐趣,并且更有干劲。以下是我们的一位参与者的留言:
我会寻找更多的乐趣,并进行更多的尝试。我也会尝试利用这次机会提升自己的水平,而不是满足于自己已经习惯的工作。
关于作者
Dr David Parsons是新西兰 - 奥克兰梅西大学(Massey University)信息技术系的副教授。除了进行学术研究之外,他也经常为软件教育协会和 Knowledgehut 提供专业课程的培训。David 在英国开始了自己的职业生涯,从那之后,他作为教育家 / 培训师、研究者和从业者,踏足了整个欧洲、北美和大洋洲。在 2003 年移居到新西兰之前,他在 Valtech 公司 Emerging Technologies 部门担任总监,这是一家总部位于伦敦的国际顾问公司。他的从业经历包括在南安普顿索伦特大学(Southampton Solent University)担任高级讲师,在位于渥太华的公司 The Object People 里担任培训师和顾问,在 BEA Systems 的国际教育部担任首席技术专家。他也是有关计算机编程和 web 应用程序开发方面的书籍的作者,并且对于敏捷软件开发实践进行了深入的钻研。他于 2014 年在 IEEE Software 杂志上首先发表了有关 coderetreat 的学术研究报告。他还是英国电脑协会(British Computer Society)以及新西兰 IT 专家学院(New Zealand Institute of IT Professionals)的一位专业成员。
查看英文原文: Refactoring Coderetreats: In Search of Simple Design
评论