What is Object Oriented Programming: A Critical Approach

These days if a programming language ain’t got that OOP, it ain’t worth a thing. Well, anyway, that’s how it sometimes seems. When I started programming back in the early 80’s hardly anyone had heard of OOP (Object Oriented Programming). When Byte magazine published a “Special Issue on Smalltalk” in 1981, the writers had to explain not only what object orientation was but also how a graphical user interface worked (most computers had text-based displays). They even had to give an explanation of a weird little pointing device called a mouse which was bafflingly strange to most readers.

This 1981 edition of Byte magazine gave most programmers their first look at an Object Oriented programming language.

Smalltalk was a language developed by a team that included Alan Kay at Xerox PARC (Palo Alto Research Center). It was Kay who coined the term object-oriented programming.  Most other mainstream languages at the time implemented procedural programming in which the fundamental building blocks were the named subroutines or procedures. In Smalltalk, the fundamental building blocks were called objects.

A Smalltalk object wrapped up bits of data with the procedures needed to act upon that data. When some programming task needed to be done, a message could be sent to an object and the object would try to find some method of responding to that message. For example, the message talk might be sent to a Parrot object, and the parrot’s talk method would respond, “Pretty Polly!” But when the talk message was sent to a Dog object, its talk method would respond, “Woof!”

Another great feature of Object Orientation was inheritance. This meant that you could create a base object type – let’s call it an Animal object – to wrap up the data and methods common to all types of animal. So the Animal object type (that is the Animal class) would have methods to handle eating, drinking and sleeping. Then descendent classes such as Parrot and Dog could be created. These would automatically inherit all the behaviour of the Animal class and add on additional special features such as the ability of a Parrot to fly and the ability of a dog to chew the furniture.

The end result was that program code was simpler (inheriting all that existing behaviour meant that you didn’t have to keep rewriting stuff all the time) and safer (by wrapping up data and methods inside objects, you could be sure that other programmers weren’t messing about with code you wanted to keep to yourself). Remember, that the code outside an object has to communicate with the code inside an object by sending messages to that object. It is left to each object to decide how it should respond to each message.

So now everything was fine and dandy. Object orientation was a big improvement on procedural languages and pretty soon many other languages decided to have objects of their own. Old-fashioned procedural C was suddenly expanded into new, gleaming C++. Then along came other languages that mixed up a C-like syntax with Object Orientation: Objective-C, Java, ActionScript and C#. There were non-C-like Object Oriented languages too – Ruby, Python, Object Pascal and others.

And did all these OOP languages make programmers more productive? Did they make programs simpler, clearer and more elegant? The simple answer is: No, they did not.

Far from being simpler than C, the C++ language is much more complicated. Similarly, Object Pascal is more complex than procedural Pascal. As for newer languages such as Ruby, which were designed with objects from the ground up – well, they have both pros and cons. On the plus side, they give the careful programmer the ability to create well-structured reusable code. On the minus side, they let the careless programmer create programs of such baroque complexity that they are impossible to maintain and debug.

There are a few reasons why the great ideas of Smalltalk have failed to live up to their promise in other languages. One serious deficiency, in my opinion, is that few Object Oriented languages do a really good job of hiding the internal data of objects. This means that programmers can take shortcuts. Instead of sending messages (or making method-calls) they can just poke right into the objects and mess around with the internal data. In other words, they can make their code dependent upon the internal details of the objects being used. That is contrary to one of Smalltalk’s key ideas.

This is what Dan Ingalls, one of the principal architects of Smalltalk, has to say in the Byte Smalltalk special issue: “No component in a complex system should depend on the internal details of any other component.”

If the internal details of an object can be accessed from outside that object and if the programmer then changes those internal details, those changes may have unpredictable side-effects on other code in a complex program. Programmers often think that encapsulation (the wrapping up of data and methods in objects) is in itself a safety net that protects their code from errors. It isn’t. Not unless you enforce strict modularity and data hiding to ensure that the internal details of your objects are invisible to the code outside those objects.

This is Dan Ingalls again, discussing the importance of modularity:

