TweetFollow Us on Twitter

OOP World
Volume Number:7
Issue Number:9
Column Tag:Developer's Forum

OOP in a non-OOP World

By Steve Sheets, Herndon, VA

[The following article was based on a presentation at the 1990 MacWorld conference in Boston. The speech was given as part of a panel discussion on Object Oriented Programming.]

OOP in a non-OOP World.

“Object Oriented Programming.” These words congure up images of new programming langauges like Smalltalk and C++. Visions of programmers everywhere, throwing out their old compilers and sample code, and starting to program exclusively in an Object Oriented Programming Language are called to mind. Jokes about those who can only program in C or Pascal (“how many Pascal Programmer does it take...”) begin to appear.

Time will tell if the above situations are more spoof than prediction. However, the thinking that inspired them has a very specific fallacy that I would like to address. First, let it be known that I am one of the world’s biggest fans of Object Oriented Programming. I honestly believe that object oriented programming is likely to become the next step in the evolution of programming languages. However, I do not agree that this next step in programming style will be the exclusive domain of the new Object Oriented Programming Langauges. This article intends to show how to make use of object oriented techniques while programming in a non-object-oriented environment. It is possible to use the ideas contained in Object Oriented Programming Languages without using the traditional object oriented constructs like objects, classes, inheritances, or methods. To understand how to go about using the techniques, but not the items, a little history lesson is in order. Even though this lesson is on a slightly different subject, it does have a point.

Back in the long ago, when Computers were first created and introduced to the swarms of eager programmers, the majority of the programming languages were line oriented. Languages like Basic and early versions of Fortran and Cobol usually paralleled Assembly language, where almost every line of code did a specific task and every line was followed by another line of code.

The flow of the program was usually from one line to another. The GOTO or Conditional GOTO statements (or their equivalents) were used to control the flow by branching, but in general, the flow was linear. This technique could cause problems. For one thing, a programmer had to understand practically every single line of the code before he could work with any piece of it. Otherwise, he would never know for sure if the portion of the code he was modifying had an effect on some other line of code. If a person were to try to work with code he had not created, he would likely have to spend a great deal of time studying it before he could work with it.

A second, nastier problem with the linear flow arrangement became apparent as programs became more complex. A simple piece of code might be modified again and again, with different branches at many points in the code. Soon programmers started getting Spaghetti Code, where the code was so complex, and the flow so strange, that no one, perhaps not even the original programmer, could understand how the code worked.

To solve this problem, more Procedural oriented languages were introduced. Languages like Pascal, C, and later expanded versions of line oriented languages were given syntax and commands that allowed a programmer to divide the code into more manageable procedures. People stated talking about the joys of this new Procedural Programming style.

Now a interesting thing started happening. Programmers who used the procedural languages, and who learned the joy of procedural programming, would sometimes still have to program using the older languages. However, they had gotten used to the advantages of the newer languages. So they added some of those new ideas to their programs, even though they were using the old languages. They wrote the programs so that they had separate subroutines and functions. Even Basic could be written in this procedural style, once the programmer understood the concept.

Notice that just because a program is written in a good procedural base programming language, it does not necessarily follow that the program is good code. Some of the worst examples of spaghetti code have been written in the so called higher level languages. These languages just made it easier to learn a new idea, like procedural programming. The languages helped to teach programmers good programming habits. Once the style was learned, it was not necessary to use the new language or features in order to implement the technique.

That’s the end of the history lesson. Now, to come back to the present; nearly everyone has been exclaiming the joys of these new Object Oriented Programming Languages. Notice any possible parallel to my history lesson? Just like those who years ago promoted Procedural Programming, they are right. There are many benefits to using object oriented programming. This new type of programming will allow you to code better. But you do not have to use Smalltalk or C++ or Object Pascal in order to implement the benefits of object oriented programming.

Many programmers would probably like to use an object oriented approach, or at least they would be interested in learning about it. However, these people may be unable, for perfectly valid reasons, to start using an Object Oriented Programming Language today. Many may have to work in a language specified by their company, or one that is specified by their job contract. Some may have to work on a computer that does not have a Object Oriented Programming Language. Or some might have to program with co-workers who have not yet “seen the light” of Object Oriented Programming. And many may have already invested a large amount of time and energy a piece of non-object-oriented code, resources they might not have to reinvest in order to convert over to an object oriented approach.

