Day 19 「完美不完美」TDD 的困难之处


图片截自联合新闻网

笔者最近在看一个邀请影视明星来进行专业运动的节目:「全明星运动会」。节目是蛮有趣的,这却让笔者不禁思考,为什麽真正专业的运动员,甚至是国手,上场比赛时我们性质缺缺,但这些不专业,甚至是连入门程度都不到的明星们进行的运动竞赛,我们却看得这麽津津有味?我是不知道啦,反正想不通也就算了,看起来这个节目应该也就这两季了…

在上一篇中,我们讨论了 TDD 的基本操作手法与运行原理,花了一些篇幅来解释它能解决什麽问题,以及为什麽。至此,读者也许不免怀疑:「既然 TDD 这麽棒,那为什麽不是每个人都要用?为什麽我用起来反而很不顺?」

没错,TDD 本来就不是一个完美的 Solution,要想享受它的好处,是得付出一点代价的。

今天我们来聊聊看,究竟 TDD 这套方法,与 Kent Beck 的 TDD 这本书,到底发生什麽事。

本文主要整理自 Teddy Chen 的 「搞笑谈软工」、 91 的培训课程内容,与拙作「Kuma 老师的软件工程教室」中的一些论述,并加入笔者现在的想法,详情请参阅 Reference。

活用 TDD 的门槛

笔者认为,TDD 要入门是不难的,只要严守 TDD 规定的流程来走,不要急着一次跨太大步,理应不会出什麽乱子。然而,TDD 难也正是难在不容易「严守流程」。为什麽?因为「要求的自主管理太严格」。

怎麽说呢?读者如果自己有实际操作过一阵子 TDD,并搭配 Kent Beck 的 TDD 一书来学习,应该不难发现,要做到 Kent Beck 那样出神入化其实没那麽容易,好像还差了点什麽。笔者毕竟也只是一个普通的 RD,所以也有这种感觉。经过一番研究,笔者认为要想活用 TDD,以下能力是需要的:

需求访谈能力

TDD 提倡的是「避免浪费」,我们做了很多事都在避免程序码的浪费,因为多打字就是多浪费时间,但回到源头,如果我们对使用者的现况、困难,与期待都搞不清楚,只会整天要求使用者「确认需求」、「订好规格」,就算我们做得再快再好,也解决不了使用者的问题,最後还是得重做。因此,「避免浪费」,要从好的需求访谈开始。

建模能力

了解了使用者的问题後,下一步就是「解释给 RD 听」。什麽,你说你自己访谈自己开发?那的确是会好一点,但也还是省不了在脑中(或在纸上)建立一个「模型」,来描述使用者现在的 context 与期待未来的新 context 的步骤。这是开发时重要的依据,必须时时参考着做,不然晚点随着开发的进行,RD 很容易掉入细节,而忘记自己走到哪去,因此走了歪路,再次造成浪费。如果做到一半发现模型有变,那就改没关系,但不能没有。

大家在看 Kent Beck 的书时,肯定觉得作者超级强的,没有画图、没有草稿,就这样一步一步,慢慢把东西给做出来,但自己做时却发现完全不是那麽一回事。为什麽(除了因为对方是大师以外)?因为 Kent 在书中虽然没写,但笔者认为他不可能对这东西的成品样貌完全没有一点点预期。这个预期可能很模糊,也可能与最终成品的样貌很不一样,甚至可能在开发过程中不断改变,但他一定有个预期,否则程序码很难发展下去。因此,再模糊、再抽象也好,建立一个模型是必须的,笔着认为这项能力应该要有,否则 TDD 不容易做得好。

分析、提 Solution,与列测项的能力

有了模型以後,我们就要来进行分析,并提出 Solution,并决定好这个 Solution 必须要「在什麽条件下,有什麽表现」。这对後续写测试来说很重要,对 TDD 来说更重要,因为 TDD 就是「测试」在驱动开发的嘛,测试好写当然重要!一样,这些测项如果列得好又准又小,又能彼此独立,TDD 执行起来就能如虎添翼。反之,You know the rest...

安排先後次序的能力

有了测项,我们要先来做一件事:决定「谁是第一个」。列得好的测项,每个测项都代表一个特性。虽说最终都得全部完成,但其实测项完成的先後顺序定得好,可以让每一步都走得小小的,能够更符合 TDD 的原则。因此,安排先後次序的能力,也是 TDD 要做得好,很重要的一环。

维持抽象思考的能力

商业逻辑是抽象的,coding是细节的。RD 的工作就是整天在抽象与细节之间跳来跳来跳去。跳久了,总不免不小心偏离了抽象而不自觉,这是程序的方向就可以不小心偏了。抽象思考的能力,指的是随时搞得清楚这行 code 是为了什麽而打的,亦即,「15 秒前你决定要实现的逻辑,跟你现在正在打的这行 code,是不是同一件事」。一旦偏离,浪费就出现了。因此,为了让我们随时保持正确的 coding 方向,「维持抽象思考」是不可或缺的能力。

