---
title: 以学习者为中心 —— 毕业生之 Tasking 和 TDD 培训
---

讲真，这是我第一次真正觉得从 coaching 中学到了东西。短短一周培训，帮我丢掉了偶像包袱，脱离了低级趣味。好的培训，以学习者为中心，而非以教师为中心。这些天里各种技术讨论、质疑神教、session 分享，好像重温了我们毕业那届激(chui)扬(niu)文(bi)字的时光。要我说，这才是 TW 精神所在。

## 目录

* 心得
* 课程安排和设计
* Tasking 授课大纲
* TDD 授课大纲

## 心得

教头计划是个高强度、全脱产的毕业生培训，这是它不同于[郑大烨校][]等利用周末培训的地方。我理解它是规模化之下的一个产物，公司有足够的动力来做这个事情。

培训前我对它的手段和目标理解就是两点：

1.  教授工程技术，以帮助同学们能快速适应项目
2.  传承敏捷文化，以传达我们认为正确的工作方式

敏捷和文化是贯彻在培训始终的，不过 tasking 和 TDD 算是其中比较大密度的两节课；具体的工程技术基本全是[娟姐][dujuan.in]和胡乐在做；课程安排、资源协调等工作基本也都是讲师们和 people 大力推动。由于我只做了 tasking 和 TDD 两节 session，所以只重点谈谈这两节课的收获、大纲和不足。

**意义**。鉴于个人对 TDD 的强烈兴趣，我主动领了任务分解和 TDD 这两节课。为啥这个事情很重要呢，因为我司作为一个高逼格（至少我了解是这样）又死贵死贵的专业咨询服务公司，敏捷实践和端到端交付一直是一个差异化的溢价点，客户买的一大部分就是这个。其中，**TDD 又是敏捷实践的核心和灵魂**。而这个东西本身很需要练习，在规模化的背景下，怎样传承这样的技术实践和文化，据说至今依然是个无解的问题。于是，前教主[熊节][]整了个 TDD 神教，教旨是「没见过 TDD 做得好但失败了的项目」。如今教主走了，神教还在，希望新一届 TWer 接过这个神圣的火种，将 TDD 火种传播到 TW 的每个角落吧。

**收获**。认真准备一个培训，会有很多意想不到的惊喜。除了能够帮你梳理知识体系、了解到不同技术对不同受众的传播方法，学习者们本身也有很多东西值得你学习。技术本身讲得再好，培训过后也大概率会被遗忘。留下来的只有什么呢？只有那些你自己经历过的东西：你练了得到反馈的习题、你在课堂提出又得到肯定的问题、你身处其中的大吵架、你准备充足的大纲被提出的无数质疑…

就好比友谊总是淡化，伟大友谊才永垂不朽。

可以说，这次培训打破了我以往讲 session 讲完就完没啥反馈的魔咒，让我意识到好几个事情，初步脱离了低级趣味，成为了一个更高尚的人：

* 讲授新技术最好的方式是**学习者中心**和**练习**。理论的东西，你讲不如他讲；实践的东西，他讲不如动手练习。讲师只是个观察者和反馈者，给予反馈、演示最佳实践、安排刻意练习
* 学习新技术最好的方式是**讲课**、**吵架**并**成立神教**。一个东西，没把大家讲会就说明没掌握；一个技术，不观点鲜明地吵个架说明没什么学习的价值；一门课讲完，不组织一个神教就不如不讲。讲师热情做如是观
* **向学习者学习**。这届同学捣鼓机器学习、捣鼓设计模式、质疑 TDD，其实是很优秀的。作为讲师，会的技能不应该是个终点，而应该不断学习精进

**不足**。时间控制不太好，有些关键点没讲全，观察不足。

## 课程安排和设计

整个课程的时间结构是由思沃学院设计的，大致是下面这样。跟敏捷实践一样，领会精神，在实践中加以改进调整：