That last reason was the one that kept me from using an Object Oriented Programming Language on my project, America Online. There was already an Alpha version of the code written in Think Pascal, without Object extensions. Neither MacApp or any other Object Oriented Programming Language was an option for America Online when I came onto the project. While there is almost nothing left of the original Alpha code in the current version of America Online, there never was a time when we could take the time that would have been needed to convert the entire code to use Object Pascal extensions or MacApp. So instead, what we did was to look at various parts of America Online and decided what we could improve using what we had learned about America Online.

Since I’m going to refer frequently to my project in this article, perhaps I’d better give you a little information about it. For those who are not familiar with it, America Online is a telecommunication service which connects our host mainframe to personal computers using proprietary protocols and software. In my case, we are using Macintoshes connected over a serial modem line. Using a low-level protocol, packets of data are transferred, error free, from the host to the Mac or visa versa. When a data packet comes in, the first few bytes of data designate what task that packet is intended to preform. A group of tasks related to a specific online function is called an “Engine”. Engines include the Form Engine (to create the windows), the Chat engine (to handle online chat rooms), Async Engine (to handle other actions), File transfer engine (to handle uploads & downloads), the LogOn Engine (to handle the log on process), and the LogOff engine (which handles the log off process).

When a packet of information comes in from the Host, America Online has to decide which engine handles that packet. Originally, America Online used procedural styles. Each Engine had a Packet Handling routine that decided whether or not that packet was handled by that engine. If it did, the packet was handled and the function returned TRUE. If it did not, the function did nothing but return FALSE. Every engine accessed the global variable space of the program in order to store states.

The original code segment that parsed a packet looked something like this.


FUNCTION Form_Engine(thePacket:TDataType);   FORWARD;
FUNCTION Chat_Engine(thePacket:TDataType);   FORWARD;
FUNCTION File_Engine(thePacket:TDataType);   FORWARD;
FUNCTION LogOn_Engine(thePacket:TDataType);  FORWARD;
FUNCTION LogOff_Engine(thePacket:TDataType); FORWARD;

PROCEDURE ParsePacket(thePacket:TDataType);
 IF NOT Form_Engine(thePacket) THEN
 IF NOT Chat_Engine(thePacket) THEN
 IF NOT Async_Engine(thePacket) THEN
 IF NOT File_Engine(thePacket) THEN
 IF NOT LogOn_Engine(thePacket) THEN
 IF NOT LogOff_Engine(thePacket) THEN

This piece of code just simply bothered me. It looks cumbersome and is difficult to manipulate. Each engine is always called, no matter whether or not the engine is on. There is no sense of which packet might effect what global data. Adding more engines to the code made the code segment even more awkward.

So I decided to apply a few of the techniques that I learned in Object Oriented Programming classes. I created some new data structures. These new structures included a new record type (TEngineRec), a pointer to this record (TEnginePtr) and a handle to the record (TEngineHdl). TEngineRec consisted of a TEngineHdl, a normal data Handle and a ProcPtr.


 EngineData: Handle;
 EngineProc: ProcPtr;
 NextEngine: TEngineHdl;
 TEnginePtr = ^TEngineRec;
 TEngineHdl = ^TEnginePtr;

For those unfamiliar with ProcPtr, it is a pointer to an actual procedure or function in memory. Depending on your language or development system, it allows the procedure it indicates to be invoked. To do the actual invoking of this procedure, I defined an Inline call that places the correct parameters on the stack and then jumps to the procedure the pointer is aimed at and executes it.

In order to make this code work, I also created one global variable, GEngineList, a TEngineHdl type.

VARGEngineList: TEngineHdl;

Obviously the idea was to try to create a linked list of Engines. GEngineList points to the first Engine in the list, and each engine points to the next one. A set of routines to add and subtract Engines to the the list was also needed. I therefore declare the following call.


FUNCTION AddEngine(theProc:ProcPtr;theData:Handle):TEngineHdl;

PROCEDURE RemoveEngine(theEngine:TEngineHdl);

These routines are uses to add and remove an engine from our list of active engines. The AddEngine call would be invoked like this:



theFormData :=...{Code to initilize data}...


Notice that when an engine was added, the pointer was passed to the Engine’s Packet_Handling routine. That routine will be executed later, when a packet comes in.

Now, let us revisit the original piece of code. The original code will pass a packet to all engines until it finds one that wants the packet. The new code only passes packets to engines that have been installed.


