We are now in an age of complex multi-core CPU environments with virtual machines running functional programming features like lambdas in Java 8 and C#. Applications share more data between threads, component layers, and data stores. One of the features helping us deal with this complexity is immutability. Immutability helps us safely share objects between not only threads, but by also design between application components (more on this in a future article.) I inject simplicity in code whenever possible using the KISS principle: Keep It Simple Stupid.
When it comes to coding, my premise is simple: read-only is simpler than read-write.
Dealing with immutable variables and objects makes writing, understanding, and maintaining complex code simpler. I’ll discuss using final on parameters, local variables, and instance variables.
Using final parameters
The reason I like to use final on parameters is to enforce as much as possible the best practice of considering input to methods as read-only. Whether or not you enforce this best practice in your project is up to you. At least there is a way to do it (partially) in Java. If you’ve written method entry-exit logging code or long complex methods (not that you should), you usually end up needing to track a method’s input values. Using final on a parameter guarantees that the compiler will generate an error if you reassign a value to the parameter. This works great for primitive parameters. Beware, for object references, the compiler does not protect the object state from changing.
If you use a parameter or a local variable from an inner class, you do not have the choice, you must use final.
For me, consistency is important, so if you use final, use it consistently (=everywhere).
Using final local variables
The reason I like to use final on a local variable is that is lets me declare intent: This variable is read-only; a variable without final is read-write. As a programmer, I’d better know what I want to do. Declaring intent and having the compiler enforce it on my behalf is a good thing.
Using final for instance variable
This is how to achieve object immutability, which is a separate topic, but I mention it for completeness. For objects, the reference is immutable, the object itself may not be.
I’ve read that most of code’s lifetime is spent being read and maintained, compared to the time it took to originally write it. What is important to me is the stable code you end up with at the end of a coding session or sprint, not the fact that you had to add and remove keywords here and there in the process. If you always keep your intentions and code matched up, the code will be that much easier to debug and maintain.
Using the ‘final’ keyword is an unfortunate inheritance from the previous generation of languages. With functional programming on the rise, my bet is that we’ll see more mainstream languages that will default to values being immutable and you’ll have to go out of your way to declare them mutable. The fact that the default today is read-write does not matter and does not mean it is the right thing to do. It’s just historical baggage for lazy typists 🙂