Я исследовал эту тему и выяснил, что назначение полей через конструктор является лучшей практикой, а не сеттер. Но что, если у меня есть объект с 10 полями? Это приведет к созданию крупных конструкторов и будет ли это считаться хорошей практикой?
Например:
public DefaultAccount(Long id, String name, String surname, String username, String password, Role role) {
this.id = id;
this.name = name;
this.surname = surname;
this.username = username;
this.password = password;
this.role = role;
}
Этот конструктор выглядит большим для меня.
По-моему, это зависит от ситуации. Приведенный вами пример - довольно простой класс с простыми типами. Я бы подумал, что все в порядке. Тем не менее, я не совсем уверен в вашем заявлении, рассматривая установщиков. Но вам, возможно, придется подумать:
Если вы работаете с некоторыми из более крупных фреймворков (Spring, Hibernate...), многие из них будут создавать объекты с использованием конструктора по умолчанию (например, new Person()), а затем вызывать сеттеры для полей. Они будут бросать исключения, если что-то недоступно.
Наличие конструктора, подобного тому, который вы указали, в порядке. Но сеттеры были бы нужны в любом случае. Если они становятся сложными, подумайте о реорганизации класса. Возможно, слишком много зависимостей необходимы. Возможно, вместо 10 параметров вы можете инкапсулировать их в другой объект (например, конфигурацию).
Старайтесь не публиковать поля. Когда в какой-то момент вам нужно проверить определенное условие в сеттере, и ваше поле было общедоступным, вы потратите некоторое время на рефакторинг. Если необходимо, проверьте предварительные условия в сеттерах и исключите исключения.
Я также нашел этот вопрос в stackoverflow, который ставит вопрос о сеттерах немного дальше: Java устанавливает частные поля внутри конструкторов
Одна из проблем с конструкторами, которые принимают множество параметров (или имеющих несколько конструкторов, которые принимают разные наборы параметров), - это ошибки, которые могут возникать, когда несколько параметров имеют один и тот же тип. Рассмотрим из вашего примера, насколько легко было бы получить порядок имени и фамилии в неправильном направлении.
Решением этого может быть использование шаблона Builder.
Ниже приведен всесторонний взгляд на то, как это работает: шаблон построителя на практике и следующий вопрос о переполнении стека также хорошо его охватывает: когда вы используете шаблон построителя
Если не все параметры являются обязательными, рассмотрите возможность использования шаблона Builder, как предложено в пункте № 2 эффективной Java от Джошуа Блоха, в котором говорится...
Вместо того, чтобы делать желаемый объект напрямую, клиент вызывает конструктор (или статический завод) со всеми необходимыми параметрами и получает объект-строитель. Затем клиент вызывает setter-подобные методы в объекте builder для установки каждого необязательного параметра, представляющего интерес. Наконец, клиент вызывает без параметров
build
метод для создания объекта, который неизменен.
На мой взгляд, наиболее эффективным способом было бы преодолеть проблему до стольких возможных классов:
public DefaultAccount(Long id, String name, String surname, User user)
{
this.id = id;
this.name = name;
this.surname = surname;
this.user = user;
}
// From second class User
public User(String username, String password, Role role)
{
this.username = username;
this.password = password;
this.role = role;
}
Таким образом, вы избегаете создания огромных конструкторов и улучшаете удобство и удобочитаемость кода.
Вы также можете использовать классы конфигурации, как описано здесь.
Фактически наличие большого количества параметров в любом из методов (включая конструкторы) является плохой практикой.
Прежде всего, я вижу конструктор DefaultAccount с полями, не связанными напрямую с учетной записью.
Вы должны извлечь, например, имя и фамилию другому классу (User?) И так далее.
getters и seters используются, когда у вас есть несколько классов, и это тоже, когда ваши поля являются частными (или защищенными и необходимыми для доступа из другого пакета). Если у вас есть только один класс, вам не нужно создавать геттеры и сеттеры, вы можете напрямую присваивать значения объектам (учитывая, что вы не хотите назначать их в своем конструкторе)