PROCEDURE New_ParsePacket(thePacket:TDataType);
 theList :=GEngineList;
 WHILE (NOT Handled) and (theList<>NIL) DO BEGIN
   IF Call_To_Proc(thePacket,theList^^.theData, theList^^.theProc)
 THEN Handled:=TRUE
 ELSE theList:=theList^^.NextEngine

Call_To_Proc is a glue routine that actually jumps to the Procedure pointed to at theList^^.theProc with thePacket and theList^^.theData as parameters.

Now, imagine what happens during a normal logon sequence. As a user first goes online, a LogOn Engine is created. Once the person is completely online, the LogOn Engine is removed and it’s handle and data handle are deallocated from memory. Then the Forms Engine and the Async engines are added to the Engine List. These Engines normally run for the life of an online session to handle most normal forms and asynchronous events.

At some point the user might decide to go to a Chat room. The Chat engine is added when, and only when, the user enters a Chat room. When he leaves the Chat room, the engine is removed. The same can happen to a File transfer engine.

Some of the advantages of this approach become apparent if you consider how we can use the new code to create new situations. Since the data for each engine is completely contained in that engines data handle, the protocol could be changed so that a user can be in more than one chat room at the same time. This would mean a chat room packet would have to have some information in it to determine whether it pertained to room “A” or room “B”, but that information would only require a couple of bytes of data and would be easy to include.

There is no reason why File transfer, or any other engine that could be conceived, could not be added and invoked any number of times, at any point in an online session. This gives us an amazingly powerful online asynchronous environment. What we are really seeing is an example of the Object Oriented concept of encapsulation of data and the concept of instance of an object.

More than one instance can easily be added to the code at any time. Until an instance is added, additional memory need not be allocated. If an engine is changed, or even if a new one is added, only routines related to the new engine need to be added. The parser code segment used to send a packet to the correct engine is never changed.

I have always considered Data Encapsulation and Instance of objects to be two of the three most important ideas associated with Object Oriented Programming. The third important idea is that of Inheritance. And this function of an Object Oriented Programming Language can be adopted to non-Object Oriented Programming Languages, too.

Actually we are already halfway there in our example. ProcPtrs can be manipulated so that certain data structures have pointers to some procedures, while other instances use other procedures. This simulates the idea that a method can be overridden or inherited. To see this more easily, lets consider another example that has ProcPtrs.

America Online has a very complete Forms engine that allows us to create almost any form using packets sent from the host. Each form packet has information describing windows and different fields on these windows. Different field types that can be on a window might include buttons, icons, pictures, non-editable text, editable text, lists, and so on. All the fields have certain tasks that they have to be able to perform. For example, each field must be able to be drawn, it must be able to handle a mousedown in it’s area, it must be able to be hilited, it must be able to handle a keystroke, it must be able to invert itself and it must have an action associated with it. Following this idea, a field data structure might look like this.


FieldRec = RECORD
  fArea : Rect;
  fActionNum : INTEGER;
  fText: Str255;
  fData : Handle;
  pMouseDown,pUpdate,pActivate,pHilite,pKeydown,pAction : ProcPtr;

FieldRec = ^ FieldPtr;
FieldHdl = ^FieldPtr;

Besides the data, a number of ProcPtrs are declared, one for each major task. Some of the tasks might be do nothing tasks. For instance, a non-editable text field would ignore keystrokes, or a picture would not need to have an action associated with it. Others are more specific for the given field type (the keystroke routine for an editable text field).

For example, when the window needs to be updated, the code might find the field list for that window. Then it would one by one cycle through each of the fields, invoking the draw command so that that portion of the window is drawn. That code would look something like the following example. Notice if the ProcPtr is nil, that means there is a do-nothing task, and it should be skipped.


PROCEDURE UpdateDisplay(theDisplay:DisplayHdl);
VAR theField:FieldHdl;
   IF theField^^.pUpdate<>NIL
   THEN Invoke_Update(theField,theField^^.pUpdate);

If a mousedown occurs, a similar scan is done. In that case, each field is checked to see if the mousedown occurs in it. The Mousedown ProcPtr will only be invoked if the mousedown has occurred in the relevant field. Notice that no matter which type of field is used, these pieces of code will never change.

Somewhere in the code, there will be a segment of code that creates these fields; this procedure is called New_Field. Each kind of field will have its own declaration section in the procedure. For example, a picture might look like this.


