5

When creating classes for "immutable objects" immutable meaning that state of instances can not be changed; all fields assigned in constructor) in Java (and similar languages), it is sometimes useful to still allow creation of modified instances. That is, using an instance as base, and creating a new instance that differs by just one property value; other values coming from the base instance. To give a simple example, one could have class like:

public class Circle {
  final double x, y; // location
  final double radius;

  public Circle(double x, double y, double r) {
    this.x = x;
    this.y = y;
    this.r = r;
  }

  // method for creating a new instance, moved in x-axis by specified amount
  public Circle withOffset(double deltaX) {
    return new Circle(x+deltaX, y, radius);
  }
}

So: what should method "withOffset" be called? (note: NOT what its name ought to be -- but what is this class of methods called). Technically it is kind of a factory method, but somehow that does not seem quite right to me, since often factories are just given basic properties (and are either static methods, or are not members of the result type but factory type).

So I am guessing there should be a better term for such methods. Since these methods can be used to implement "fluent interface", maybe they could be "fluent factory methods"? Better suggestions?

EDIT: as suggested by one of answers, java.math.BigDecimal is a good example with its 'add', 'subtract' (etc) methods.

Also: I noticed that there's this question (by Jon Skeet no less) that is sort of related (although it asks about specific name for method)

EDIT, MAY-2014: My current favorite is mutant factory, FWIW.

Community
  • 1
  • 1
StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • I'd call it a poorly named method. – Falmarri Jan 04 '11 at 00:37
  • "move" and "delta" imply mutability of an existing instance's properties... – BoltClock Jan 04 '11 at 00:39
  • Please read the actual question -- I did NOT ask how to name methods, but what to call kinds of methods. But just to prevent others from tripping on sidelines I will edit code a bit. – StaxMan Jan 04 '11 at 00:42
  • 1
    This is reminiscent of copy-on-write semantics...maybe there's something in that. Not a helpful answer, I know, but perhaps it will hit a neuron in someone's brain and generate a better answer :) – Cameron Skinner Jan 04 '11 at 01:22
  • "Mutant Factory" it is then! https://github.com/FasterXML/jackson-databind/blame/master/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java#L31 – Phil Kulak Feb 02 '18 at 21:38

3 Answers3

3

Hrm … it creates mutated versions of the object … maybe we should call it a mutant factory? :-)

Luke Maurer
  • 7,845
  • 2
  • 24
  • 24
3

I call those types of methods "copy methods".

While the clone() method creates an exact copy, a copy method makes a copy of an instance, usually with an implied or explicit variation. For example, String#toUpperCase() would be a copy method of the immutable String class - it copies an instance with a variation: it upcases all the letters.

I would consider withOffset() method in your example to be a similar copy method.

I don't know of any references that document the term "copy method". I'm borrowing the term "copy" from its use in C++: copy constructors and the "copy" naming guideline from the Taligent Coding Standards (more info).


As for the term "fluent factory methods", I don't know why "fluent" would make a difference, since a "fluent interface" is just an API style (separate from the builder pattern). If the term "factory method" doesn't apply here, I don't see how calling it a "fluent factory method" makes it apply any better.

Community
  • 1
  • 1
Bert F
  • 85,407
  • 12
  • 106
  • 123
  • Fluent part was just a suggestion, based on fact that such methods are often used to support fluent style. However it is not the same as fluent style does not mandate (or necessarily even promote) immutability. "copy method" sounds reasonable, let's see if anyone has even better suggestions. (I actually was about to mention "copy constructor" as a reference in question, but decided against it to try remove possible confusion) – StaxMan Jan 04 '11 at 18:02
1

This does not really look like a factory method. The signature alone only tells me that I can chain it in different calls, but not that it is supposed to create a new instance: I see this use case more like a StringBuilder that allows append("a").append("b"). It could, of course return a new StringBuilder every time (as your Circle does).

So it's not by design a factory. (Think of extracting the interface and writing the JavaDoc for that method: "one must return a new instance, since I'm immutable" -- why so ??) The fact that your class is immutable is just an implementation detail).

EDIT: Perahs a better example would be BigInteger, since that's also immutable. Along with multiply(BigInteger), it provides a package-private method:

BigInteger multiply(long v)

which returns a new instance and resembles your case very well. That's simply an operation that happens to return a result of the same type as the initial object; not a factory and I don't think this kind of operation really deserves its own name.

Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
  • I agree in that it is not a factory method, which is why I was hoping to find a better term. BigInteger is a good example. But beyond this, note that immutability is a VERY important aspect here; and definitely not (just) an implementation detail -- the whole object must be immutable, not just operations with this method. Maybe you are not be familiar with immutable object style or benefits? It helps tremendously with multi-threading and with concurrent data structures. With StringBuilder, returning of instance is just a convenience thing that allows chaining. – StaxMan Jan 04 '11 at 03:45
  • I never said the method is immutable, immutability refers to objects of your Circle class in my post. I said "implementatin detail" because I'm trying to just look at that method in order to classify it and ignore the actual implementation. All I'm saying is if that was an abstract method (declared in an interface), it's unlikely that you would require _all_ implementations to behave like this one. Therefore, I think this behaviour is not essential for this method. – Costi Ciudatu Jan 04 '11 at 09:51
  • I think I found a better example: String.concat() -- although that doesn't come from the CharSequence interface. The javadoc says: "If the length of the argument string is 0, then this String object is returned". You could do the same if the X offset is 0, so a new object is not even a requirement. – Costi Ciudatu Jan 04 '11 at 10:03
  • Sure, it is possible to also return the same instance, which is a useful if minor optimization. Immutability of the instance is the key feature, and my point is that these methods are integral pieces needed to support many use cases. And a name/term is needed to discuss class of such methods -- I don't care about javadoc for the method itself, but rather discussions about actual use or design patterns. – StaxMan Jan 04 '11 at 17:59
  • I got a little lost in details and maybe that's why you got me wrong... My whole point is that these methods do not deserve a name of their own, not to mention a design pattern. They frequently occur as a consequence of immutability, but not only. It's just a particularity of some operation to return a (new) instance of the same type (but I'd say it's still just a method like any other). Bear.giveBirthToCub() would return a new Bear instance, but this doesn't make it more special than Bear.eat() (and Bear is not immutable -- except for the winter season, to continue with my obsession). :) – Costi Ciudatu Jan 04 '11 at 23:28
  • I am fine agreeing to disagree: I feel there is nothing wrong in naming class of methods that have common goal. It's not like we were running out of names to call things, or there was huge information overload with terminology. Anwyay, thanks for comments & constructive criticism. Plus that reference to BigDecimal was a good one; I should probably add it as an edit to question itself! – StaxMan Jan 06 '11 at 22:35
  • @StaxMan: If a method will modify the object instance upon which it is invoked, its name should clearly reflect that. Whether or not `Circle` is mutable, I would expect `WithOffset` to return a new instance unless the new instance would be indistinguishable from the old one (note that if the old instance is mutable, that it and of itself would make it distinguishable from any other instance, new or otherwise). – supercat Apr 27 '14 at 21:29