views:

855

answers:

15

Is it a good or bad idea to make setters in java return "this"?

public Employee setName(String name){
   this.name = name;
   return this;
}

This pattern can be useful because then you can chain setters like this:

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

instead of this:

Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);

...but it sort of goes against standard convention. I suppose it might be worthwhile just because it can make that setter do something else useful. I've seen this pattern used some places (e.g. JMock, JPA), but it seems uncommon, and only generally used for very well defined APIs where this pattern is used everywhere.

Update:

What I've described is obviously valid, but what I am really looking for is some thoughts on whether this is generally acceptable, and if there are any pitfalls or related best practices. I know about the Builder pattern but it is a little more involved then what I am describing - as Josh Bloch describes it there is an associated static Builder class for object creation.

+4  A: 

This scheme (pun intended), called a 'fluent interface', is becoming quite popular now. It's acceptable, but it's not really my cup of tea.

Noon Silk
Ha! Scheme! I see what you did there.
Crashworks
Crashworks: The scheme pun was a side-effect, I was mainly pointing out the pun on 'this'. Nice to see it works on multiple levels though :P
Noon Silk
You're clever without even trying!
Pierreten
As Maddox said: http://www.thebestpageintheuniverse.net/c.cgi?u=puns
ssg
+20  A: 

It's not bad practice. It's an increasingly common practice. Most languages don't require you to deal with the returned object if you don't want to so it doesn't change "normal" setter usage syntax but allows you to chain setters together.

This is commonly called a builder pattern or a fluent interface.

It's also common in the Java API:

String s = new StringBuilder().append("testing ").append(1)
  .append(" 2 ").append(3).toString();
cletus
It's often *used* in builders, but I wouldn't say "this is ... called a Builder pattern".
Laurence Gonsalves
It's funny to me that some of the rationale for fluent interfaces is that they make code easier to read. I could see it being more convenient to write, but it kinda strikes me as being harder to read. That's the only real disagreement I have with it.
Brent Nash
Probably the ultimate incarnation of fluent interfaces is LINQ
cletus
It's also known as train-wreck antipattern. Problem is that when an null-pointer exception stack trace contains a line like this, you have no idea which invocation returned null. That's not to say that chaining should be avoided at all costs, but beware of bad libraries (esp. home-brewn).
ddimitrov
+1  A: 

On first sight: "Ghastly!".

On further thought

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

is actually less error prone than

Employee anEmployee = new Employee();
anEmployee.setName("xxx");
...
list.add(anEmployee);

So quite interesting. Adding idea to toolbag ...

djna
No, it's still ghastly. From a maintenance perspective, the latter is better because it's easier to read. Additionally, automated code checkers like CheckStyle will enforce lines to be 80 characters by default - the code would get wrapped anyway, compounding the readability/maintainence issue. And finally - it's Java; there's no benefit to writing everything on a single line when it's going to be compiled to byte code anyway.
OMG Ponies
personally, I think the former is easier to read, especially if you are creating several objects this way.
Ken Liu
@Ken: Code a method. Write one copy in fluent format; another copy in the other. Now give the two copies to a couple of people, and ask which one they find easier to read. Faster to read, faster to code.
OMG Ponies
Like most tools, it can be easy to overuse. JQuery is oriented around this technique and is thus prone to long call chains which I've found actually impairs readability.
staticsan
+4  A: 

At least in theory, it can damage the optimization mechanisms of the JVM by setting false dependencies between calls.

It is supposed to be syntactic sugar, but in fact can create side effects in the super-intelligent Java 43's virtual machine.

That's why I vote no, don't use it.

Marian
Interesting...could you expand on this a bit?
Ken Liu
Agreed, I'd like to know more about how this can affect optimization
Carson Myers
Just think about how superscalar processors deal with parallel execution.The object to execute the second `set` method on is dependent on the first `set` method although it is known by the programmer.
Marian
+2  A: 

I don't think there's anything specifically wrong with it, it's just a matter of style. It's useful when:

  • You need to set many fields at once (including at construction)
  • you know which fields you need to set at the time you're writing the code, and
  • there are many different combinations for which fields you want to set.

Alternatives to this method might be:

  1. One mega constructor (downside: you might pass lots of nulls or default values, and it gets hard to know which value corresponds to what)
  2. Several overloaded constructors (downside: gets unwieldy once you have more than a few)
  3. Factory/static methods (downside: same as overloaded constructors - gets unwieldy once there is more than a few)

If you're only going to set a few properties at a time I'd say it's not worth returning 'this'. It certainly falls down if you later decide to return something else, like a status/success indicator/message.

Tom Clift
well, generally you don't return anything from a setter anyway, by convention.
Ken Liu
Maybe not to start with, but a setter doesn't necessarily keep its original purpose. What used to be a variable might change into a state that encompasses several variables or have other side effects. Some setters might return a previous value, others might return a failure indicator if failure is too common for an exception.That raises another interesting point though: what if a tool/framework you're using doesn't recognise your setters when they have return values?
Tom Clift
@Tom good point, doing this breaks the "Java bean" convention for getters and setters.
Andy White
+3  A: 

