Skip to content

How to Think About Object Oriented Design

Introduction

This article is intended both to introduce object orientation to those new to the subject and to address some common conceptual misunderstandings about how object orientation works (and doesn’t work). I’ve been planning to write on this subject for some time but have never had time to write it all down. So I intend to build this article in "installments" — whenever I get time, I’ll add a new topic. You can follow the article as it’s written, and I’d love your comments. Please do bear in mind, however, that until this notice is removed it’s an unfinished document.

Object oriented design is here to stay. I can’t say for how long, but I don’t see its successor on the horizon, so, love it or hate it, those of us working in software today need to understand it. Yet one of the things which is tricky about object orientation is that it is possible to use object oriented code without really understanding object orientation in general. It is, in that sense, deceptively, and perhaps dangerously, simple.

But it’s also complicated: I do remember how confusing it was to learn some of the concepts when I used my first object oriented language, despite the fact that that language — the Whitewater Group’s Actor — had what is to this day some of the best documentation ever written for those new to objects. It was in a sense like learning calculus — a bit confusing at first, but after a while you start to develop an innate sense for what an integral is and then it all starts to make sense.

Object Orientation is an Attempt to Solve the Problem of Software Complexity

Many introductions to this subject start with the so-called "pillars" of object orientation (abstraction, encapsulation, inheritance, and polymorphism). While these principles are indeed important, I think they are confusing to folks who don’t already have a conceptual understanding of objects and so rather than begin there I want to step back a bit and look at why we bother with objects at all. I’ll derive the "pillars" later on.

Indeed, the "pillars" are a solution, and you can’t ever understand any solution without knowing what the problem is. The problem, in this case, is very simple to describe: Software becomes more complicated every year. The word processor of today has orders of magnitude more features — and hence, code — than the operating system of decades ago. This code, however, still has to be maintained by human beings, and better tools alone won’t solve the problem of understanding and maintaining it. Nor will larger teams, because more people means you have to make a proportionately larger effort to make the code understandable to relative strangers. Since tools are only a partial solution and there’s a diminishing return on adding manpower, we need a method of structuring the code we write to be understandable and maintainable even if the applications are so large that no single human can ever read, much less understand, the entire code base.

I consider the following to be a "golden rule" of object orientation.

Object orientation is a method of making extremely complicated software understandable and maintainable. If using objects makes your code more difficult for others to maintain then you are probably doing it wrong.

It is possible to drive a nail with a pipe wrench, but a hammer is a generally better-suited tool for that purpose. Similarly, in the world of software we have many different syntactic tools (programming constructs) at our disposal, the fact that you can use a certain construct to do a task doesn’t mean you should.

This is no less true for object orientation than it is for templates. When it comes to when and how to use object oriented design techniques, we — meaning those of us who want to build reliable and maintainable software systems as opposed to jargon-compliant bloatware — must always keep in mind why we bother to use the techniques at all: Not out of blind allegiance to some abstract rules about the way that software should be written but because we derive real benefits, namely, the ability to get our jobs done, from structuring code for understandability. If our designs are so obtusely structured that they are only understandable to the designer then we have failed.

Before we examine how object orientation can help solve this problem, let’s take a look at some of the other, non-object-oriented methods of addressing the same issue:

Namespaces
Namespaces are like folders in your file drawer. Rather than looking for a piece of paper amongst the 10000 sheets in the drawer, you can go to an appropriate folder and narrow your search. Namespaces are a fairly significant improvement over a monolithic API (in the same way that adding directories improved DOS — early DOS didn’t have them!), but they’re only a partial solution to the problem of complexity. Even looking only at the problem of organizing functions, there are some aspects of organization that namespaces don’t even begin to address, such as the fundamental difference between when a function is declared and when it is used — both cases may or may not be within the same namespace, and namespaces don’t offer much help in sorting it out. Note that Delphi’s units are a primitive ("primitive" because they don’t have any kind of hierarchy) kind of namespace, so this is a concept which has been in Delphi from version 1, although the namespace support in Delphi 2005 is a good deal more sophisticated.
Prefixes
In the Windows API, related functions tend to share prefixes. For example, functions dealing with COM tend to start with "Co" (e.g., CoInitialize). (But not always!) There’s a fatal problem with this technique, however: It is next to impossible to change such a prefix after it’s been published, because it’s written into countless pieces of code which use the function. At the function level prefixes are at best just a poor substitute for namespaces, and as far as I can tell this technique is really only useful when you need to support tools which have no concept of a namespace.
Structured programming
Whereas namespaces help you find the code you’re looking for, structured programming is an attempt to make it easier to understand. Like namespaces, structured programming is a good technique but only addresses a small part of the software complexity problem.