测试与程序的能力

在有了 Solution,也决定要先做什麽以後,就是实际把 code 与测式写出来了。这是一个「硬碰硬」的事情,没有绕开的可能性。举个例子,当你决定在这里「问 DataBase 有没有符合条件的学生,有就发通知,没有就回传 400 给前端」,或是你想要「找出这个学生的清单中,微积分最高分的前三名,如果有重考的就采较高分计算」,从你双手碰到键盘起算,到最终打出来了一份 code,中间要停下来查几次 StackOverflow?不论前面的准备做得再好,「写 code」还是一件避不了的事,因此,有好的「码农」能力还是很重要的,它一定不能成为你开发中的瓶颈。

顺道一提,「你知道 AI 现在已经能写 code 了吗?」这不是危言耸听,这是正在发生的事情。

辨识坏味道能力

TDD 要求我们「先让它 compile 能过,再让它对,再让它变好。」前两项我们可以靠 IDE 与 Unit Test 帮忙,但第三项,至少目前为止你得靠自己。你有过以下经验吗?主管指着一段 code 问你:「这里有什麽 code smell?」你呆住了,你觉得这段写得棒极了,自你生眼晴发目眉以来,你都是这麽写的,从不觉得有什麽问题。如果上述情况你经常遇到,那恭喜你,有了一个很明确的改善目标:「加强辨识坏味道能力」。

而且要赶快改善,否则你会几乎完全无法进行下一个步骤:重构。

重构能力

能指认出 code smell,下一个挑战就是重构了。你知道这里有 Data Clump 的坏味道,你知道这里违反了迪米特法则,问题是要怎麽重构?没有好的重构知识与能力,在 TDD 的过程中,就算感觉这里怪怪的,也无法很快地重构成更好的样子。因此,好的 TDD 也会需要开发者具有好的重构能力。

打字速度,含工具的使用能力

最後,这是笔者接触过的 RD 们,最常忽略的能力了。你知道这里要把方法抽成 Delegate,你知道这里要抽一个 interface 出去,并让呼叫端全部改使用 Interface。你都知道,但你要花多久才能把这件事实现?五分钟是肯定不能接受的。在 TDD 的流程中,开发者的脑筋是转得很快的。而大脑的思考最怕被中断。如果打断你思考的是你老板的电话,那没办法;如果是你自己慢得要死的手指,那就很呕了。

三秒会太短吗?十秒?三十秒够了吧?不能再长了。再长,你的思绪都会被你自己的手速中断,思绪一旦中断,要再加速就费劲儿了。是故,练习吧!


图片截自「喜剧之王」

总结

我们花了不算短的篇幅,来描述要操作好的 TDD ,你应该具备什麽能力。事实上,这些能力不是专属 TDD 的。笔者认为,所有「优秀的 RD」都应该具备以上的能力。而一旦你具备了这些能力,不要说 TDD 了,ADD、BDD、CDD、… 应该是什麽 DD 都难不倒你,到了那时,是不是 TDD 好像也不是那麽重要了。所以身为 RD,做好该做的,练好该练的,流程什麽的自然学得快、用得好。


图片截自「三个傻瓜」

谜之声:「All is well!」

Reference

  1. 『浅谈TDD系列 3/3』 — TDD在实战上真正的困难:https://tinyurl.com/8zz8c5s5
  2. 搞笑谈软工 - 为什麽看不懂Kent Beck的Test-Driven Development By Example?:https://tinyurl.com/9z3u64dc
  3. Kent Beck, Test Driven Development : By Example, Addison-Wesley Signature Series, 2002
tags: ithelp2021

<<:  [ Day 04 ] Virtual DOM ? ReactDOM ?

>>:  使用jupyterhub执行MNIST training

day30-浅写axios+完赛文

安安,搭给贺,终於来到最後一天了!(转圈d(`・∀・)b 不免俗一下还是要来讲一些心得,在挑战铁人赛...

Ruby on Rails ⾃订验证器 Validator

现有的验证器不够⽤吗?有几种⽅式可以⾃订验证器: 写⼀个⽅法,挂到 validate ⽅法上: cl...

Day36 ATT&CK for ICS - Impact(2)

T0826 Loss of Availability 攻击者尝试破坏工控设备重要的系统或元件,阻止工...

Day30 - 总结

终於来到本次铁人赛的第30天,回顾当时报名的初衷,主要原因是以前在查技术问题时,过往许多系列文帮助我...

Day 52 (JS_API)

1. API? 应用程序介面 图形库中的一组API定义了绘制指标的方式,可於图形输出装置上显示指标。...