VAR theField:FieldHdl;
 kPicture: BEGIN

You can see that this kind field basically does nothing but draw itself. A more interesting kind of field might be a clickable Icon field.


 kClickIcon: BEGIN

This type of field has it’s own draw and invert calls. It also uses the Track_Invert call in order to handle a mousedown. That call keeps track of whether or not the mouse is inside the field area. It invokes the Invert ProcPtr repeatedly to hilite or unhilite the field depending on if the mouse is in or out of the area. If the user releases the button while the mouse is over the field, that call invokes the Action ProcPtr. The action ProcPtr is the most generic one, the Do_Action_Number procedure which does an action defined in the ActionNumber field.

If an entirely new kind of field needs to be created, say for example a clickable Picture, some of the previously defined routines could be used (inherited) to define this kind of object. This code would be added to the new field.


 kClickPict: BEGIN

We have created a new type of field, with it’s own specific appearance and function, without adding any new code except for the creation routine. Even if we had to create a new field with a new special task, (such as a new way to handle drawing,) only a single new procedure would need to be written (in this case, Draw_Bitmap_Icon). We can use the old procedures/tasks for the rest of the new field.

Notice that this Clickable PICT field is related to a non-Clickable PICT field. These fields don’t quite function as a superclass and a subclass, but there is a relationship involved. This might not be true inheritance, but it sure does make it easier to create new fields when they are needed.

Inheritance, instancing of objects and data encapsulation are possibly the three most important ideas in object oriented programming, and they have all been simulated in a non-object-oriented procedural language. And I would like to add that this this is not merely sample code that is never used in a real-world application. These three ideas are used over and over again inside of America Online.

The code would have never been designed the way it was if I had not aware of the object oriented concepts and had not seen them used in a object oriented world. America Online is a better product because of the object oriented lessons learned. The code is more flexible, easier to work with and more powerful. Even if a programmer is never to use MacApp in a major project, or he is never to use an Object Oriented Programming Language in a job, the project or job he is working on, the code he creates may be better if he uses the object oriented concepts he learns.


Community Search:
MacTech Search:

Software Updates via MacUpdate

