现在我正在重构旧的Java项目,现在遇到了一些问题。
它定义了一个类名DataHolder
,它从Map<String,Object>
扩展,并作为参数传递给类和方法。
public class DataHolder extends Map<String,Object> {
}
public class Cls1 {
public void execute(DataHolder data) {
data.put("key1", someData);
}
}
public class Cls2 {
public void execute(DataHolder data) {
Object someData = data.get("key1");
}
}
...
有超过30个类和100个方法正在使用此DataHolder
实例,对于大多数实例,它是唯一的参数。
当一个方法生成一些其他方法可能需要的值时,它只是将它们放入数据持有者。如果它需要一些,它只是从数据持有者那里得到它们。
代码难以阅读,测试甚至重构。我正在尝试重构它,但不知道该怎么做。
有什么好主意吗?
答案 0 :(得分:2)
DataHolder似乎是一种单例,它确实产生了理解和测试代码的问题。可以用来摆脱单例的一般原则可能适用于您的用例。以下是应用于执行方法的两个示例。
Cls2#execute
只需要data.get("key1")
- 重构过程的第一步就是将其传递给方法:
cls2.execute(dataHolder);
//becomes
cls2.execute(dataHolder.get("key1"));
这样您就可以删除所有“只读”依赖项。对于需要多个值的更复杂的示例,传递包含所有相关信息的对象(希望比DataHolder更专业化)可能是有意义的。
至于Cls1#execute
它基本上创建了一个新值,所以应该返回它而不是将它放在一个全局数据结构中:
public void execute(DataHolder data) { data.put("key1", someData); }
应该是:
public Object execute() { return someData; }
一篇非常有趣的文章:Google guide on Writing Testable Code。
答案 1 :(得分:1)
这是一个元问题所以我不会在这里写出实际的代码。
一种方法是使用Singleton模式。基本上,你有一个类,它将静态字段中的DataHolder对象初始化,并在每次需要时返回该对象。
您可以删除函数中的所有DataHolder参数,并在开始时DataHolder data = DataHolderSingleton.getInstance()
进行类似的调用。
如果对Singeltons的使用不清楚或者这种方法的好处我会尝试扩展这个答案。