演化架构与紧急设计: 测试驱动设计,第1部分 - 编程入门网
构与紧急设计: 测试驱动设计,第1部分(7)
时间:2011-05-18 IBM Neal Ford
这段代码允许测试通过,但是再考虑一下,它十分糟糕!在使用测试研究实现 代码的方法时有时会出现这种情况。这段代码中哪些部分非常糟糕?首先,它非 常长而且复杂,并且它也有 “不止一件事” 的问题。我的本能指引我返回 int [],但是它给底部的代码增加了很多复杂度而没有给我带来任何好处。开始过多 地考虑怎样做才能使将来可能调用此方法的方法更方便,将令您遭遇危险的处境 。您需要一个非常有说服力的理由才能在此接合点添加复杂的内容,而我还没有 那样的理由。查看这段代码,我发现 factors 也应当作为类的内部状态而存在, 使我可以分解该方法的功能。 测试显现的有益特性之一是真正内聚的方法。Kent Beck 在十分有影响力的 Smalltalk Best Practice Patterns 一书中提到了这一点。在该书中,Kent 定 义了一种名为组合方法(composed method)的模式。组合方法模式将定义三条主 要语句: 把程序划分为多个可执行一项可识别任务的方法。 把方法中的所有操作保持在同一个抽象级别 这将自然而然地得到拥有许多小方法的程序,每个小方法都只有几行代码。 组合方法是 TDD 提倡的有益设计特性之一,而我已经在 清单 11 的 getFactors() 方法中明显违反了这种模式。我可以通过执行以下步骤来修正: 将 factors 提升为内部状态。 将 factors 的初始化代码移到构造函数中。 去掉对 int[] 代码的转换,等到它变得有益时再处理它。 添加 addFactors() 的另一项测试。 第四步非常微妙但是很重要。编写出这个有缺陷的代码版本揭示出分解的第一 步并不完整。隐藏在这个长方法中间的 addFactors() 代码行是可测试的行为。 它是如此地微不足道,以至于在第一次查看问题时我都没有注意到它,但是现在 我看到了。这是经常出现的情况。一个测试可以指引您进一步将问题分解为越来 越小的块,每个块都是可以测试的。 我将暂停处理 getFactors() 的比较大的问题,而处理我新遇到的小问题。因 此,我的下一个测试是 addFactors(),如清单 12 中所示: 清单 12. 测试 addFactors()
清单 13 所示的测试中的代码本身十分简单: 清单 13. 添加因子的简单代码
演化架构与紧急设计: 测试驱动设计,第1部分(8)时间:2011-05-18 IBM Neal Ford我运行我的单元测试,充满信心地认为我会看到表示测试成功的绿条,但是却 失败了!这样一个简单的测试怎么会失败?根本原因显示在图 2 中: 图 2. 测试失败的根本原因 我期望看到的列表有 1, 2, 3, 6 几个值,而实际返回的是 1, 6, 2, 3。那 是因为我将代码改为在构造函数中添加 1 和数字本身。这个问题的一种解决方案 是,始终在假定应先添加 1 和该数字的情况下编写期望的代码。但是这是正确的 解决方案吗?不是。问题更为基础。因子是不是一个数字列表?不是,它们是一 个数字集合。我的第一个(错误)假定导致我使用一列整数作为因子,但是这是 个糟糕的抽象。通过将我的代码重构为使用集合而非列表,我不但解决了这个问 题,而且优化了整个解决方案,因为我现在使用的是更精确的抽象。 如果在让代码影响您的判断力之前编写测试,这正是测试可以揭露的有缺陷的 思维方式。现在,由于这项简单的测试,我编写的代码的整体设计更好了,因为 我已经发现了更合适的抽象。 结束语 到目前为止,我以处理完 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |