Using immutable objects has become more and more common, even when the program at hand is never meant to be ran in parallel. And yet we still use getters, which require 3 lines of boilerplate for every field and 5 extra characters on every access (in your favorite mainstream OO language). While this may seem trivial, and many editors remove most of the burden from the programmer anyways, it is still seemingly unnecessary effort.
What are the reasons for the continued use of accessors versus direct field access of immutable objects? Specifically, are there advantages to forcing the user to use accessors (for the client or library writer), and if so what are they?
Note that I am referring to immutable objects, unlike this question, which refers to objects in general. To be clear, there are no setters on immutable objects.
I’d say this is actually language-dependent. If you’ll excuse me I’ll talk about C# a bit, since I think it’ll help answer this question.
I’m not sure if you’re familiar with C#, but its design, tools, etc. are very intuitive and programmer-friendly.
One feature of C# (which also exists in Python, D, etc.) that helps this is the property; a property is basically a pair of methods (a getter and/or a setter) which, on the outside, look just like an instance field: you can assign to it and you can read from it just like an instance variable.
Internally, of course, it’s a method, and it can do anything.
But C# data types also sometimes have GetXYZ() and SetXYZ() methods, and sometimes they even expose their fields directly… and that begs the question: how do you choose which to do when?
Microsoft has a great guideline for C# properties and when to use getters/setters instead:
Notice that the entire goal of these guidelines is to make all properties look like fields externally.
So the only real reasons to use properties instead of fields would be:
Now let’s get back to Java/C++, and immutable data types.
Which of those points apply to our scenario?
What’s the point of storing data if you’re going to hide it and do nothing with it?
But sometimes it does apply (e.g. say you have an immutable tree) — you might not want to expose metadata.
But then in that case, you would obviously hide the data you don’t want to expose, and you wouldn’t have been asking this question in the first place! 🙂
Now Java and C++ don’t have properties, but methods take their place — and so the advice above still applies, and the rule for languages without properties becomes:
If (1) you don’t need ABI compatibility, and (2) your getter would behave just like a field (i.e. it satisfies the requirements in the MSDN documentation above), then you should use a field instead of a getter.
The important point to realize is that none of this is philosophical; all these guides are all based on what the programmer expects. Obviously, the goal at the end of the day is to (1) get the job done, and (2) keep the code readable/maintainable. The guide above has been found to be helpful in making this happen — and your goal should be to do whatever suits your fancy that will make that happen.