我有一些回调接口:
public interface FooCallback {
boolean doSomething(Foo fooArg);
}
在服务层的方法中被实现为匿名块:
public void methodA(Bar barArg) {
// some bussiness logic like parsing Foo object from Bar for example
FooCallback cb = new FooCallback() {
@Override
public boolean doSomething(Foo fooArg) {
// some calculation with fooArg and barArg and return boolean value
}
}
saveBar(barArg, cb);
}
saveBar是同样在该类中的方法,用于将Bar对象保存到数据库中的方法取决于doSomething
的{{1}}方法的结果;
FooCallback
我的服务类中有很多类似public void saveBar(barArg, cb) {
// get Foo object from database
if (cb.doSomething(fooFromDB)) {
// save barArg into DB
} else {
// antother logic
}
}
的方法。匿名代码块也是不好测试的。您能告诉我类似实施的最佳实践是什么吗?我知道将内容从methodA
移到另一个方法,但这意味着每个方法都是self methodCallback。你怎么看?我正在使用Java。谢谢你的建议。
答案 0 :(得分:0)
您是对的,匿名块样式会使测试复杂化,这就是为什么我在这种情况下不推荐这样做的原因。如果您想尽可能地接近于您概述的方法,请创建一个实现FooCallback的类,然后将该类的实例提供为包含methodA()和saveBar()的任何类的构造函数的参数。您不会丢失任何东西,并且可以选择在测试过程中为模拟实例提供doSomething()的不同实现。
我说如果您想 ,因为我不确定给定示例中整个FooCallback方法到底提供了什么优势。如果您完全放弃该类及其匿名实现,并且仅让methodA()返回一个用于确定是否应使用saveBar()的布尔值,似乎一切都会更好地组织。为什么要创建一个仅包含一个返回布尔值的方法的整个接口,而不是直接在FooSaveHandler或所有此类中直接处理该接口?
编辑以附带注释:
如果您有在不同情况下需要在Foo上调用的A-X不同的逻辑集,并且您有条件地调用这些单独的A-X方法的逻辑,那么为什么不更简单呢?
handleFooBarLogic(Foo foo){
boolean saveBar = false;
//Logic that originally called methodA()
if(something) {
return saveBar = doSomethingOriginallyFromMethodA(foo);
}
//etc.
return saveBar
}
saveBar(Bar bar) {
//Just saves a Bar
}
如果我们说的是最好的(或至少是更好的)做法,则saveBar()所做的不仅仅是保存Bar,而且到那时为止,应该已经确定需要保存Bar。从该前提向后工作,完全不需要回调,也不需要接口。您最终会得到很大的鸣叫if语句,但是至少事情更容易测试,并且最终更容易理解正在发生的事情。