Disclaimer – this is a commentary about the state of the industry not about my specific place of employment. If it were, I’d have quit and found another job already. I haven’t, therefore it isn’t. QED.
Disclaimer 2 – it got pretty long but I’ve been typing it on and off for a week and I’m not sure much more I can edit it. I hope it gets you thinking.
I feel as if the OO train left and very few people were on it. There I said it. Don’t feel bad if you missed it, I’m pretty sure that I’m not on it either. What the heck am I talking about? Let me explain.
In the beginning
Way back in the dark ages I learned to program (20 years ago now that I stop to think about it). I did this with an Amstrad CPC 6128. It had a built in 3” (not 3.5) floppy drive and I had a hundred programs on disk but every month something magical happened. A magazine would arrive (Amstrad Action) containing 3 or 4 pages of type-ins. These consisted of programs written in Amstrad BASIC which you would read from the magazine and type in by hand.
I was hooked instantly. I’d found a way of controlling my computer and it let me be creative and feel powerful all at the same time. I had no idea what I was doing of course. I was just a fleshy copy-paste mechanism, a form of chinese room.
Skip forward a few years. By now I’ve learned BASIC enough that I can cobble together some rudimentary programs of my own. The trick is to write down what you want to do and figure out the program flow. Then you carve that flow up into chunks and implement the chunks into different areas of memory.
You did this with line numbers. By default line numbers started at 10 and went up by 10 for every new line but you could restart the code at any line number. So you’d implement the drawing routine at 300 and the movement logic and 1000 and before long you had some kind of snake clone. It’s funny, even though these numbers were arbitrary I’d still occasionally be working on a section of program in the early part of the line numbers and accidentally overwrite a later part.
My primary units of program control were if statements, for loops and the dreaded goto. My primary units of data were primitive integer types, strings and arrays (of integers or strings).
The school daze
Fast forward a few more years. Now I’m in high-school and they’re teaching me Pascal. This language is great. There are no line numbers and you refer to functions and procedures by name. Each function can have sub-functions and functions from the outside can’t see those so you can define little areas of your program and focus on just those bits without ever running out of line numbers. If you get a really big program you can define units (but I never really do).
I almost never use gotos any more but I use select-case statements and call functions a lot. To the for-loop I added a do-while and a repeat-until and of course if was still around. There’s pointers but that stuff is hard. In the data space we got the record which was amazing. Now I could start creating abstractions like person, customer and salesrecord. At least in class, my own programs lacked such sophistication. The most complex program I wrote in this era, a simulation of the classic board-game battleship, used 2 10x10 arrays so I saw no need.
Wander forward in time again. Not too far as I’m gaining momentum now. About half way through high-school. They’re trying to teach me logo (is that not a step down from Pascal?) but I bought a C++ compiler and snuck it into class. Here we can create classes which is this weird organizational thingy where we have a record with some functions on it (to save it to disk or print it on the screen or calculate age or whatever you needed). There’s also these things called objects which are related to classes somehow but I’m not entirely sure how. Apparently global variables are bad so you put them in a class which limit’s their scope (Pascal was big on scope so I know that word). There’s also this thing called inheritance where you can re-use code without copying and pasting but as everything is a function you can get a lot of re-use from having a large mass of parameters (or declaring class variables).
I guess you can tell that OO was completely lost on me. Polymorphism, Inheritance and Encapsulation are really big words that were explained to me in very academic language from very dry books and their meaning and it’s potential impact on me at this stage in my education are completely lost. Effectively I’m writing Pascal code using the C++ language.
So I graduate high-school and move to university. Here they teach us assembly (using the IJVM) and functional programming (in gofer of all languages). It was a weird course. There is some C (which I figured was like C++ only far less confusing) and then we were introduced to Java.
This was a language in which everything is an object (or class, I hadn’t yet figured out the difference). If you wanted to write stuff to the screen you might call upon the services of screen object or if you wanted to read from a file then you’d use a file object.
Lecturers spoke about encapsulation whilst showing a slide of a person object with a private dob field and a public getAge method. They showed us Inheritance hierarchies containing Shape, Circle and Square and how we could add a draw method to each and then draw a list of “shapes” without knowing which we were dealing with. In short very, very simple examples.
Next we were introduced to the UML Class diagrams. To me this notation (which is meant to help people understand object collaborations) just reinforced my views that the whole class thing was an organizational unit. After all what looks easier in a diagram? One box with one label that says “SendNewsletter” or 5 boxes that collaborate (whilst remaining decoupled) to send a branded, personalized monthly newsletter to some subset of users in a database.
In my experience UML makes it too easy for the inexperienced user to ignore complexity and give a complex issue a very shallow treatment. Every box becomes a Facade for a system you don’t bother to draw (and hence is never implemented).
I was in tertiary institutions for a total of 10 years (2 universities and 1 TAFE) and I managed to graduate without understanding Objects in the slightest. The few people that I am still in contact with from those days seem to be in pretty much the same boat. In point of fact, if I look around at the industry at large I don’t see a lot of people engaged in OO Design at all.
The Real World (TM)
Since leaving my structured studies behind and tackling more real world problems I have become more and more aware of the lack of OO knowledge in myself and those around me.
Whenever I’m confronted with an existing scenario and new complexity is introduced I open my tool-box and find find my trusty if-else-statement or switch-statement. After a while this makes my methods disappear off of the bottom of the screen and so I tend to use the handy extract-method refactoring which is built into Visual Studio to break it up a bit.
There are a few people that I’ve worked with (most I’d guess) who think that this is going a bit too far. After all, how are they supposed to figure out what is going on when I keep breaking bits of logic out on their own. Now they have to skip about the class looking at each of the methods in turn and use their highly-prized UML skills to construct a sequence diagram. Or they would if anyone cared about sequence diagrams. More likely they’ll invent their own diagramming technique for program flow and then use that which makes it impossible for them to effectively communicate their findings to anyone else.
People will lose the plot even more if you start adding in collaborating objects into the mix. Now they have to check in different files for what is going on and their home-spun diagrams have stopped making sense even to themselves. They say they’d prefer simplicity and maintainability and yet they refuse to acknowledge the benefits of the SOLID design principles. Oh that’s just for complex stuff, they’ll say. We just get data on and off of forms with some business rules.
I have some news for you. That IS the level of complexity of most systems. Most systems boil down to business rules, data entry and reporting. Most of the other stuff you do is probably to support one of those 3 things.
So why don’t we leverage Object Oriented design and thought processes? I think that Kent Beck and Ward Cunningham summarized what I feel the issue is quite nicely in their paper entitled “A Laboratory For Teaching Object-Oriented Thinking”:
The very reason that OO became a dominant paradigm in the first place is because the programmers of the day were unable to keep track of the state of their entire application as those applications got bigger and bigger. To counter this effect they invented a technique for breaking the program into smaller chunks that could each act as a discrete unit and could delegate tasks out to or request required information from other chunks as required. This meant that the programmer no longer needed to know the state of the entire program to make changes. Instead we can work within the confines of a single class and assume that our collaborating classes know their job.
Very few of us seem to have mastered this (and I count myself as one who hasn’t). You can see that when people start writing down call stacks and setting breakpoints in their code. It is fundamental to the way a programmers mind typically works that we have to have all of the information. We cannot let go at the borders of a single object but we have been told that we must. So the solution is to cram as much into a class as we can. After all, a class that does 27 things is more reusable than one which does 2 or 3 right? And I can’t just add new classes to the system, who will update the UML diagram?
It’s interesting to note that some DO seem to get it. Many frameworks and libraries get quite clever and use OO techniques under the covers. These same libraries have a habit of throwing a darned Facade in the way making the end user capable of using them without understanding a single thing about how they work. I guess the smart guys got sick of the rest of us harping on about what we need to do to use their stuff.
Some frameworks get really bold and require us to create our own classes. The usually proscribe 2 or 3 types of class that are necessary (i.e. View, Presenter and Entity) and so we go about creating one of those whenever we really have to. We make those classes work really hard though don’t we? They end up with a lot of variables and methods. In fact they end up like little Pascal programs all on their own.
Is this a problem? I feel like Neo standing before Morpheus in The Matrix wondering whether to take the Red Pill or the Blue Pill. Either the industry is full of people making the same mistakes over and over or I’m fooling myself about our potential effectiveness.
I don’t have all the answers but I’m attacking this one the same way that I usually do. Reading voraciously and trying to absorb so much knowledge that hopefully some small portion will stick. I’m looking for good materials on learning (and teaching) good OO techniques so if you know of any, leave me a comment.
I believe that this isn’t an effective way of learning OO techniques though. They need to be applied to real world problems. Ones that have jagged edge cases.
I think that taking special care of the Single Responsibility Principle and aggressively refactoring code regularly will help. I also think that designing for testability (and in particular Test-First) are also great at making us aware of where the edges of our classes are.
What do you think? Do you do OO? Are those around you baffled by your preference for creating new classes over new methods? Do they see you producing very small units of logic and data and wonder how you keep track of the big picture? Do they ever create a new class to encapsulate an existing concept or do they just create mammoth utility classes with 500 static methods?
The OO train may still be at the station. Have you got your ticket?
No new comments are allowed on this post.