Saturday, June 11, 2011

Better programming with immutable objects

Recent buzz in the development community has discussed functional programming languages. These languages have a different approach to the organization of code. They are not object-oriented languages, nor are they procedural. Functional programming languages include Haskell, Erlang, and F#.

Working with old-fashioned object-oriented languages (C++ and C#), I suffer from language envy. I can see the shiny new languages but use the old, dented languages for my daily work. (Of course, I recognize that at one time C# and even C++ were the new, shiny languages. I also recognize that at some point in the future, Haskell and F# will be considered the old, dented languages. But for now, the grass is greener over the fence and in the yard of the new languages.)

I may be suffering from envy, but I don't sit and curse the darkness. Instead, I try to use the techniques of the new languages in my current toolset. I did this when programming in C and gazing longingly at C++; I wrote code in a style that I called "thing-oriented" programming. My thing-oriented programming let me identify key objects in the code (data structures, not objects in the OO sense) and collect and organize functions by the objects they manipulated. It was a step towards object-oriented programming. (Eventually I did learn C++ and work on C++ projects.)

With the introduction of C# and .NET, I used the same idea. For this transition, I wrote class libraries in C++ that mimicked the class libraries in .NET. (Not the entire .NET collection, just the basic classes to get the work done.) The work was a bit difficult, as we were not allowed to use STL. But like "thing-oriented programming", it was a step towards .NET and made the transition easier.

So here I am again, and this time the target is functional programming languages. I want to transition to functional programming from object-oriented programming, but don't have the tools. (The day job uses "classic" OO languages, and I struggle to find time outside of the office.)

My transition technique is to use "immutable object programming".

This has some interesting effects:

1) To construct an object, all data must be present. I cannot instantiate an object and later give it more information. Once an object is instantiated, it is complete and final. (I can construct other objects from built objects, so I can construct a "sales price" object and later use it to construct a "discounted sales price" object. But I cannot wedge in a discount to the "sales price".

2) I find myself thinking about the sequence of operations and the dependencies between objects.

3) My programs are designed in three phases: collect data (and construct objects), construct other objects from the collected data, and produce output. This is a pattern that goes back to the beginnings of the programming age. It may be a natural fit for the "immutable object programming" style, or it may be driven by the calculations of the systems.

4) My thinking is more rigorous. Not necessarily up front, but the end result (the final code) is more disciplined. I write some code, and sometimes take non-immutable shortcuts (or even OO shortcuts). These shortcuts are obviously wrong, but they yield the correct output. Once I have the correct output (and tests to check that output), I revise the code and remove the shortcuts.

5) My code is easy to debug. When the output is incorrect, I know that an object has incorrect data. (Or possibly the output routine is incorrect.) If the object has incorrect data, I know that it was constructed improperly. (There is no other method that modifies the object.) Finding the problem is a simple matter of identifying the incorrect object and then identifying the construction of that object.

6) My code is easy to change. I have made a number of changes to the code, and all have been simple and obvious. (And therefore, they worked.) These were not trivial changes, either; some were large and affected multiple modules.

I will admit that I do not understand functional programming languages. I have created some small programs in Haskell, but not enough that I "grok" the concept. My "immutable object programming" trick may be a step towards functional programming or it may be a step away from functional programming. It feels right, and I like the results.

1 comment:

Daniel Williams said...

Brilliant, thanks for the suggestions. I too coded in "thing-oriented" C before I knew about C++, and agree that you can learn alot from other languages and apply them to your day job even if your current language does not actively support the new way of thinking.

Cheers,
Danel