Конструктор Инъекция, дизайн для тестируемости
У меня есть этот код (вы, вероятно, можете игнорировать, что это код 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;
}
В этом коде я рассматриваю возможность добавления большего количества объектов, используемых этим классом. Я продолжаю просто добавлять больше аргументов и передавать их в конструктор. Возможно использовать настройку впрыска?
Но, по словам Миско, это тоже кодовый запах.
http://misko.hevery.com/code-reviewers-guide/
"Объекты передаются, но никогда не используются напрямую (используются только для получения доступа к другим объектам)"
6 ответов
Наличие слишком большого количества аргументов в вашем конструкторе является признаком того, что у вашего класса слишком много обязанностей. Если вы просто устанавливаете поля в своем конструкторе, посмотрите, не используются ли некоторые из этих полей только подмножеством методов в классе. Это признак того, что ваши аргументы и методы могут быть разделены на более мелкие классы с более сфокусированной ответственностью.
Поскольку вы хотите очистить свой код и улучшить его тестируемость, возможно, вы можете пойти на инициализацию сеттера. Таким образом, у вас будет более чистый конструктор для вашего объекта. Также проще протестировать код, если вы можете установить только "некоторые" из его полей, а не все. Тесты становятся более читабельными.
Стоит взглянуть на Spring, потому что, даже если вы не используете его, вы можете извлечь выгоду из руководящих принципов этой платформы.
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;
}
}
Согласился с Биллом, что это может указывать на слишком много обязанностей. Но если вы действительно не можете снять эти обязанности, представьте объект параметров - один из способов очистки занятых конструкторов / методов, подобных этому.
Я не думаю, что мы должны игнорировать, что это свинг-код. Графические интерфейсы объединяют несколько разрозненных объектов организованным способом. Я бы посоветовал вам серьезно подумать о рефакторинге, если вы обнаружите, что поддерживаете несколько конструкторов, потому что будет очень непонятно понимать, что есть, а что нет. Но если вы помещаете семь компонентов в какой-то организационный шаблон, это не обязательно плохая идея делать все это в конструкторе, если он однозначно делает каждый аргумент.
Если вопрос "У этого класса слишком много проблем?" перестаньте спрашивать "Каковы признаки того, что у класса слишком много забот?" Почему бы не спросить: "Что беспокоит этот класс?" Если ответ прост: "Он объединяет несколько элементов формы в одно представление", что я (и, как следствие, другие стороны, просматривающие ваш код) логично предположил бы, то перестаньте беспокоиться о косметике, такой как конструкторы. Это достаточно очевидно в этом случае. Добавление большего количества классов просто запутает это.
Вопрос оформлен как творческая / механическая проблема, но, как указывалось во многих предыдущих ответах, это на самом деле проблема дизайна.
Я думаю, что переоценка схемы композиции объектов может быть более полезной в долгосрочной перспективе, например, перераспределение абстракции так, чтобы BrowserFrame состоял из разделов (например, AddressSection, ActionSection, InputSection, FeedbackSection и т. Д.) Вместо отдельных объектов Swing,
Вы также можете рефакторировать чрезмерную параметризацию конструкции BrowserFrame, используя вместо этого подклассы.