So we all know the bean/POJO get/set convention right? Its fine for mutable objects, but what about immutables? The convention just doesn't work there.
BigDecimal base = new BigDecimal(100d); base.setScale(2); // BUG!!!
Why is the above a bug? Because BigDecimal
is immutable, and so the set method doesn't actually change base
. Instead, the method returns a new BigDecimal
instance which isn't being assigned in the example. Here's the fixed version:
BigDecimal base = new BigDecimal(100d); base = base.setScale(2); // FIXED by assigning
In addition, by returning a new instance, the set method actually breaks the JavaBean spec. This is because the JavaBean spec says that set methods must return void.
So what can be done? Well I'd like to argue that the time has come for a new coding convention for immutable beans/POJOs. As a convention (preferably Sun endorsed) it would allow frameworks like JSF or Struts to handle immutable objects properly. So, what do I propose?
Mutable verb | Immutable verb |
---|---|
get | get |
set | with |
add | plus |
subtract | minus |
Here's an example of a datetime object using these conventions:
DateTime dt = new DateTime(); // immutable get is the same as a mutable get int month = dt.getMonthOfYear(); // immutable sets use the 'with' verb dt = dt.withYear(2006); dt = dt.withMonthOfYear(5); dt = dt.withDayOfMonth(23); // immutable add or subtract using the 'plus'/'minus' verbs dt = dt.plusYears(1); dt = dt.minusDays(1); // combinations, for example, the first day of the next month dt = dt.withDayOfMonth(1).plusMonths(1);
If adopted as a standard, there is even the potential to write a PMD or FindBugs rule to match on the verbs and ensure that you actually assign the result, thus eliminating a potential bug.
So, do you use immutable objects? Do you have a coding convention like this? Should this become a Sun convention? Opinions welcome!
I agree with your comments, however in order for this to catch on we need complete Sun support addressing the current api. I say that simply because, inconsistent code is a pain to work with and has less of a chance of being embraced by other programmers. For example...
ReplyDeleteWhile using the core sun api you are using the traditional setter which returns a new instance then, in your application's core api you are using setters with names like with prefixed, it would only be confusing to another programmer.