如何重构使用遍布各处的地图的代码?

时间:2014-01-04 13:42:38

标签: java map refactoring

现在我正在重构旧的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实例,对于大多数实例,它是唯一的参数。

当一个方法生成一些其他方法可能需要的值时,它只是将它们放入数据持有者。如果它需要一些,它只是从数据持有者那里得到它们。

代码难以阅读,测试甚至重构。我正在尝试重构它,但不知道该怎么做。

有什么好主意吗?

2 个答案:

答案 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的使用不清楚或者这种方法的好处我会尝试扩展这个答案。