Well, I guess it’s clear the direction from which I am trying to reason about this.
There is a lot of talk these days about the virtues of immutability (constness) whenever possible. The Concurrent programming in Java book talks a lot about this too.
However, all this is just what I’ve read about. I personally, haven’t coded much in Functional languages. And it looks very surprising to me that it is possible to work comfortably with immutable objects. Theoretically, it is definitely possible. But, from a practical point of view, is a very comfortable experience. Or what is the new kind of reasoning (for FP) that I must develop so that I don’t need mutability so much.
I would appreciate how to think about writing programs when you are forced to use immutable objects.
- Already making this a Community Wiki … for all those who are interested in closing this question or marking this as subjective … etc. etc. … *
Many functional languages are non pure (allow mutation and side effects).
f# is for example, and if you look at some of the very low level constructs in the collections you’ll find that several use iteration under the hood and quite a few use some mutable state (if you want to take the first n elements of a sequence it’s so much easier to have a counter for example).
The trick is that this is something to generally:
That it is possible to largely avoid mutating state is evidenced by the large amount of functional code out there. For people brought up on imperative languages this is somewhat hard to get your head round, especially writing code previously in loops as recursive functions. Even trickier is then writing them, where possible, as tail recursive. Knowing how to do this is beneficial and can lead to far more expressive solutions that focus on the logic rather than the implementation. Good examples are those that deal with collections where the ‘base cases’ of having no, one or many elements are cleanly expressed rather than being part of the loop logic.
It is really 2 though that things are better. And this is best done via an example:
Take your code base and change every instance variable to readonly[1][2]. Change back only those ones where you need them to be mutable for your code to function (if you only set them once outside the constructor consider trying to make them arguments to the constructor rather than mutable via something like a property.
There are some code bases this will not work well with, gui/widget heavy code and some libraries (notably mutable collections) for example but I would say that most reasonable code will allow over 50% of all instance fields to be made readonly.
At this point you must ask yourself, “why is mutable the default?”.
Mutable fields are in fact a complex aspect of your program as their interactions, even in a single threaded world, have far more scope for differing behaviour; as such they are best highlighted and drawn to the attention of the coder rather than left ‘naked’ to the ravages of the world.
It is notable that most functional languages have either no concept of null or make it very hard to use because they work, not with variables, but with named values whose value is defined at the same time (well scope) the name is.
I find it unfortunate that c# did not copy java’s concept of immutability with local variables too. Being able to assert emphatically that something doesn’t change helps make intent clear whether a value is on the stack or in an object/struct.
If you have NDepend then you can find these with
WARN IF Count > 0 IN SELECT FIELDS WHERE IsImmutable AND !IsInitOnly