in reply to The fallacy of the *requirement* for read-only instance variables.

Here is one rule of thumb that I advise:   stick to actual requirements.

The author of a class might be tempted to put things into the class which do not have an actual, present requirement to be there at this time.   It might be tempting to think that the author is doing us a favor.   In reality, probably not.

“Forever after,” code is going to be written that is dependent upon the API that has been set forth by this object.   That code will, quite necessarily, be dependent upon everything about it ... the methods and their parameter lists; the acceptable ordinal values and/or character strings; the list goes on.   Going forward, that code will probably be impossible to change, or perhaps even to fully catalog.   It is therefore very highly desirable that this API be as small as possible, and also that it should possess no gratuitous features.   “Verily, you will have to support it ... all of it ... forever.   Choose Wisely.™”

IBM (had | has) a term for things like these interface-changes:   HIPER = “Highly Pervasive Change.”

Obviously, obviously, the design of every software system consists of educated guesses.   My rule of thumb is simply, that you should make the best possible guesses concerning what you guess you must guess about.   If on the other hand you guess that you don’t have to make a particular decision yet ... defer that decision until you actually do.

And, yeah, (gasp!) you might be dead-wrong.   (Oooh, I hate it when that happens!   But it happens a lot.)   Use your best judgment about what choices you deem that you must make now, and try to minimize that number of choices.   You are not actually making a real-world object... you are making a simulacrum of one.   You do not need to make a real-world object.   Endeavor to make exactly what you need, and no more.