Перевод статьи Immutable Setters: Naming Conventions
Сеттер поля для иммутабельного объекта отличается от обычного сеттера. Так как не изменяет объект, а создает новый с измененым параметром класса. Это веская причина для изменения нейминга методов.
В этой статье список различных возможных соглашений для иммутабельных классов, с примерами на Java.
withX(…)
Самый распространенный в настоящее время шаблон для сеттеров. Например, это наименование используется по умолчанию для генерируемых сеттеров в фреймворке Immutables. Пример:
Foo newFoo = foo.withX(1047);
В Immutables
возможно изменить шаблон наименования через аннотацию @Value.Style
, опция называется with="..."
, лишний раз подчеркивает with
как соглашение по-умолчанию.
Соглашение использовать with
широко распространено, примеры сеттеров вы сможете найти в библиотеках Guavа и Java Time.
Just x(…)
Другой подход, заключается в полном отсутствии префикса. Пример использования найдете также в Immutables
при сборке объекта, используя паттерн Builder. Пример:
Foo foo = ImmutableFoo.builder()
.x(1047)
.y("Hello World")
.build();
Если используете такой вариант наименования, то посмотрите также и вариант геттера в таком же стиле. Это будет перегруженный метод без аргументов, даже если не используется паттер Builder в классе. Пример:
Foo newFoo = foo.x(5); // setter - один аргумент
int x = newFoo.x(); // getter - без аргументов
Такое соглашение использует фреймворк Java Spark.
setX(…)
Некоторые API используют стандартные наименования сеттеров для иммутабельных классов. Такие имена методов неочевидны, так обращаясь к объекту мы не может сразу отличить иммутабельность, а для нового участника проекта это будет каждый раз сюрприз. При этом и в стандартном JDK такое подход также использутся.
Работает с объектом типа BigInteger и пишем код для установки значения:
bigInt.setBit(2);
…и это пример ошибки, так как такой метод не изменяет состояние объекта, а создает новый. При использовании сеттера в таком виде возвращаемый объект не используется, хотя и создается. Правильно использовать сеттер:
BigInteger newBigInt = bigInt.setBit(2);
deriveX(…)
Для подчеркивания факта создания нового объекта (derived - производный), вы можете использовать шаблон deriveX(…)
. Иммутабельный класс Font
в Java API следует этому правилу. Если вы хотите создать новый шрифт, например, с указанием размера, используйте:
Font newFont = font.deriveFont(newSize);
Класс Font
используется с незапамятных времен, а метод deriveFont(...)
c JDK 1.2.
В настоящее время данный формат нейминга не рапространен.
Иммутабельный объект, как аргумент
Когда иммутабельный объект является аргументом метода и влияет на вызываемый объект, то сеттер не является сеттером по сути. В этом случае не требуется префикса вовсе. Например, умножение чисел:
BigDecimal newBigDec = bigDec.multiply(BigDecimal.TEN);
…сигнатура похожа не сеттер, при этом имя метода multiply
точно описывает действие
и данный нейминг в этом случае подходит лучше других альтернатив.
Аналогично String.substring
, Path.resolve
и не только.