“The message-sending metaphor provides modularity by decoupling the intent of a message (embodied in its name) from the method used by the recipient to carry out the intent. Structural information is similarly protected because all access to the internal state of an object is through this same message interface.”

Alan Kay has expressed regret that he overemphasized the benefits of objects at the expense of messages. He has said: “I’m sorry that I long ago coined the term ‘objects’ for this topic because it gets many people to focus on the lesser idea. The big idea is ‘messaging’… The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be.”

Another of the key features which made Smalltalk so revolutionary, and such a delight to use, was its programming environment. Smalltalk was not conceived as a stand-alone language. It was created to be a complete, unified programming system. Its editing windows and browsers were all, in effect, Smalltalk objects. In Smalltalk you can create a new window by evaluating a piece of Smalltalk code. You can change the development environment by writing new Smalltalk classes.

This shows a 1980’s version of Smalltalk. Its multi-window graphical environment was revolutionary for its day.

In most modern Object Oriented languages, the language itself either has no dedicated environment at all or, if it has one, that environment has no close connection to the language. So with Ruby, for example, you are free to pick a text editor of your choice but neither the language nor the editor are in any way aware of one another. In C# you are likely to be using Visual Studio, but you cannot evaluate some C# code in order to create new Visual Studio windows.

Put simply, most modern OOP languages have picked up a random bunch of stuff from Smalltalk and forgotten about what made Smalltalk beautiful. As a consequence those languages are often no simpler or safer or more elegant and beautiful than older procedural languages.

Alan Kay has said, “When C++ came out, they tried to cater to C programmers, and they made a system that was neither fish nor fowl. And that’s true of most of the things that are called object-oriented systems today.”

Sadly, I think he’s right. That doesn’t mean that you cannot write beautiful, modular code using modern OOP languages. What it does mean, however, is that you have to exercise a good deal of self-discipline in order to do so. In my view, the beauty is in the simplicity.

About the Author

Huw Collingbourne has more than 30 years of programming experience and is currently the technology director at SapphireSteel Software, developers of the “Ruby In Steel” Ruby and Rails IDE for Visual Studio and the “Amethyst” IDE for the Adobe Flash Platform. Check out Huw’s popular online programming courses: Advanced Ruby Programming, Learn C# Programming, Ruby Programming for Beginners, Learn to Program with Pascal, and Breaking into the Programming Business.


  1. Patrick Beard says:

    Objective-C does intone the messaging mantra. Over the years the maintainers of Objective-C have resisted the temptation to break encapsulation to sipped things up. For that reason, Objective-C frameworks are flexible and can evolve without breaking existing clients. Try that with C++.

  2. I've also written code for 30 years, starting in C, moving to C++ and eventually C#, so naturally I too have an opinion on this subject. Like any tool, object oriented programming can be misused. But encapsulation, polymorphism and dynamic dispatch are powerful concepts that make working with a large-scale program significantly easier in OOP than a functional language. However, I submit that the move to managed languages was even a more important step to making large-scale software projects maintainable. I often compare writing C++ code to cutting the lawn with scissors, whereas C# is like a riding lawn mower. I have much more control with scissors, but a lawn mower is significantly faster and easier. With C# (or Java) I'm no longer spending hours each day chasing down errors that have nothing to do with the overall domain problem I'm trying to solve. Errors including null and invalid pointers, pointers to pointers, improper dereferencing, memory leaks, etc. I would argue just the opposite–that it takes much more discipline, effort and time to write and manage a large-scale software project in a functional language such as C than in an OO managed language such as C#.

  3. To be fair, though, it's a really slow riding lawn mower, while the scissor implementation cuts the lawn really fast.

  4. Sebastian Nozzi says:

    "As for newer languages such as Ruby, which were designed with objects from the ground up – well, they have both pros and cons. On the plus side, they give the careful programmer the ability to create well-structured reusable code. On the minus side, they let the careless programmer create programs of such baroque complexity that they are impossible to maintain and debug".

    First let me say that I like Smalltalk much more than Ruby. But I was struggling in understanding the statement above. What is it, in your opinion, the factor in Ruby that would lead to a codebase more difficult to maintain than a Smalltalk one? The meta-programming abilities? The lack of an integrated IDE?

Speak Your Mind