|     时间      | 计划                 |
| :-----------: | :------------------- |
| 09:00 - 09:20 | 站会                 |
| 09:30 - 10:20 | 前一天的 code review |
| 10:30 - 11:30 | 早上课程             |
|       -       | 午休                 |
| 13:00 - 15:00 | 下午课程             |
| 15:00 - 18:00 | 练习、session 分享   |
| 19:00 - 23:00 | 晚间作业时间         |

整个教学课程的设计思路主要是两点：**学习者中心**和**反馈**。反馈体现在课程的方方面面，比如 code review 对作业的反馈、每周 retro 的反馈、课堂上随时提问的反馈、课堂上结对练习的反馈…学习者中心大概体现了课堂反转的模式，不是由讲师主讲，而是由学员课上课后的练习、主动的 session 分享等组成。上下午三个小时左右的授课时间，也是以学习者中心的思路来设计课程：

1.  (15min) 讲概念，讲师讲或同学主动提问、分享
2.  (20-30min) 布置练习
    * 演示（可选）
    * 学生练习
3.  (20-30min) 总结
    * 学生演示：由同学和讲师点评好习惯和改进点
    * 讲师演示最佳实践
4.  (15-20min) 学生再做一遍

一次循环大概 1 个半小时的样子。要点如下：

1.  演示部分，总结很重要。需要学生自我观察、对比别人的做法，讲师做必要的补充和纠正。主要目的是使学生明白**做得好的**、**可以改进的**、**问题其他的解决方案**
2.  学生演示做完后，讲师可以演示下最佳实践，比如 tasking、TDD 这种课，就可以对 TDD 的粒度、红绿时机、提交频率、提交信息等做一定程度的引导和最佳实践展示
3.  「再做一遍」的理论基础是反馈和刻意练习。强调学生上一把做得好的要保持，重点在改进项要留意。我都羡慕这样的刻意练习~
4.  「再做一遍」部分极其重要但比较耗时，所以两节课我们采用的方式都是：3 个小时大概分成 1+2 两部分~~大家都知道我拖堂~~，上部分做一个极其简单的题目（「打印成绩单」和「斐波那契数列」），主要在暴露和搜集问题；下部分再做一个更加复杂的例子（「POS 鸡」和「FizzBuzz」），强调要改进上部分暴露出来的问题

## Tasking 授课大纲

### 知识体系

