Immutable Setters: Naming Conventions

A “setter” for an immutable object is something different from a setter for a mutable object. For this reason they are typically named differently.

This article lists the different conventions, with examples from the Java world.

withX(…)

This is the de facto standard naming convention for immutable setters. This is for example the default name for setters generated by the Immutables framework. Here's an example:

Foo newFoo = foo.withX(1047);

There is a @Value.Style option to change this pattern, but the option itself is called with="…", which emphasizes what the default convention is.

Being the most widespread convention, it's easy to find examples of this. Guava and the Java time package being two.

Just x(…)

Another approach is to not have a prefix at all. You see this in for example builders generated by the Immutables framework:

Foo foo = ImmutableFoo.builder()
                      .x(1047)
                      .y("Hello World")
                      .build();

If you use this approach directly on the immutable class (that is, no builder involved) you'd typically have it as an overload to the getter:

Foo newFoo = foo.x(5);  // setter - one argument
int x = newFoo.x();     // getter - no arguments

This convention is used in for example the Java Spark framework.

setX(…)

Some APIs use the same naming convention as for setters in mutable classes. This has the obvious drawback that it can be surprising when you're new to a code base. Working with BigInteger and writing…

bigInt.setBit(2);

…would for example be a mistake, since the returned object is discarded. With this naming pattern you have to get used to writing

BigInteger newBigInt = bigInt.setBit(2);

deriveX(…)

To highlight the fact that the new value is derived from the existing object, you could use deriveX(…). The immutable Font class in the Java API follows this pattern. If you want to create a new font with, for example, a specific size you use

Font newFont = font.deriveFont(newSize);

The Font class has been around since the beginning of time. This convention is not very common as of today.

Immutable object being an operand

When the immutable object is itself an operand to the transformation it's not really a setter in the traditional sense, and there's no need to have a prefix for the method. For example…

BigDecimal newBigDec = bigDec.multiply(BigDecimal.TEN);

…has the same signature as a setter, but multiply is clearly a better method name than any other alternative.

Same with String.substring, Path.resolve, etc.

Comments

Be the first to comment!