Today I want to introduce you to a simple rule that I apply when developing software. This rule often saves me a lot of time and it is simple to apply. I usually write code in Java and so the rule is made for Java programming in the first place, but it might also be adapted to other languages.
I call that rule
One dot per line
The dot character in Java is primarly used for dereferencing. This also means that it can lead to NullPointerExceptions. The nature of NPEs is that they contain few context information.
java.lang.NullPointerException at org.apache.commons.lang3.time.FastDateParser$TimeZoneStrategy.<init>(FastDateParser.java:869) at org.apache.commons.lang3.time.FastDateParser.getLocaleSpecificStrategy(FastDateParser.java:637) at org.apache.commons.lang3.time.FastDateParser.getStrategy(FastDateParser.java:606) at org.apache.commons.lang3.time.FastDateParser.access$100(FastDateParser.java:73) at org.apache.commons.lang3.time.FastDateParser$StrategyParser.letterPattern(FastDateParser.java:234) ...
This is primarily a problem when methods are chained.
Method chaining – a train wreck
Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results. Local variable declarations are syntactic sugar because of the difficulty humans have with deeply nested method calls. A method chain is also known as a train wreck due to the increase in the number of methods that come one after another in the same line that occurs as more methods are chained together even though line breaks are often added between methods.
When using method chaining the methods should ensure that they don’t return nulls. Otherwise every call in the chain can produce a NullPointerException. Lets assume that you have written the following code:
A NullPointerException might then look like this
java.lang.NullPointerException at com.acme.domain.Client.getMortgage(Client.java:325) ...
If a NullPointerException occurs it’s hard to guess where the NPE occured, isn’t it? Was the Mortgage null or the PaymentCollection or does no next payment exist?
One might argue that you can just look at the source code of every method call to find out which ones can return null. But this is still tricky, because what the code does might strongly depend on the actual database state. So a code analysis might not be successful. Furthermore the code you have checked out might not be the code version that caused the problem. This is usually the case when the NPE occurs in a production environment. So you should not forget to checkout the correct code version first.
Finally it would be better if the NullPointerException let you know where it exactely occurred. You can achive this if you follow the rule One dot per line.
Format a method chain
Format your chained method so that every line contains only one dot.
client.getMortgage() .getPaymentCollection() .getNextPayment() .applyPayment(300.00)
If now an NPE occurs the line number will point to the problematic line.
This is the simplest way to provide better NPEs in existing code with only few modifications and therefore reducing the rist of introducing new bugs.
Introduce local variables
Mortgage mortgage = client.getMortgage(); PaymentCollection paymentCollection = mortgage.getPaymentCollection(); Payment payment = paymentCollection.getNextPayment(); payment.applyPayment(300.00)
This also leads to better NPEs and furthermore helps you in debugging mode, because you can see all intermediate results in the debuggers local variable view.
Exceptions to the rule
- A static access does not increase the dots per line count. E.g.
This is allowed because the static access Client.INSTANCE can’t produce a NPE. Either the class is loaded via the class loader or it is not, but then you will get another exception or rather an error. E.g. a NoClassDefFoundError.