A short while ago I posted this rant about a incompetent programmers and a good friend posted the following comment:
You say OOP is about hiding mutable state. Isn’t it about encapsulating mutable state? Maybe it’s just a matter of wording – but “hidden”, in my dictionary, means that it’s totally out of reach. Encapsulated state (again, in my dictionary) can be modified, but only through controlled operations.
When I was writing my comment in the rudimentary comment box the text just kept growing and growing. Suddenly, the pink borders of that box began flashing with fluid rainbow color gradients. At that point I realized that I should probably dedicate a new post to this subject.
The Short Answer
If I want to stay inline with mainstream terminology and common wisdom than I should absolutely have used “encapsulated” and in fact, it was exactly the word I was looking for but could not find. Instead, I used the rather blunt “hidden”. It is also absolutely true that often the state that I was talking about is still modified using methods or something like it (I tend to prefer message). However, after pondering this question for a bit, I really think at that point I do meant hidden so let me show just what I’m talking about.
The Long Answer
Just for kicks, let’s see what the general consensus has to say about OOP:
Object-oriented programming (OOP) is a programming paradigm that uses “objects” – data structures consisting of datafields and methods together with their interactions – to design applications and computer programs.
Thank the Lord! There is no mention of class or classes in there. I’ve never edited the global consensus before but if I ever see a mention of one of those words for this particular definition then that’s going to be the first time. For the rest, the definition is just shit. It sounds like something an anthropologist would jot down when he saw a few programming monkeys doing it in the wild.
If I would be to give a redefined definition of what I said in a previous post than it would be something like:
OOP is about programming with objects, only objects and doing it with messages.
But I’m not going to do that. Instead, I’m going to show the following class:
class Operation : IExpression
{
readonly IEnumerable<IExpression> expressions;
public Operation(IEnumerable<IExpression> expressions)
{
this.expressions = Enforce.NotNull(expressions, "expressions");
}
public string Compile(IDictionary<string,object> context)
{
return new Sequence(this.expressions).Compile(context);
}
}
Hopefully that makes some sense. It is just a simple class that resembles something that can be compiled into code. In my case, I’m using it to compile to SQL but the pattern is more generally useful. For me this resembles an acceptable piece of OOP and I would argue that the state is completely hidden. Of course, if I put some expressions in there as a client than I know that they ought to be in there somewhere but that is not the point. If I pass an instance of Operation to someone else then he or she would have absolutely no knowledge of what state that object is carrying. The only thing they can rely on is that it probably knows how to do its job and that it has a Compile method that converts it to a string using a IDictionary<string,object> instance.
Continuing with the human analogy, you generally don’t know what mutable state another human has. You can make some assumptions about it but you can never really know. The only thing you can do is to ask them about it. Even then, they might not want to tell you or in other circumstances they might lie about it so that information is not really something to depend upon. The only thing left to do is to just have them do it and see what they make of it. If you are really insecure about the outcome you can even have multiple people do the same thing concurrently and use the result that suits you most. This solution translates beautifully to software too.
Another problem is that trying to mutate human state – either for better or worse – doesn’t always work. Not everybody likes to learn new things and it also takes a dedicated effort of some form to imprint any kind of paradigm. This is generally annoying but it does mean than an human instance can be easily fed to the next operation. Translated to objects it means that instances should not be forthcoming with regard to mutation of their internal state. In other words, they should offer little opportunity for outside forces to mess with their internal state. In fact, it should be hidden as much as possible because one of the Meticulous Laws tells us that: “The less the internal state of a particular instance resembles the messages it can send, the more useful it is.”
Hide the state! Pull the lever!
Sorry, I just could not help throwing a Dwarf Fortress reference in there (be sure to support the toad if you like it). Somehow though, I feel that hiding the state is on par with the importance of pulling a lever (or not pulling a lever for that matter) in Dwarf Fortress. The future of the fort or in our case, the code depends on it. Hiding stuff is important.
For me, one of the big problems with encapsulation is that I’m now seeing shit like this:
class Expression
{
IList<IExpression> expressions = new List<IExpression>();
public IList<IExpression> Expressions
{
get
{
return this.expressions;
}
set
{
this.expressions = value;
}
}
}
There is usually some other class involved to do the probing of the internal state using the convenient (but wrong) external access methods. And I’m still being nice, usually, the fuckers don’t even bother to include properties and/or to adhere to the C# style conventions. They usually write a bunch of nonsense Javafart or VBShit (or something like that). Usually, this code consists of an humongous amount of getThisMotherfucker or setThatMotherfucker methods that don’t have anything to do with OOP or encapsulating state for that matter. Let alone hiding state. For most, encapsulation means wrapping it with yet another class with absolutely no behavior defined at all. It’s just a bunch of getters and setters passing values all over the place. For me, “encapsulation” is somewhat on par with “data structures consisting of datafields and methods together with their interactions” (from the general consensus definition for OOP). I don’t like it because it’s not strong enough. People are easy to get the wrong impression and thus make a mayor fuckupage of the code.
Functional, OOP and Prototyping
There is this interesting dual between FP (functional programming) and OOP. In FP it is all about data. First, analyze the data, then model the data and then start to build your awesome functional library on top of data. When a new operation on the data is requested you are able to smack that bitch in no time but if the data changes, you are fucked because you more than likely have to change a lot of your function definitions. Now look at OOP. You are analyzing the data, modeling the data and then start to build your awesome objects on top of that data. When a new piece of data is added there is no problem, you stuff that in some class, somewhere. However, whenever you a new operation is requested your’re fucked because you suddenly got to traverse your well defined hierarchies of classes to facilitate for this new functionality. To me, the dualism in this is striking and it actually affects the way you have to think.
After a lot of fail, I found out that there is usually absolutely no need for class hierarchies. Just forget them. If you just consider an object a little piece of functional (immutable) data with accompanying operations then you’re all set. The only time you need to think about classes proper is when you are refactoring duplicate code. Sometimes, an abstract class here or there can do wonders for your code base. Otherwise, there’s little use for them – use interfaces instead. There is also a lot more in common between functional and object oriented programming than might be apparent at first sight.
For me, the only real OO programming language is Smalltalk. It is not just because of the OO optimized syntax but mainly about the fact that it is objects all the way down. Everything, literally everything is an object. Down to the lowest bits of code, everything is an object and everything is done with messages. And even when you’ve hit the bottom, it goes even further because the specifications to Smalltalk (aka “The Blue Book”) are written in Smalltalk too! Unfortunately it’s very niche but it still remains as an excellent study object. A lot of techniques are applicable to more pragmatic programming environments and the inner workings of the Smalltalk machine itself are well described in the Blue Book and worth studying and/or trying out in your environment of choice.
I’m practical though and consider C# a very reasonable compromise. With C# 3.0, a lot of work was done to move C# into the functional slice and with 4.0 we get to enjoy the dynamic slice of the cake as well. That said though, why I am I even ranting about this obtuse Smalltalk in the first place? Well, it mainly has to do with cloning or copying objects to generate new variations. Another thing that one might notice if he or she would browse the Smalltalk code is that there are a lot of operations but not a whole lot of getters and setters. In fact (and not only in Smalltalk), classes really do tend to hide their state rather than just encapsulate it. A lot of classes that actually do something useful accept a few parameters in their constructor or factory messages and offer a range of operational messages in return. Usually, the actual state that is used or stored isn’t clear and it really doesn’t matter because everything useful can be done with operational messages. By this, I mean messages that actually do something useful with the matter at hand instead of bluntly returning the value that is stored inside. Of course you’ll find some getting and setting but these are never important for that actual problem at hand and usually have to do with a more user friendly way of initializing the orchestra you’re directing.
So WTF Is The Point?
I know there is not really a point in the rant so far. I’ve babbled somewhat about functional and object oriented programming but what am I really trying to say? Well, it’s actually very simple:
Mutable state is the spawn of the devil
Mutable state really is evil and more importantly: often unnecessary.
Programming without mutable state is bliss and this is where functional programming comes in. This school of thought has always avoided mutable state and global state (very evil this! beware of danger!) and they might be able to learn us some things. Not least on how to actually get anything useful done with this style of programming.
IMHO, you really need to understand a bit about FP to do decent OOP but especially in the future. Nowadays, programmers can still be somewhat lazy and don’t worry about multi core processing too much but in the future this will simply be not possible anymore. If you insist to write your code in an imperative matter, utilizing mutable global or even local state all over the place, then you will have a hard time adapting to the new paradigm. Functional code (without side-effects) is the future. Microsoft is slowly adapting its community by introducing facades in the form of Linq, Parallel Extensions, Reactive Extensions and maybe even F# itself. By way of these, developers are slowly eased into more functional programming styles without even having a clue. Java has had Scala for a long time and I know that were I programming in a Java oriented environment, this would be one of my favorite puppies.
Learning a bit of functional programming WILL (and I don’t like to shout) make you a better programmer
Wrapping up
I can endlessly continue with this stuff but the long answer is getting long enough. In the end I’m getting more and more convinced that I really meant hidden (versus encapsulated) in the first place even though in that particular post, “encapsulated” would probably have been better. There is nothing inherently wrong with exposing the state to be modified by external sources using a logical operation or some other means of encapsulation as long as it is perfectly clear that state is modified. I like it better though when objects expose better and improved objects with new state and characteristics by themselves without me having to mutilate their state. I also like to use objects as seeds for new objects but maybe that’s just me.
With the fast garbage collectors that we have today, I’m fighting for more mapping and less mutilation. I’d rather have a new fresh copy of some kind of object with my desired properties than the same object with some kind of internal state mutilated according to my wishes. When I get a fresh object I’m free to do whatever I what with it. When I get the same object modified, some other motherfucking object might be hanging on to it causing all kinds of strange things to blow up whenever I try to do something remotely interesting with my latest toy. It also explains why I’m totally in love with IEnumerable. It’s powerful yet it doesn’t allow for people to easily screw up.
In OOP, imperative programming and mutable state remain important and allow us to do useful and powerful things but they should be the exception rather than the norm.