![Tasking Mindmap](https://user-images.githubusercontent.com/11895199/45260147-fe60ca80-b411-11e8-9634-71cdb44b06c0.png)

![Tasking Mindmap 2](https://user-images.githubusercontent.com/11895199/45260255-9790e080-b414-11e8-93b1-f9c869fba1ce.png)

记得课上没有讲得很细致的一个问题是，关于设计的问题。有同学提出，tasking 出来的东西很函数式，很不 OO。用函数式还是 OO，这其实是个设计的问题。所以问题是，是否应该提前设计，设计应该什么时候发生？

**应该适度提前想好设计**。这个点想清楚了，实现方案才是相对合理的，基于此方案进行 tasking 的输入输出也才不至于大翻新。并且，**设计应该发生在做任务分解时**，因为[任务如何分解，与技术架构和你的设计是相关的][design during tasking]。

### 授课大纲

* 讲基本的 tasking 思路：为何要做，如何做输入输出分解，数据如何表示
* 练习 I：「打印成绩单」
* 让同学分享一波，可以展示出：
  * 不同画法
  * 对数据内容、格式的强调方式
  * 结构化输入、非结构化输出过程的必要性
  * 中间思维是否真的可视化出来了
  * 图作为设计思路交流工具的可视化作用
* 展示最佳实践
* 练习 II：「POS 鸡」- 这波难一点，复杂一点，练习强度和牵涉问题更多
* 让同学互相 review，讲师辅助讨论
  * 输入输出不同结构会影响 tasking，所以 tasking 的时候要不要考虑实现/设计：这个例子没有任务分解，直接就是 tasking，所以设计要考虑；实现一般不考虑都有解；
  * 实际项目上输入输出不明显的怎么 tasking？第一，输入输出一般是明显的，就是数据嘛，只是到哪儿去的问题；第二，这个 tasking 模型确实只是考虑了最简单的输入输出，对于实际项目，我们有更强大的增强思维框架——引出「六何法/5W1H」
  * 实际项目会有时间让你 tasking 吗？这个事是要做的，但是你一做 2、3 个小时那肯定是不会让你做的，所以速度要提高。怎么提高呢，你需要数据指导+刻意练习——引出「PDCA」
  * 复杂项目怎么做 tasking？肯定不是只有输入输出吧？问得好，没错。从「业务需求」到技术层的「输入输出」，中间是有个思维过程的，它需要把业务等价地拆分成更小的、具备输入输出的子任务。这项技术就是——引出「任务分解」
* 讲任务分解，以一个例子 demo 做法（当时用的是一个「注册页面」的例子）
* 讲 PDCA —— 如何刻意练习、反馈精进
* 讲六何法 —— 更精细的分析框架

这节课总结下来，需要注意的点在：

1.  开场部分。需要把「为啥要做 tasking」的原因更好地表明，可能需要改变干讲的方式
2.  第一次练习部分。是否需要把最佳实践先简单示范一下，引导一下大家的 tasking 方法？现场我*忘了*做这步，但发现让 2 位以上的同学来展示各种的 task 方法、各自具备和缺失的元素，会更有利于大家理解为什么要用「最佳实践」的做法
3.  练习和展示部分花费的时间一般会比 20-30 分钟扩张个一倍左右。主要是讨论。要利用好讨论。要讲的东西，是可以从讨论中延伸出来的，而且更容易被接受；也要准备好，补充讨论里没涉及到但必要讲的东西

## TDD 授课大纲

### 知识体系

![TDD-1](https://user-images.githubusercontent.com/11895199/45469336-a270ab80-b75b-11e8-9892-8dd01a4ba5b7.png)

![TDD-2](https://user-images.githubusercontent.com/11895199/45468989-072b0680-b75a-11e8-8835-6c791e0e727e.png)

### 授课大纲

就这次课程而言，鉴于同学们已经在 TWU 上过 TDD 的课程了，所以关于 TDD 的理论部分可以由同学们来回顾，课程本身侧重于练习，并解答同学们对于 TDD 的一些疑问。上课前，我列出来的几条目标为：

1. **简要回顾 TDD 的一些根本问题：三原则、五步法及实践**
2. **解答同学们的一些疑问**。质疑声音是必须回答的
3. **让同学动手实践 TDD，亲身感受好处和操作过程中的细节**
4. **展示一下 TDD 的力量：小步提交、快速反馈、最小实现、节奏感、副屏测试、live templates**

课程的设计思路仍然是以学习者为中心。

* 回顾根本问题：**TDD 的好处、三原则、五步法**。这部分由同学来总结，讲师辅助回答
* 列课程期望：让同学自由提出关于 TDD 在实践应用中的困惑、质疑
* 练习 I：fibonacci 数列 - 看掌握情况决定后续习题难度安排
* 让同学分享一波收获和不足，讲师做适当补充。重点关注：
  * 有没有最小实现？是不是容易3分钟没做完全 `git checkout .`
  * 有没有小步前进？出了问题是直接 `gco .` 还是陷入调试？
  * 有没有快速反馈？有没有经常运行测试？
  * 有没有一次做太多事情？刚写完一个挂掉的测试又同时进行了重构？
* 回顾 I：根本理论基础——三原则，五步法。结合实践体会
* 演示最佳实践：demo 一下做法，展示下小步提交、快速反馈、最小实现、快捷键、节奏感等要素
* 练习 II：FizzBuzz。强调练习 I 中总结的收获和不足，收获保持、刻意练习不足
* 回顾 II：一般可以明显看到不足被纠正强化的现象。同时由于例子更加复杂，往往会衍生出来更多的问题。请同学补充疑问，并与上面疑惑做统一解答
* 疑惑解答的部分，顺便引出以下知识点。如有可能，让同学自主思考并思考答案；如没人提问，可由讲师做最后补充
* 延伸概念简要回答：
  * 好测试的特征
  * 测试金字塔
  * mock & stub
* TDD 的缺点

![TDD-three-principles](https://user-images.githubusercontent.com/11895199/45488391-de276780-b793-11e8-849b-4c73493eec6d.png)

![TDD-five-steps](https://user-images.githubusercontent.com/11895199/45489560-22683700-b797-11e8-8e75-12263b0853cd.png)

在搜集疑问的过程中，同学提了如下问题。都是比较具体的实践问题，还是挺棒的。由于问题比较杂，现场的时候我按照「基本理论&实践手法」、「更具体的项目问题」、「复杂场景」几个层级把问题归了类。在做完练习 II、进入回顾 II 的部分时，尝试与同学一起结合练习经历解答「基本理论&实践手法」部分的问题。然后再统一回答更复杂的「更具体的项目问题」、「复杂场景」等问题。

```markdown
* 写测试浪费时间
* 先写测试和后补测试有什么区别？为什么不能后补测试？
* 为何一定要最小实现？控制不住步子，一不小心就迈得太大步也不行吗？
* 改了需求就要改测试，是否浪费时间？
* 真的能一步步驱动出设计来吗？是否需要提前架构？
* 复杂场景怎么先写测试？覆盖率如何保证？
* 质疑 TDD
```

在引导的过程可以综合采用鼓励+点名+问封闭式问题等方式。从现场来看效果还是挺不错的。除此之外，我还准备好回答以下激烈问题，结果没有人问：

```markdown
* TDD 神教是不是太极端了？
* 公司真的大家都在用 TDD 吗？我怎么看见很多都不在用呢？
* 任何场景任何地方都适合用 TDD 吗？
* mock 真的有意义吗？我听到很多人都说尽量不要 mock？
* TDD 就没有缺点吗？
* TDD 一些原则听起来非常极端，真的要遵循到极致吗？
* 质疑 TDD。不为啥，就是质疑
```

其实实践起来，很多问题对着原则找都能解决，大家最关心的就是两个问题：

* 一些实践（比如最小实现、小步提交、没有红测试不写实现、测试刚好挂掉、实现刚好通过）是否真的要100%照搬遵循？
* 我为啥要学 TDD？

第一点在与同学讨论、回答疑问的时候重复强调得比较清楚：当然不必要。TDD 能给你的是，当你大步不了时，依然能采用小步的步子安全前进；如果你技术熟练了，实践熟练了，大步当然没有问题，甚至你先写实现再补测试能补出优秀的测试来也没问题。神教之极端，还是在于保护大多数人。

第二点，不学伤害公司嘛。你看 XP 和敏捷有啥区别呢？一个要学，一个不用学，来搞个培训就给你发证。企业搞敏捷，看重的还是频繁上线，频繁到可以两周发布一次就基本满足需求了。这个粒度下，持续集成是锦上添花，自动化部署是锦上添花，TDD 和重构也是锦上添花。主要是抄敏捷的三大会、故事墙这些项目管理实践，技术实践通过原来加班、人肉的节奏也能凑合。剥离了技术实践的「敏捷」，其实就是另外一种流程，它提升了企业的发布频率，但对于个人来说和瀑布也没啥本质区别。什么样的公司对敏捷有真正技术实践上的动力和需求呢？必须是有大量用户流量的、质量体验问题直接与钱挂钩的、有技术能力的、有资源并且愿意投入的大厂。

所以话说回来，为啥要学 TDD 呢？首先 TW 是满足于两周一次上线的公司吗？你个人是满足于两周一次上线的开发者吗？

[郑大烨校]: http://weare.thoughtworkers.org/category/%E7%94%9F%E6%B4%BB/
[dujuan.in]: https://dujuan.in/
[熊节]: http://gigix.thoughtworkers.org/
[design during tasking]: https://ethan.exthoughtworkers.tech/#/post/2017-06-18-tdd-series-4-tdd-is-an-art-not-scientific
