08 09 10|TDD中的测试

TDD 学习笔记 | 极客时间 | 徐昊·TDD 项目实战 70 讲

TDD 不能做什么?

  • 不能窥探方法内是如何实现的,例如对于一个排序算法,只能验证结果是否符合预期,不能验证使用了哪种算法(冒泡、插入等)
  • 不能求解自己不会的问题,例如:
    • 自己没有思路的算法题
    • 破解世界七大数学难题获得高额奖金

TDD 是一种架构技术

  • 从“驱动”的角度讲,TDD 并不是一种编码技术,它无法驱动你写出你不会实现的代码。
  • TDD 是一种架构技术,它能通过测试与重构,驱动单元的划分以及功能的归属,因而是一种更为落地的架构软件的方式。
  • 在 TDD 中,重构是和测试一样重要的驱动力,驱使我们得到更好的架构和更清晰的代码结构。

常用的重构手法

以下操作应该被看作修改代码的基本功,而不是重构 如果无法借助自动化重构工具高效修改代码,那么 TDD 带来的效率将会大打折扣。而无法支持这几个核心手法的 IDE,也不足以支撑 TDD 的实施。

语义化的查找替换(Semantic Find and Replace)

  • 在不破坏现在代码结构的前提下,完成查找替换
  • 提取方法(Extract Method)
  • 内联方法(Inline Method)

通过提取 / 合并单元进行重架构(Extract and Merge Units)

  • 在提取方法的基础上,我们可以进一步将提取出的行为从当前对象中分离出去,也就是提取对象(Extract Object)
  • 一旦提取出对象,我们就能通过类内字段(Field)、参数(Parameter)等方式,不再直接引用当前对象上下文,从而将其与当前对象上下文分离
  • 对应地,我们可以使用的重构手法有引入字段(Introduce Field)、引入参数(Introduce Parameter)等

使用多态替换条件

  • 通过策略模式消除 if else

重构到模式(Refactoring to Patterns)

  • 将架构上的坏味道替换为设计模式(Design Pattern)。
  • 这是一种更有效的架构软件的方法,用公认的好设计(模式)替换了公认的不好的设计(坏味道),还能满足功能的需求,必然能是更好的架构(而不用虚无缥缈地归结于“品味”或“经验”)。
  • 对于 TDD,行业中存在这样一种困惑:从功能测试出发,逐步完成软件开发,这或许没问题。但架构怎么办?
    • 实际上,红 / 绿 / 重构循环中的重构就是解决架构问题的。
    • 只不过架构并不是预先设计的(Upfront Design),而是在完成功能的前提下演进而来的,因而也称演进式设计(Evlutionary Design)。
  • 通过重构到模式演进式地获得架构,是一种实效主义编码架构风格(Pragmatic Coding Architect)。

⭐️⭐️⭐️⭐️⭐️ Joshua Kerievsky 在 2004 年写过一本书,《Refactoring to Patterns》(中文版《重构与模式》)。这本书的价值远被低估了,是关于软件架构非常重要的著作!

最晚尽责时刻(Last Responsible Moment,LRM)

  • 其在信息不足的情况下做决定,不如延迟到信息更多,或是不得不做出决策的时机再决策。
  • 这种策略的重点在于,在保持决策有效性的前提下,尽可能地推迟决策时间
  • 在架构愿景不清晰时,能让我们不必花费时间进行空对空的讨论,可以尽早开始实现功能,再通过重构从可工作的软件(Working Software)中提取架构。
  • 这种方式也被称作 TDD 的经典学派(Classic School)或芝加哥学派(Chicago School)

伦敦学派(London School)

  • 适用于架构愿景已经比较清晰的情况
  • 一种利用架构愿景分割功能上下文,然后再进入经典模式的 TDD 方法
  • 对于复杂的场景,可以极大简化构造测试的时间

经典学派和伦敦学派

  • 都是 TDD 中都需要掌握的基本功
  • 在功能上下文内,以经典学派为主
  • 而跨功能上下文时,可以使用伦敦学派对不同的功能上下文进行隔离
comments powered by Disqus