我们的团队获得了进一步维护和开发的遗留系统。 因为这是真正的“传统”东西,实际上,真的是非常少量的测试,而且大多数都是垃圾。这是一个带有Web界面的应用程序,所以有容器管理的组件以及普通的java类(没有绑定到任何框架等),无论何时你想在哪里“new-ed”。
当我们使用这个系统时,每次触摸给定的部分时,我们都会尝试将所有内容分解为更小的部分,发现并重构依赖项,推送依赖项而不是将它们拉入代码中。
我的问题是如何使用这样的系统,打破家属,使代码更可测试等?何时停止以及如何处理?
让我举个例子:
public class BillingSettingsAction {
private TelSystemConfigurator configurator;
private OperatorIdDao dao;
public BillingSettingsAction(String zoneId) {
configurator = TelSystemConfiguratorFactory.instance().getConfigurator(zoneId);
dao = IdDaoFactory.getDao();
...
}
// methods using configurator and dao
}
这个构造函数肯定做得太多了。另外为了进一步重构测试它需要用PowerMock等做一些魔术。我要做的就是把它改成:
public BillingSettingsAction(String zone, TelSystemConfigurator configurator, OperatorIdDao dao) {
this.configurator = configurator;
this.dao = dao;
this.zone = zone;
}
或仅为依赖项的setter提供构造函数设置区域。
我看到的问题是,如果我在构造函数中提供依赖项,我仍然需要在某处提供它们。所以它只是将问题提升一级。我知道我可以创建工厂来连接所有依赖项,但触摸应用程序的不同部分将导致每个工厂有不同的工厂。我显然无法立即重构所有应用程序并引入,例如那里的春天。
公开setter(可能提供默认实现)是类似的,而且它就像添加代码仅用于测试。
所以我的问题是你如何处理?如何使对象之间的依赖关系更好,更易读,更可测试而无需一次性完成?
答案 0 :(得分:3)
我刚刚开始阅读Michael Feathers的“有效使用遗留代码”。 这本书基本上是你的问题的答案。它提供了非常可操作的“小块”和技术,可以逐步使遗留系统得到测试,并逐步改进代码库。
导航可能有点令人困惑,因为本书通过指向特定技术来引用自身,几乎从第1页开始,但我发现内容到目前为止非常有用。
我与作者或类似的东西没有任何关系,只是我面对类似的情况,发现这是一个非常有趣的资源。
HTH
答案 1 :(得分:2)
我试图建立一个像童子军规则这样的规则:当你触摸文件时,你必须稍微改进它,除了实现你想要实现的任何东西。
为了支持你可以
就这些改进达成一致的固定时间预算,例如2小时的特色工作,我们允许1小时的清理。
有可见的指标显示随时间的改善。通常很简单的事情,如平均文件大小和测试覆盖率就足够了
列出你想要更改的内容,至少是为了更大的内容,例如“摆脱TelSystemConfiguratorFactory”跟踪你已经在哪些任务上工作,并优先处理已经开始的新事物。< / p>
无论如何,请确保管理层同意您的方法。
在更技术方面:你展示的方法是好的。在许多情况下,我会考虑第二个构造函数提供所有依赖项,但通过带有参数的新构造函数。不建议使用其他构造函数。当您触摸该类的客户端时,请使用新的构造函数。
如果你要使用Spring(或其他一些DI框架),你可以先从Spring上下文中获取一个实例作为中间步骤来替换对static Factories的调用,然后再通过spring实现它并注入所有依赖项。< / p>