Because it doesn't return void, it's no longer a valid JavaBean property setter. That might matter if you're one of the seven people in the world using visual "Bean Builder" tools, or one of the 17 using JSP-bean-setProperty elements.

Ken
It also matters if you use bean-aware frameworks like Spring.
ddimitrov
or if you use the introspection API to write reflective code...
Dan Vinton
+4  A: 

If you don't want to return 'this' from the setter but don't want to use the second option you can use the following syntax to set properties:

list.add(new Employee()
{{
    setName("Jack Sparrow");
    setId(1);
    setFoo("bacon!");
}});

As an aside I think its slightly cleaner in C#:

list.Add(new Employee()
{
    Name = "Jack Sparrow",
    Id = 1,
    Foo = "bacon!"
});
Luke Quinane
I like this, just another reason to learn C#
Carson Myers
double brace initialization may have problems with equals because it creates an anonymous inner class; see http://www.c2.com/cgi/wiki?DoubleBraceInitialization
Csaba_H
+1  A: 

In general it’s a good practice, but you may need for set-type functions use Boolean type to determine if operation was completed successfully or not, that is one way to. In general, there is no dogma to say that this is good or bed, it comes from the situation of course.

Narek
How about using exceptions to indicate error condition? Error codes can be easily ignored as many C programmers painfully have learned. Exceptions can bubble up the stack to the point where they can be handled.
ddimitrov
+2  A: 

I don't know Java but I've done this in C++. Other people have said it makes the lines really long and really hard to read, but I've done it like this lots of times:

list.add(new Employee()
    .setName("Jack Sparrow")
    .setId(1)
    .setFoo("bacon!"));

This is even better:

list.add(
    new Employee("Jack Sparrow")
    .Id(1)
    .foo("bacon!"));

at least, I think. But you're welcome to downvote me and call me an awful programmer if you wish. And I don't know if you're allowed to even do this in Java.

Carson Myers
The "even better" does not lend well to the Format Source code functionality available in modern IDE's. Unfortunately.
Thorbjørn Ravn Andersen
you're probably right... The only auto-formatter I have used is emacs' auto indenting.
Carson Myers
A: 

From the statement

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

i am seeing two things

1) Meaningless statement. 2) Lack of readability.

Madhu
+2  A: 

I used to prefer this approach but I have decided against it.

Reasons:

  • Readability. It makes the code more readable to have each setFoo() on a separate line. You usually read the code many, many more times than the single time you write it.
  • Side effect: setFoo() should only set field foo, nothing else. Returning this is an extra "WHAT was that".

The Builder pattern I saw do not use the setFoo(foo).setBar(bar) convention but more foo(foo).bar(bar). Perhaps for exactly those reasons.

It is, as always a matter of taste. I just like the "least surprises" approach.

Thorbjørn Ravn Andersen
I agree on the side effect. Setters that return stuff violates their name. You are setting foo, but you get an object back? Is this a new object or have I altered the old?
crunchdog
+7  A: 

To summarize:

  • it's called a "fluid interface", or "method chaining".
  • this is not "standard" Java, although you do see it more an more these days (works great in jQuery)
  • it violates the JavaBean spec, so it will break with various tools and libraries, especially JSP builders and Spring.
  • it may prevent some optimizations that the JVM would normally do
  • some people think it cleans code up, others think it's "ghastly"

A couple other points not mentioned:

This violates the principal that each function should do one (and only one) thing. You may or may not believe in this, but in Java I believe it works well.

IDEs aren't going to generate these for you (by default).

I finally, here's a real-world data point. I have had problems using a library built like this. Hibernate's query builder is an example of this in an existing library. Since Query's set* methods are returning queries, it's impossible to tell just by looking at the signature how to use it. For example:

Query setWhatever(String what);

It introduces an ambiguity: does the method modify the current object (your pattern) or, perhaps Query is really immutable (a very popular and valuable pattern), and the method is returning a new one. It just makes the library harder to use, and many programmers don't exploit this feature. If setters were setters, it would be clearer how to use it.

ndp
thanks for this answer; I appreciate the real-world perspective.
Ken Liu
btw, it's "fluent", not "fluid"...as in it lets you structure a series of method calls like a spoken language.
Ken Liu
+1  A: 

Paulo Abrantes offers another way to make JavaBean setters fluent: define an inner builder class for each JavaBean. If you're using tools that get flummoxed by setters that return values, Paulo's pattern could help.

Jim Ferrans
A: 

I'm in favor of setters having "this" returns. I don't care if it's not beans compliant. To me, if it's okay to have the "=" expression/statement, then setters that return values is fine.

Monty Hall
A: 

This may be less readablye

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

list.add(new Employee() .setName("Jack Sparrow") .setId(1) .setFoo("bacon!"));

is way more readable than:

Employee employee = new Employee(); employee.setName("Jack Sparrow") employee.setId(1) employee.setFoo("bacon!")); list.add(employee);

Scott
I think it's pretty readable if you don't try to put all your code on one line.
Ken Liu