There are other non-OO solutions as well (and if you think of anything significant that I’ve omitted, please leave a comment), but you get the point: Since complexity is now the rule rather than the exception we need a comprehensive solution to this problem. So let’s try and solve that, and when we’re done we’ll have something which looks a lot like object oriented design.

Tune in soon for the next exciting episode!

{ 5 } Comments

  1. David Melchior | July 1, 2005 at 5:54 am | Permalink

    I think that http://www.geocities.com/tablizer/oopbad.htm makes an interesting starting point for an OOP discussion. (Not that I agree with the claims made on the page)

  2. mike montagne | September 26, 2005 at 1:54 pm | Permalink

    While perhaps a departure point for OO design discussion, this article barely touches the surface of the concept and issues of OO Design. If its readership were not intended to be developers or prospective developers, I can understand the desire to avoid the traditional topical categories. But I think instead, it would be more useful to preface those topics with more tangible definitions of OO programming and OO Design issues. One undoubtable virtue of OOP (expressed in terms for the broadest potential audience) is it is a pattern, without which, almost all application software would far more expensive, and difficult to deliver. OOP, in effect, is a pattern by which software development specializations are delegated, and by which, in the end, application development is reduced to the more manageable responsibilities, of authoring what makes the given application unique. I believe these are the real, driving forces behind the broad adoption of OOP. Perhaps that makes the respective aspects of encapsulation the most important virtue of OOP; and perhaps that further means that these aspects of encapsulation deserve the initial intentions of such a basic article on OOP Design. David, by way of the indicated site, expresses many reservations which, imho, only point out the many human failings to achieve the ideals of OOP. I believe, because of personal work, that on the contrary, we are on the cusp of formalizing a specirication for *how* to design OOP. It is easy to ding OOP for excessive resource footprints for instance. But to contribute to a perception of OOP, it is more useful to suggest the pathway to the perfection of OOP. Obviously, object-oriented techniques are as readily perfected as any other possible programming approach. I would say, on the contrary, that because of the potentials of encapsulation, that OO Design is even *more* readily perfected. There is no *inherent* disadvantage to OOP whatsoever. What I advocate, is the perfection of specifications for trees of descendants, exceptionless programming, and optimized resource deployment — all of which are readily perfected in OO design. The very encapsulation of OOP, and revision of the OO architecture of descendant trees readily possible by OOP, make OOP by far the most preferrable medium for achieving these objectives.

  3. Craig Stuntz | September 26, 2005 at 1:58 pm | Permalink

    Mike:

    > …this article barely touches the surface

    > of the concept and issues of OO Design…

    That’s because I’ve only just started it. Read the highlighted section at the top of the article. There’s a lot fo work yet to do.

  4. mike montagne | September 26, 2005 at 2:29 pm | Permalink

    Yes, I realize that. The real gist of OOP is indeed a difficult issue to put a readership’s hands around. Yet we are certainly within an evolutionary phase where almost all modern application development is OO. A reason we evidently use the same development tools, is evidently a mutual appreciation for the quality of the original abstractions indigenous to those tools. My apologies, if the tone is interpreted as merely critical. The intention was to encourage focus on what makes OO most excellent — which at the same time is to encourage what is vital to the continued health both of our favorite tools, and the entire public surviving by the excellence of underlying concepts. Yes, then: the general public *needs* to grasp the underlying issues, so that we all are empowered to prosper by OO Design. Thus as no article on OO Design will be finished until we altogether ratify a perfected formula for OO Design, in effect, the best that any of us can do to then is categorize the areas of effort, and how all together can be perfected.

  5. Lars | October 16, 2006 at 11:24 pm | Permalink

    From a low level and simple perspective, pbject orientation in Delphi is mainly procedural

    programming with SELF being passed as a hidden parameter and a few other /syntactic sugars/

    going on under the hood.

    When people design OO code, they still eventually do some sort of procedural programming when

    implementing the methods. Objects just allow us to reuse the procedures and keep the code a

    lot neater than procedural code. That doesn’t mean you can’t reuse procedural code!

    Oh, you can - look at all the reusable DLL’s people have written. The entire windows API.

    Reusable procedural code can be inherited and modified just like objects can - it is just

    messier doing it that way! It’s that simple - OO hides code and reduces the verbosity

    of procedural code. It hides some brackets and incoming parameters.

    OO can be emulated in Delphi without using any of the OO features - just use records and

    pass SELF in to each procedure, using GET and SET calls instead of properties. The problem

    with emulating OO using procedural code is that it ends up looking ugly - it’s all

    about syntax sugar. OO let’s us be less verbose than procedural code (and cleaner).

Post a Comment

Your email is never published nor shared. Required fields are marked *

Bad Behavior has blocked 1846 access attempts in the last 7 days.

Close