2

Why learning about Fluent Interfaces, I came across this post which states that using set hints one is mutating the object whereas with is returing a new object.

I have seen this pattern first hand while using PySpark (Python API for Apache Spark):

# Using "set" to modify exiting object

from pyspark.conf import SparkConf
from pyspark.context import SparkContext

conf = SparkConf()
conf.setMaster("local")
conf.setAppName("My app")

sc = SparkContext(conf=conf)

# Also possible using Fluent Interface

conf = (
    SparkConf()
        .setMaster("local")
        .setAppName("My app")
)

sc = SparkContext(conf=conf)


# Using "with" to return new objects

from pyspark.sql import functions as F

dataframe = (
    spark.createDataFrame([], StructType([]))
         .withColumn("a", F.rand())
         .withColumn("b", F.rand())
         .withColumn("c", F.col("a") + F.col("b"))
         .withColumnRenamed("c", "result")
)

My question is whether this set vs with has a particular name? Or is that just a framework/language-specific pattern?

From the example above it is visible it is a concept independent from Fluent Interfaces themselves (the set approach can be used perfectly without any Fluent API), however it contributes to the readability.

3 Answers3

1

which states that using set hints one is mutating the object whereas with is returing a new object

That's not how I'd interpret it. What annoys me more is that this is clearly a subjective naming topic with no technical impact, and the referenced source is presenting their opinion as an absolute truth.

In my opinion, the naming is more closely tied to whether you're using the builder pattern with method chaining in mind, or just an everyday value setter.

Builders tend to have method chaining in mind (though not always), and With reads more fluently in the consumer code in those cases. For example:

var person = new PersonBuilder()
                    .WithFirstName("Rick")
                    .WithLastName("Sanchez")
                    .Build();

I would expect that syntax regardless of whether a builder is immutable and each method returns a different instance, or if it mutates the original builder. That is a completely separate discussion from the names of these chained methods.

Could you have used Set instead of With? Sure. It makes no technical difference.

However, if you're looking at an everyday value setter, With is less common than set. Compare this:

person.SetName(newName);

to this:

person.WithName(newName);

So yeah, if you're using a regular setter and are mutating the instance, Set makes more sense. As far as cases where With makes more sense go, it's really just a minor renaming in order to make the consumer code read more fluently. There is no right or wrong in those cases, just a matter of personal preference.

Flater
  • 44,596
  • 8
  • 88
  • 122
  • 1
    Curiously, when I read `person.WithName(newName)` the first that comes to mind is `searching` not `setting`. However, I'm biased by many years of programming setters as `setX()`. I think I wouldn't have noticed any difference if I were new to this. – Laiv Oct 31 '22 at 08:16
  • 1
    @Laiv this naming could be inspired by the old Pascal’s `with` statement, which was very handy to mass-initialize properties without repeating the object name. Many tried to emulate it with method chaining. However Joshua’s builder pattern —that tries to achieve the same objective— uses indeed the more traditional `set` and not `with` (but maybe there are some variants) – Christophe Nov 01 '22 at 10:12
1

Using the prefixes set for mutating an object and with for keeping it immutable by returning a changed copy, is a popular naming convention that exists across several languages, inter alia Java. It doesn’t have a specific name.

The convention is however not universal, as the example of fluent interfaces show: there with is used for a convenient method chaining reading experience, not necessarily in an immutability context. The best is therefore to stay consistent in your own usage (and document it).

Historical background

This article from 2006 by Stephen Colebourne, Immutable POJOs - Improving on getters/setters explains the origin: the set prefix was an established convention for setters. But some new API was to be designed with immutable objects, and the with alternative was used to avoid confusion guarantee immutability. His 2011 refresher on popular prefixes explains it well:

set: Mutable setter. This mutates the target object setting a property, such as bean.getBar(bar).

with: Immutable "setter". Returns a copy of the original with one or more properties changed, such as result = original.withBar(bar).

Coleborne was a contributing experts of the JSR-310 specification, which defines the Java date and time API. The ideas expressed in the 2006 article made their way into the official standards in the 2007 JSR proposal, that ended to be adopted early 2014 for JDK-8.

Christophe
  • 74,672
  • 10
  • 115
  • 187
0

The general (object oriented) terminology is accessor and modifier. Apparently 'mutator' is used a lot too instead of modifier.

Perhaps more commonly used and specific to methods and properties are getters and setters.

Which brings me to the point that 'with' is not commonly regarded to be the counter part of set. 'With' is just a keyword or statement in a number of languages for which it does different things.

Martin Maat
  • 18,218
  • 3
  • 30
  • 57