业务实践介绍完了,现在该聊聊团队实践了。团队实践支配着团队成员之间的关系,以及团队成员与他们所创造的产品之间的关系。这些实践有助于小型团队表现得像真正的团队。他们帮助团队建立交流的语言,使团队成员对彼此、对正在构建的项目的期望保持一致。
隐喻
隐喻是一个看名字你根本不明白这是啥的实践,即使是看了它的概念,你也许还是会这么想:为了有效地进行沟通,团队需要一个受限制的、有几率的词汇表,其中包含项目中的术语和概念。这个实践的目的是为了将项目与团队具备的共同知识关联到一起。
这个隐晦的实践直到领域驱动设计的出现迎来了曙光。埃里克·埃文斯(Eric Evans) 在《领域驱动设计:软件核心复杂性应对之道》中创造了一个概念 - 统一语言(Ubiquitous Language)。这才是隐喻该有的名字。
在某一个项目中团队需要对问题域进行建模,描述这个模型的词汇表需要得到所有人的认同,是的,包括利益相关者。这样做有一个好处,当大家在讨论问题时,不用做过多解释,大家都在同一个上下文里。举个例子:
在某项目中需要用一个词语来指代系统的客户,在项目前期并没有统一语言(或者说没有很好地实践隐喻),大家对客户一词有无数个词语来指代 - person,client,customer...于是在讨论问题时,他在说person,我在说client。在代码里也是同样的情景,同样的实体,有无数个变量名,但其实他们都是同一样东西。
统一语言过后,大家指定一个用词,摒弃其他所有词语,不论是在代码中还是在讨论的时候大家都能在同一个上下文里。
可持续节奏
跑得快的不一定赢。
加班
加班是程序员们绕不开的话题,我们需要达成一个共识 - 永远不加班是不现实的,低频率的偶尔加班是合理的,一直在加班是不可接受的。
长期加班或者说是加班到深夜,会给我们带来什么?以我自己为例,我的脑子里一团浆糊,平时简单的问题我需要更多的时间来思考;我更容易做出错误的决策,第二天上班发现自己昨天写了一坨无法描述的代码;代码质量也得不到保证。
加班只有两种原因
- 需要解决复杂问题
- 需要赶工期保证项目完成
这两种问题可以通过很多方式解决,但长期加班绝不是唯一一种,在第一篇文章中,我们已经有了一些不错的解决方案,或许还有很多别的方案,你必须非常清醒地意识到加班的成本可能远远超过节省的时间。
当然,在国内背景下,有一些项目需要迅速抢占市场以获得第一批用户,这些项目的同学需要无休止地加班,在这种问题上,每个人都有不同的选择。
马拉松
不管是项目管理者还是程序员或者别的什么角色,都应该意识到软件项目是一场马拉松,而不是冲刺,更不是一系列的连续冲刺。你的奔跑必须能长时间坚持。你必须以“可持续节奏”来奔跑。
一旦冲刺,你就必须减速或者休息(换句话说就是996都在划水),这样一来,你的平均速度将慢于“可持续节奏”。马拉松的冲刺,应该只发生在快接近重点且你还有足够的能量。
请你记住,加班工作并不能向雇主展现你的奉献精神。相反,如果你自己天天在加班,而同事没有加班,说明你的计划做的很糟糕,你答应了不该答应的截止日期,承诺了做不了的事情,你只是一个可被操纵的劳工而非专业人士。
睡眠
不管怎样,请保持你充足的睡眠,这是人类最好的养生之道。每个人所需的睡眠时长不一样,尽快认识自己的身体,找到自己到底需要多久的睡眠。请不要让工作吞噬你的睡眠时间,否则你的生产力会直线下降。
代码集体所有
敏捷项目中没有人独占代码,代码归集体所有。任何团队成员都可以随时改善项目中的任意模块。团队集体拥有代码。这样做的好处是知识会分散在团队中。每个团队成员都能够更好地理解模块之间的界限,以及系统的整体工作方式。这极大地提高了团队沟通和决策的能力。
代码集体所有并不意味着你不能有所专长。你需要做的是既要在自己擅长的领域工作,还要与其他领域的代码打交道。
一些公司的规则与这完全相反。每个程序员拥有自己的代码,并且要对自己的代码负责。程序出现 bug,要通过代码追责;别人需要修改自己的代码,需要告知你,由你来修改;业绩和地位由代码来决定,关键业务代码的程序员地位高于其他程序员。
整个代码库无法复用,模块封闭,壁垒坚固。
持续集成
在早年的敏捷中,持续集成意味着开发人员每隔一两个小时就签入一次源代码的修改,并将其合并入主干。所有单元测试和验收测试都应该是通过状态。不存在任何未集成的特性分支。部署时不应激活的所有变更都要通过开关(toggle)来处理。
这个时候所谓的集成其实都是开发人员自觉在本地实施的,是否真的破坏了集成,需要开发人员自觉地修复或是等到 QA 来发现问题。
2001年,ThoughtWorks 创造了 CruiseControl,第一个持续构建工具。这个工具可以将签入时间缩短至几分钟。它能够监视源代码控制系统,一旦发生任何签入就会启动构建,自动运行系统的大部分测试,并将构建结果发给团队中的每一个人。
后来出现了许多大家耳熟能详的构建工具 - Jenkins、Bamboo 等等。因为签入源代码的时间已经被缩短到几分钟,持续构建变成了持续签入,每一次签入都将触发一次构建。
纪律
持续构建应该永不失败,每个程序员都要在提交代码前运行所有测试。如果构建失败了,那说明有奇怪的事情发生了,毕竟你在本地的构建时成功的。
失败的构建是一次紧急事件,应该有物理措施立马通知所有人,所有人应该用最高优先级来处理这个事件,所有程序员应该停止手头的工作,合力将构建修复成功。构建必须永不失败。
代价
如果对构建失败熟视无睹会发生什么?简单来说,这是在作死,所有人都会自动屏蔽构建服务器发来的失败通知。经受不住骚扰的人还可能删去失败的测试,觉得以后加上就好了。往往这样的以后会变成永不。
日复一日,构建看起来都是完美的,但是大家都忘了其实我们删除了一大堆测试,既然测试失败了,那么也就意味着我们的系统已经被破坏了。
但是无所谓,构建时绿色的,它在告诉大家,系统现在可以被部署,于是,一个不堪重用的系统上线了。
站会
站会的思路很简单,团队成员站成一个圈,回答3个问题:
- 上次站会之后我做了什么?
- 下次站会之前我要做什么?
- 什么阻碍了我的工作?
在站会上不要讨论,不要深入解释,不要藏着掖着或者带情绪的表达,也不要发牢骚或聊八卦。每人30秒,会议结束,该干活的干活,该讨论的自己下去讨论。
虽然思路简单,但是在实践的过程中大家依旧会产生很多困惑,这些回答或许可以解答你的困惑:
- 该会议是可选的。许多团队不开这个会议也能过得很好。
- 不一定每天都开。但需要选择合理的时间间隔。
- 即使是大型团队,站会时间也只应该在10分钟以内。
- 这个会议只遵循上述的简单议程,不要多加任何东西。
猪和鸡的寓言
猪和鸡的寓言讲的是:
一只猪和一只鸡走在路上。 鸡说:"嘿,猪,我们开一家餐馆吧!" 猪回答说:"嗯,可以啊,我们叫什么名字呢?" 鸡答道:"叫火腿蛋怎么样?" 猪想了一下,说:"滚!你要我的肉,但你就下个蛋!"
问:在培根加鸡蛋的早餐中,鸡和猪有什么区别? 答案:鸡只是参与,但猪需要牺牲!
这个故事应用在站会里面的意思是:理论上来说,只有开发人员才能在站会上讲话,经理和其他人可以旁听,但不应该插话。但其实这不是一条铁律,只要议程还是那样的议程,如果需要,其他人也可以发言。