Основная проблема с большим списком параметров - удобочитаемость и опасность того, что вы перепутаете параметры. Вы можете решить эти проблемы с помощью Pattern Builder , как описано в Effective Java . Это делает код более читабельным (особенно языки, которые не поддерживают именованные и необязательные параметры):
public class AddressBuilder {
private Point _point;
private String _houseNumber;
// other parameters
public AddressBuilder() {
}
public AddressBuilder WithPoint(Point point) {
_point = point;
return this;
}
public AddressBuilder WithHouseNumber(String houseNumber) {
_houseNumber = houseNumber;
return this;
}
public Address Build() {
return new Address(_point, _houseNumber, ...);
}
}
Address address = new AddressBuilder()
.WithHouseNumber("123")
.WithPoint(point)
.Build();
Преимущества:
- параметры названы так, чтобы они были более читабельными
- сложнее перепутать номер дома с регионом
- можете использовать свой собственный порядок параметров
- необязательные параметры могут быть опущены
Один недостаток, о котором я могу подумать, состоит в том, что забывание указать один из аргументов (например, не вызывая WithHouseNumber
) приведет к ошибке времени выполнения вместо ошибки времени компиляции при использовании конструктора. Вам также следует рассмотреть возможность использования большего количества объектов-значений, таких как, например, PostalCode (в отличие от передачи строки).
В связанной заметке иногда бизнес-требования требуют изменения части объекта значения. Например, когда адрес был введен изначально, номер улицы мог быть написан с ошибкой и должен быть исправлен сейчас. Так как вы смоделировали Address как неизменный объект, здесь нет сеттера. Одним из возможных решений этой проблемы является введение «функции без побочных эффектов» в объекте значения адреса. Функция будет возвращать копию самого объекта, за исключением нового названия улицы:
public class Address {
private readonly String _streetName;
private readonly String _houseNumber;
...
public Address WithNewStreetName(String newStreetName) {
// enforce street name rules (not null, format etc)
return new Address(
newStreetName
// copy other members from this instance
_houseNumber);
}
...
}