Typinator 6.7 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Adobe Lightroom 6.2 - Import, develop, a...
Adobe Lightroom is available as part of Adobe Creative Cloud for as little as $9.99/month bundled with Photoshop CC as part of the photography package. Lightroom 6 is also available for purchase as a... Read more
ForeverSave 2.1.4 - Universal auto-save...
ForeverSave auto-saves all documents you're working on while simultaneously doing backup versioning in the background. Lost data can be quickly restored at any time. Losing data, caused by... Read more
VueScan 9.5.27 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
AirPort Utility 6.3.6 - Set up and manag...
Note: Most recent release available only within OS X 10.11 El Capitan update. Use AirPort Utility to set up and manage your Wi-Fi network and AirPort base stations, including AirPort Express, AirPort... Read more
Quicksilver 1.3.1 - Application launcher...
Quicksilver is a light, fast and free Mac application that gives you the power to control your Mac with keystrokes alone. Quicksilver allows you to find what you need quickly and easily, then act... Read more
Tidy Up (Five Users) 4.1.5 - Find duplic...
Tidy Up is a complete duplicate finder and disk-tidiness utility. With Tidy Up you can search for duplicate files and packages by the owner application, content, type, creator, extension, time... Read more
Mellel 3.4.3 - The word processor of cho...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
Skype - Voice-over-internet p...
Skype allows you to talk to friends, family and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more
Bookends 12.6.0 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Access the power of Bookends directly from Mellel, Nisus Writer Pro, or MS Word (... Read more

Swords & Crossbones: An Epic Pirate...
Swords & Crossbones: An Epic Pirate Story 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: | Read more »
Camel Up (Games)
Camel Up 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: | Read more »
The Martian: Bring Him Home (Games)
The Martian: Bring Him Home 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Based on the best selling novel and critically acclaimed film, THE MARTIAN tells the story of Astronaut Mark... | Read more »
This Week at 148Apps: September 21-30, 2...
Leap Into Fall With 148Apps How do you know what apps are worth your time and money? Just look to the review team at 148Apps. We sort through the chaos and find the apps you're looking for. The ones we love become Editor’s Choice, standing out above... | Read more »
Tweetbot 4 for Twitter (Social Networki...
Tweetbot 4 for Twitter 4.0 Device: iOS Universal Category: Social Networking Price: $4.99, Version: 4.0 (iTunes) Description: *** 50% off for a limited time. *** | Read more »
Mori (Games)
Mori 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Stop, rewind and unwind with Mori. Time is always running, take a moment to take control. Mori is an action puzzle game about infinitely... | Read more »
100 Years' War (Games)
100 Years' War 1.0 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: | Read more »
Tower in the Sky (Games)
Tower in the Sky 0.0.60 Device: iOS Universal Category: Games Price: $1.99, Version: 0.0.60 (iTunes) Description: | Read more »
hocus. (Games)
hocus. 1.0.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0.0 (iTunes) Description: New, polished, mind-bending, minimal puzzle game with dozens of levels and extra-ordinary design Features:- Beautifully crafted... | Read more »
Mos Speedrun 2 (Games)
Mos Speedrun 2 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Mos is back, in her biggest and most exciting adventure ever! Wall-jump to victory through 30 mysterious, action packed levels... | Read more »

Price Scanner via

13-inch 2.5GHz MacBook Pro (refurbished) avai...
Apple has Certified Refurbished 13″ 2.5GHz MacBook Pros available for $829, or $270 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook Pros... Read more
27-inch 3.2GHz iMac on sale for $1689, save $...
Adorama has the 27″ 3.2GHz iMac on sale for $1689 including free shipping plus NY & NJ sales tax only. Their price is $110 off MSRP. Read more
12-inch Retina MacBooks on sale for up to $12...
B&H Photo has 12″ Retina MacBooks in stock today and on sale for up to $120 off MSRP. B&H will include free shipping, and there is NY sales tax only: - 12″ 1.1GHz Gray Retina MacBook: $1224 $... Read more
Tablets Shaping Up for Growth in 2016 – Strat...
Observing that Apple, Samsung, and Microsoft have refocused what tablet computers can do, market analysis firm Strategy Analytics believes there is immense opportunity for new and replacement sales... Read more
Apple Interbrand’s Number One Most Valuable G...
Apple and Google hold aced #1 and #2 spots respectively in Interbrand’s 2015 Best Global Brands Report, leading all tech brands that now comprise more than a third of the entire rankings value.... Read more
Apple offering refurbished 2015 13-inch Retin...
Apple is offering Certified Refurbished 2015 13″ Retina MacBook Pros for up to $270 (15%) off the cost of new models. An Apple one-year warranty is included with each model, and shipping is free: -... Read more
Apple refurbished 2015 MacBook Airs available...
Apple has Certified Refurbished 2015 11″ and 13″ MacBook Airs (the latest models), available for up to $180 off the cost of new models. An Apple one-year warranty is included with each MacBook, and... Read more
Adobe Photoshop Elements 14 Gets Haze Removal...
The latest iteration of Adobe’s powerful consumer image editing appliction Photoshop Elements 14 analyzes your photo and removes background haze, so your shot looks sharp all the way to the horizon... Read more
Apple refurbished 15-inch Retina MacBook Pros...
Apple has Certified Refurbished 2015 15″ Retina MacBook Pros available for up to $380 off the cost of new models. An Apple one-year warranty is included with each model, and shipping is free: - 15″ 2... Read more
21-inch iMacs on sale for up to $120 off MSRP
B&H Photo has 21″ iMacs on sale for up to $100 off MSRP including free shipping plus NY sales tax only: - 21″ 1.4GHz iMac: $1029.99 $70 off - 21″ 2.7GHz iMac: $1229 $70 off - 21″ 2.9GHz iMac: $... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, you're Read more
Senior Payments Architect - *Apple* Pay - A...
**Job Summary** Apple , Inc. is looking for a highly motivated, innovative and hands-on senior payments architect to join the Apple Pay Engineering team. You will Read more
SW QA Engineer - *Apple* TV - Apple (United...
**Job Summary** The Apple TV team is looking for experienced Quality Assurance Engineers with a passion for delivering first in class home entertainment solutions. **Key Read more
Finance Manager, *Apple* Online Store - App...
…successful global retailer. Innovate and think creatively as a finance partner for the Apple Online Store team. Look ahead and anticipate the needs of your business. Read more
*Apple* Retail for Business Support Supervis...
…is looking for a motivated, outgoing, and creative individual who wants to offer Apple Business Customers an unparalleled customer experience. The Apple Retail for Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.