鉴于:LegacyControllerClass
扩展了MonsterFrameworkClass
(人们刚刚生活多年的一个非常令人讨厌的框架的一部分)。 Framework类具有很多魔力,从默认构造函数中的大量逻辑到反射加载类的静态块。
LegacyControllerClass
中的许多生命周期方法,它们会改变全局状态。 execute()
方法是一个千言万语,具有你能想到的所有邪恶。
public class LegacyControllerClass extends MonsterFrameworkClass {
//Life-cycle method
public void validate(){...}
//Life-cycle method
public void preExecute() {...}
//Life-cycle method
public void execute() {
//oodles of legacy code here:
// examples: call static methods of 'Util' classes
// lots of new X().y(..)
// call databases, services
// Even call super.execute()!!
// More rubbish
// More rubbish
}
}
好的,现在行动的场景是execute()方法。我正在通过测试驱动一个他们称之为“故事”的项目来向这些穷人介绍测试驱动开发。 “故事”涉及向responseProperties添加错误消息,以便视图(jsp)可以将其读取并显示。伪代码类似于:
if (error) {
Build the error message
Add the error message into the responseProperties
}
遗憾的是,这段代码必须在execute()
方法中的垃圾之间进行混淆。
我的问题是:我能做的最好的事情是什么? 我能提出的解决方案是:
rubbish1()
和rubbish2()
rubbish1()
和rubbish2()
我开始以这种方式实现它,但是MonsterFrameworkClass
实际上正在妨碍我:像静态加载,加载ResourceBundle
随机属性文件的构造函数魔法等等。
有没有其他方法来处理相同的事情?
小小的免责声明:我肯定会购买迈克尔·费瑟的“使用传统代码”并将其吞下去,但这似乎是一个悬而未决的成果。
答案 0 :(得分:1)
将垃圾重构为方法很好。现在你可以下载Powermock来模拟代码中的所有可怕的垃圾。完成模拟后,您可以测试代码。
如果你不为这个怪物添加任何东西,那就更好了。您可以通过为新内容编写自己的类来将您的功能组合成MonstrosityRubbish
(或其他)。
如果可能的话,最重要的是不要触及任何遗留代码,您可以将代码组合到其中。
所以在代码中:
private MyShinyClass yourShinyObject; // init
public void execute(Param param0) {
rubbish1();
yourShinyObject.handleError(param0);
rubbish2();
}
public class MyShinyClass {
public void handleError(Param param0) {
// your code here
}
}
如果你能设法编写这样的新东西,你将只依赖于Param
可以被嘲笑/存根,你的代码可以在不设置头发的情况下进行测试。
如果你能以功能性方式编写它,那就更好了,这样你就不必在分离的代码中操作responseProperties
:
public void execute(Param param0) {
rubbish1();
responseProperties.add(yourShinyObject.fetchErrors(param0));
rubbish2();
}
public class MyShinyClass {
public List<HopelessError> fetchErrors(Param param0) {
// your code here
}
}
当然execute()
不需要您可以传递任何您想要{/ 1}}的变量/字段的参数。