构造函数注入,可测试性设计

时间:2009-12-18 15:53:58

标签: java testability constructor-injection

我有这个代码(你可能会忽略它是Swing代码),但我的构造函数中通常会有太多的参数。我应该使用模型bean类,然后在构造函数中传递该对象吗?

public BrowserFrame(final JTextField url, final JTextArea response, final JTextField command, final JButton actionButton) {

    this.urlField = url;
    this.responseArea = response;
    this.commandField = command;
    this.actionButton = actionButton;

}     

在此代码中,我正在考虑添加此类使用的更多对象。我是否只是添加更多的args并在构造函数中传递它们。可能使用设定注射?

但根据Misko的说法,这也是代码味道。

http://misko.hevery.com/code-reviewers-guide/

“传入对象但从不直接使用(仅用于访问其他对象)”

6 个答案:

答案 0 :(得分:2)

在构造函数中包含太多参数表明您的类有太多责任。如果您只是在构造函数中设置字段,请查看其中某些字段是否仅由类中的方法子集使用。这表明你的论点和方法可以分成更小的类,责任更集中。

答案 1 :(得分:0)

由于您希望清理代码并提高其可测试性,因此您可以进行setter初始化。这样你就可以为你的对象提供一个更清晰的构造函数。如果你可以只设置其中某些字段而不是全部,那么测试代码也会更容易。测试变得更具可读性。

值得研究Spring,因为即使你没有使用它,你也可以从这个框架的指导中受益。

答案 2 :(得分:0)

BrowserFrame往往表示您正在扩展您不需要的类(JFrame)。那很糟糕。

我倾向于有一个关于JComponent /视图层的布局图层。

class ThingView {
    [...]
    public JTextField /*or JComponent*/ createURL() { /* or geURL */
        return new JTextField(...); // Or from a field if using get.
    }
    [...]
}

class ThingLayout {
    private final ThingView view; 
    [...]
    public JPanel createBrowsePanel() {
        JPanel panel = new JPanel();
        [...]
        panel.add(view.createURL());
        [...]
        return panel;
    }
}

答案 3 :(得分:0)

同意比尔的意见,这可能表明责任太多了。但如果你真的不能把这些责任拉出来,Introduce Parameter Object就是清理繁忙的构造函数/方法的一种方法。

答案 4 :(得分:0)

我认为我们不应该忽略这是摆码。 GUI以有条理的方式聚合几个不同的对象。如果你发现自己支持多个构造函数,我建议你认真考虑重构,因为理解什么是必要的和非必要的将是非常混乱的。但是如果你将七个组件放入一些组织模板中,那么在构造函数中完成所有操作并不是一个坏主意,如果每个参数的含义都是明确的。

如果问题是“这个课程有太多顾虑吗?”停止问“课堂上有太多顾虑的迹象是什么?”为什么不问“这堂课关注的是什么?”如果答案很简单,例如“它将几个表单元素组织到一个视图中”,这就是我(以及其他方面浏览您的代码)会逻辑地假设,然后不再担心像构造函数这样的化妆品。在这种情况下,这是显而易见的。添加更多类只会使其模糊不清。

答案 5 :(得分:0)

这个问题被认为是一个创造性/机械性问题,但正如之前的许多答案所指出的那样,这实际上是一个设计问题。

我认为对对象组合方案的重新评估从长远来看可能更有用,例如重新排列抽象,以便BrowserFrame由Sections(例如,AddressSection,ActionSection,InputSection,FeedbackSection等)组成,而不是个别Swing对象,

您还可以通过使用子类来重构BrowserFrame构造的过度参数化。