For a (public) read-only instance variable (ROIA) to have a value, it must be assigned one. This may happen in one of two ways.
- It is initialised at instantiation time with a value passed in by the caller.
In this case, whenever the caller might read the ROIA (back) from the object instance, it could just as easily, and more efficiently, obtain that same value from the same source as it got it from when it instantiated the object in the first place.
Now, some will argue: "But what of the caller passes the object to some other piece of code that doesn't have access to the value used during initialisation?". And the answer is, that if the caller can pass the object to that other code, it can equally well pass the value to that other code directly rather than via the object.
And then: "What if the caller has many values that it wants to pass to the other code? Isn't encapsulating them into a data-only object and passing its handle to that other code better than passing a bunch of discrete variables?". And the answer is, how is that better than putting the variables into a simple data structure like a hash or array and passing a reference to that to the other code?
- It is initialised with a value derived from the values passed in by the caller.
In this case, the ROIA is calculated or otherwise derived from the other initialisation parameters, and then stored so that it needn't be recalculated every time the caller reads it. In effect, the ROIA is acting as a cache.
The problem here is that is assumes that the caller will call twice or more. But why would he? Why wouldn't he retrieve the value once and store it locally if he will need to reference it multiple times. The sole purpose of caching the value internally it to save the recalculation expense. But if the caller stores it locally, he also avoids the method call expense.
But more to the point, the initial calculation is only done if the caller actually needs the value. And if the caller takes the responsibility for caching the value, if he needs to, then the cache space is only allocated if it is needed also.
There is one legitimate case when a ROIA makes sense. For that to be the case requires several properties of the ROIA:
- The value stored in the ROIA must be expensive to calculate.
- It must be required multiple times.
- It must be required both internally to the instance; and externally to it.
This combination of circumstances are far, far rarer than the prominence ROIAs are given in texts, documentation and existing codebases would suggest. And in many cases, maybe even most cases of existing usage, that combination of properties is a strong indication of bad OO.
It indicates either that:
- The class is deficient in that it forces the caller to perform algorithms that should be provided by the class as a method.
- Or the value has been wrongly encapsulated into a catch-all object. (Sometimes referred to as a God-object.)
- Or the class should not be a class, but a simple data structure.
- Or it is a (truly) premature optimisation based upon whatifitis second guessing what the class user might require.
But in most cases, it is simply the class author thinking: the user has passed me this value, so I'll stick it in an instance variable just in case he wants it back at some point. Forgetting that if the caller gave it to you in the first place, if he needs it again, he can re-access the same place he got it from when he passed it to you.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.