Monday, April 26, 2010

Archive from 22_6_07 - OOP Research

I have begun work on re-writing Object Oriented Program Development. Having been writing in what I feel is an Object Oriented manner for some time, I still find it interesting to read all the various viewpoints about OOP. There are the nay-sayers who proport that OOP is a useless fad without any benefit. ( Surprisingly enough they are generally old-school procedural programmers ). There are others who argue that OOP is not formal enough to be considered as an identifiable "thing".(Academics?) Then there are the swarms of programmers who are out there actually using object oriented techniques, for better or worse, and getting things done.

Like most things in life, its more a question of your perspective, that defines your reality.
My interest in OOP is both in doing it "well" and in the emergent phenomena that using it permits to occur. In simple terms, "stuff that can be build on top of the OOP ideas".

Procedural programming has its own emergent phenomena. Huge API's, function libraries, DLL's etc. All these things made procedural programming easier.
For me, Object Oriented programming provides a way to conceptualise the problem domain and extract the semantics of the entities within the solution more cleanly than procedural code. I also enjoy the elegance of the exception system. Once I turned my head inside out enough to think in these terms it suddenly all made sense as a simple, clean system. The most difficult period for me was when I had a foot in both camps, having come from procedural programming and moving towards OOP. (Even though I still didn't have a clear idea what it was all about) But once I was more in the OOP camp than the procedural camp, so many of the design decisions became so much easier.
I still find reading OOP books, how much of the concepts and code is written in what I would consider as a "procedural" style. Especially the old course notes that I have inherited. It seems so much clearer to me now. I remember going through the course as a student before it was in its current incarnation and struggling with the material. In retrospect it was mainly due to the lecturer not really having any ideas what they were talking about. Its not that they didn't know about classes and objects, its just that they still had both feet firmly planted in the procedural camp. Everything they looked at and gave examples of was constructed to work well in a procedural program. They had still not made the leap into using objects with other objects. Rather they were still trying to use object as slightly more complex data types in a procedural program.

I remember the first major program I wrote using classes in VB. It was basically using classes as huge function libraries. Honestly I have still been working that way up until recently when I started a large burst of programing that involved churning out a number of programs quit quickly. It gave me the concentrated experience to see what I was doing and try new things with each one. I feel like I have "got" a little more of the picture.
I still have problems establishing the static structure of a program to facilitate easy message passing, but less so now. I am also wrestling with the coupling issue. I have found that reading about and applying unit testing has cleaned up the coupling issues alot in my designs. Building mock objects and having to keep each object loosely enough coupled that it can be instantiated for testing has forced me to think "cleaner". It has also prompted a whole new line of thought on refactoring ( which I have loved since I first heard about it ) I have found that with a good refactoring tool such as Ref++ or any of the Java refactoing tool sets, its possible to really clean up and isolate all the semantics of an object. Every single atomic operation that is logically valid within the object can be isolated in its own private method. Each of these can then have pre-conditions and post-conditions established and a much cleaner style of exception handling be introduced.
These semantic functions ( as I call them ) are simple one or two line functions that clearly and simply express a possible operation on a data element. There is also often a lot of common functionality that can be expressed as template functions. These however are still wrapped in a tiny private method as this carries the domain semantic ( the method name ) that clearly expresses the logical operation in terms of the domain its occurring in.
I have also been exploring some of the ideas of "Onion skin" objects. This is the idea of wrapper classes taken to a whole new level. To understand this idea, its useful to conceptualise the operations within a class. A method call ( or event handler if you prefer ) can do only a couple of things, it can "mutate" a data element ( potentially change ) it can "do something else" ( make a call to another object - raise an event or message ) or it can throw an exception in response to an illogical message or from having caught an exception from a downstream object. There are also tests. The object can perform a logical test on its data members, on the messages it receives and on the exceptions that may be generated or be caught from below. Another function that is common is transformation of messages. This may be transformation of type or transformation of values ( clipping to a range for example ) In a nice clean design this does not need to happen, but when interfacing with other systems it appears to be inevitable. (Win32 API for example)
All these tasks can be isolated in a common "layer", so the top layer might be the public interface of the object, the next layer might be the "Check incoming messages" layer, the layer below contains the logic for any message transformation. Below that may be core logic tests. Below that might be exception handling for any outgoing calls, etc.
This is just a different way of stratifying the functionality that is already found in most objects. However rather than these functions occurring in a single method body. They are split over these thin walled wrapper objects. This provides some interesting properties to me. There is a great deal of shared code that can be factored out and placed in these thin walls where it can be generalised and simplified even more. Then there is the fact that each message in and message out has to pass through each layer explicitly. This means you cannot forget to deal with one of the steps of good programming habits. ( Check data range, check all parameters etc ) as you are forced to address each step individually.
I have found success with using inner classes for the construction of these "onion skin" objects. This keeps all the tightly coupled code in the one file pair and makes it fairly easy to maintain. I am still exploring the idea of trying to share some of the "layers" between different domain objects. At the moment I am sharing some template functions in libraries to help with repetitive tasks.
My last trick at the moment is working on self documenting code. This ties in with the semantics above. If you extract every single logical operation within the object to a little private method with a well chosen name, the code starts to look very very readable as a set of comments. Sometimes this takes a little bit of creative massaging of the names chosen for the type and methods but the need for comments inside the object becomes effectively zero. The public interface still needs to be clearly documented, and that's it.

Must write some papers on this stuff at some point....

No comments:

Post a Comment