TLDR На мой взгляд, использование методов внутри конструктора является признаком плохого дизайна. Если вы не ищите совета по дизайну, тогда ответ «нет, нет ничего плохого в этом, технически говоря, до тех пор, пока вы избегаете использования неконфиденциальных методов», должно сделать все хорошо. Если вы ищете советы по дизайну, см. Ниже.
Я думаю, что ваш пример кода не является хорошей практикой вообще. На мой взгляд, конструктор должен получать только те значения, которые имеют к нему отношение, и не нужно выполнять какую-либо другую инициализацию этих значений. Вам не нужно проверять, что ваш конструктор «работает» со всеми этими небольшими дополнительными шагами - все, что вы можете сделать, это построить объект и надеяться, что все окажется в правильном состоянии. Кроме того, ваш конструктор заканчивается более чем одной причиной изменения, что нарушает SRP.
class Info {
public RoadInfo(String cityName, double lat, double lng) throws FileNotFoundException, SAXException, IOException, XPathExpressionException {
// TODO Auto-generated constructor stub
this.cityname = cityName;
this.lat = lat;
this.lng = lng;
this.path = "c:"+File.separatorChar+this.cityname+".xml";
System.out.println(path);
this.initXPath();
this.method1()
this.method2()
..
this.expr = "//node[@lat='"+this.lat+"'"+"]/following-sibling::tag[1]/@v";
this.xPath.compile(this.expr);
String s = (String) this.xPath.evaluate(this.expr, this.document, XPathConstants.STRING);
System.out.println(s);
}
Так, например, это конструктор является загрузка файла, разбор его в XPath .. если я когда-либо хотите создать RoadInfo
объект, теперь я могу сделать это только при загрузке файлов и волнуясь об исключениях. Этот класс также становится тяжело сложным для модульного теста, потому что теперь вы не можете протестировать метод this.initXPath()
изолированно, например, если у this.initXPath()
, this.method1()
или this.method2()
есть какие-либо сбои, то каждый из ваших тестовых случаев не удастся. Плохо!
Я бы предпочел, чтобы выглядеть примерно так:
class RoadInfoFactory {
public RoadInfo getRoadInfo(String cityName, double lat, double lng) {
String path = this.buildPathForCityName(cityName);
String expression = this.buildExpressionForLatitute(lat);
XPath xpath = this.initializeXPath();
XDocument document = ...;
String s = (String) xpath.evaluate(expression, document, XPathConstants.STRING);
// Or whatever you do with it..
return new RoadInfo(s);
}
}
Не говоря уже о том, что у вас есть по крайней мере 5 обязанностей здесь. OS-нейтральный путь
выражение
- Построить Сложение XPath для широты/долготы
- Создание XPath doocument
- Получить
s
- все, что
- Создать новый
RoadInfo
экземпляру
Каждый из этих обязанностей (кроме последних) следует разделить на свои классы (ИМО) и иметь RoadInfoFactory
организуют их все вместе.
Лично я ожидал, что конструктор предоставит мне объект, с которым я могу начать работать сразу, поэтому я бы не захотел вызвать методы для инициализации объектов после конструктора каждый раз, когда я создаю экземпляр этого класса , Мне кажется, что метод вызова из конструктора мне кажется прекрасным. –
(В комментарии, потому что я недостаточно информирован, чтобы изложить это точно): По-моему, * нет *. Ваш конструктор предназначен только для захвата состояния, переданного ему. Если вам нужно выполнить логику состояния, переданного вашему конструктору, вам нужен еще один уровень косвенности. –
Сохраните конструктор просто. Конструктор должен иметь код, связанный с инициализацией объекта. Я предпочитаю перемещать неинициализирующую часть кода вне конструктора. –