STRUCTURED PROGRAMMING

Grinding The Speckled Axe

Jeff Duntemann KIGRA/7

There's an old story they tell up in Wisconsin: A farm boy found an old axe chunked into a tree stump while trampin' the deep woods. He brought it home, touched up the edge with his trusty whetstone, and found that it still cut wood as well as an axe oughter. The axe head had gotten mighty rusty over the years, though, and was all pitted and rough.

So the boy asked his paw if he'd grind the axe head full bright agin on the big grinding wheel out aside the barn. And his paw said, "Sure, son -- if you turn the wheel."

So the boy pushed the pedal of the big grinding wheel while his paw pressed the old axehead agin it. The sparks flew, because his paw was a strong man and held the axe head hard agin the wheel. The rust was ground away, but under it all the deepest rust spots still showed as speckles all over the new bright steel.

So the man kept the axe head pressed hard agin the wheel, knowing his son wanted it ground full-bright. But after half an hour, the speckles were fewer but still there, and the boy let up on the pedal so that the wheel stopped.

"Come on, son," his paw said, "we'll make those speckles go away afore sundown!"

But the boy, when he stopped panting, lowered his eyes and said, "Y'know, paw, I heard at school last week that speckled axes was fersure the latest thing."

The Axe or the Pits?

The next time you find yourself working long past sundown grinding the pits from a speckled axe, think hard about the very serious question: What am I working on? The axe or the pits?

It's a funny thing about this programming stuff. Unlike a lot of work I can think of (like being a soda jerk at Walgreen's or going around the backyard in March picking up what the dog's been doing all winter) it's fun. It can become so much fun that watching the sparks and pumping the pedal take on a fascination all their own, regardless of the work actually being done.

Complicating the issue is the fact that a lot of us (and I'm certainly right in there) grind away at the pits because it feels good, without needing to get anything in particular accomplished. This is why there are Mandelbrot Set programs all over the place; man, you want sparks?

Now and then I think it's well worth drawing a sharp line between work that has to be done because the job needs doing, and work that gets done because it feels good. If you get a kick out of spinning elaborate menuing and windowing systems out of thin air, the tendency is to launch in and do it all over again whenever you pick up a consulting project or get a new assignment from the boss. Remember: They're not paying you for the shine. They're paying you for the edge.

Unearthing a Truly Ugly Truth

This bears on the theme I began last month, which is the art of designing with object-oriented techniques. OOP brings a level of modularity and loose coupling to structured programming that has been almost unknown until today. The same well-designed object hierarchy can be used as the foundation for many different applications, in part because of that modularity, and in part because OOP is unexcelled at generalizing functionality. It's the ultimate in efficient boilerplating schemes: Take a generic field object and add to it only what it needs to become a date field object, or a phone number field object, or a Boolean field object. Take what you can. Add only what you must.

So what I'm going to tell you to do early-on in an OOP development project is this: Take a walk in the woods. See what's lying around, and see what you can bring back with you. Resist, as much as possible, the Not Invented Here syndrome. If it works, and if it's even remotely close to what you need, grab it. If necessary, bend your spec to align it with the architecture of the object libraries you find.

I say this for a very important reason. With going on a year of object-oriented exploration behind me, I have identified (and others have verified) a Truly Ugly Truth: Designing a workable and efficient object hierarchy is murder. Much of the ease and the magic in Smalltalk stems from the fact that its standard class libraries are works of brilliance, they're done, they have some history (Smalltalk was in "design mode" for about 15 years before becoming available for small machines), and they're yours with the language. Much the same is true of Actor, and if it doesn't have as many years of history, that's mostly because its authors built on the better features of well-known and thoroughly shaken-out languages such as C and Pascal.

This sounds a little like I'm growing disenchanted with OOP in general. Not true -- but as I said in an earlier column, the hype has gotten way out of hand, especially when we don't really know what OOP's true value to the programming art will turn out to be. People have been attributing "easy, hassle-free prototyping" to the OOP nature of languages such as Smalltalk, when in fact the ease of prototyping was due to the brilliance and completeness of the class libraries. Prototyping in "naked" (that is, class-less) Object Pascal is no easier than prototyping in Extended Pascal, or whatever people will eventually come to call the Turbo Pascal standard language definition.

So if you're launching into an ambitious design project in Object Pascal or (God help us) C++, do not expect the OOP nature of the underlying language to make things easier on you. On the contrary, you will soon be up to your nether parts in some of the most intractable decisions of your entire career.

Drawing Line Between Parent and Child

Let me give you a very simple f'rinstance, one that came up during the terrific Get-TUG-Gether seminar and party in Seattle last summer. (I'd love to shake your hand up there this year -- information is in the "Products Mentioned" box at the end of this column.) I was explaining polymorphism to the group, and using the example of a field editor class. I drew a figure on the whiteboard that looked something like the one shown in Figure 1.

The idea was to create an abstract class named Field, which would never actually be instantiated. Field would take care of all those things that every field -- regardless of its type -- would have to do: Clear some number of characters in a line, lay down a title, indicate that this particular field is active, and so on. But Field would not actually have any "guts" with which to edit data. Instead, child objects of Field would be derived from Field to do the actual editing, through an Edit virtual method present in each.

In Figure 1, I show them as String-Field, IntegerField, and DateField. A StringField object would simply accept string data and allow simple line-type edits on the string data. An IntegerField would allow entry of only numeric digits and supporting characters like the minus sign. If the user attempted to press "W" while executing IntegerField.Edit, the object would beep and refuse the character. Similarly, DateField.Edit would validate a date character by character, perhaps within a template separating day, month, and year subfields. In any event, you edit the data in any of these related objects simply by executing an object's Edit method.

This works -- I've actually written the code since then -- but as the estimable Brian Foley of Turbo Power Software rose to point out, this system is very inefficient from a code standpoint. The three child objects shown in Figure 1 have a lot of code in common, because all three control a cursor within a delimited portion of a line, picking up characters from the keyboard and formatting them on the screen.

Brian took the time to rearrange the figure much as I've shown it in Figure 2. He placed virtually all of the field editing code in a parent object named StringField, because beneath it all, we encode most data in string form anyway. What actually differs among the various types of data is how the data is validated. The child objects all gather information from the user by calling their collective parent's Edit method, and then examine that data for adherence to the specific requirements of the data type after the user has pressed Enter. The StringField parent class has no validation, because any string data enterable by the user is legal tender. StringField is, however, a usable, non-abstract class.

Brian's arrangement eliminates nearly all duplication of code among the various objects. And like my earlier arrangement, it also works. The line is drawn differently between parent and child. Which is best?

There's no single answer. And it's an even messier question than I've shown so far. Suppose I want to add a Boolean Field object to the hierarchy? That is, I want a field to select between two available choices like Yes/No, Male/Female, Active/Suspended, Alive/Deceased. But I don't want the user to have to actually type out either of the two values. I want each field to have a default value, and to allow the user to toggle between the two values for a given field with the click of a mouse or a press on the space bar.

It gets pretty obvious that Boolean-Field needs to be descended from something else, something probably one level higher than StringField. Also, entering the full value of a field in string form and then validating the string after Enter is pressed forbids something I like a lot: Character-by-character entry validation. In Figure 1, an IntegerField will beep a "W" the moment it's pressed. In Figure 2, the "W" won't be detected or an error reported until the user presses Enter. The user has to go back and "fix" the data -- when initially, he or she wouldn't have been allowed to enter invalid data to begin with.

You'll find that subtle changes in the structure of an object hierarchy have lots of odd little side-effects like that. You might leap initially to Brian's arrangement in a quest for code efficiency, only to find that user operability of the application suffers.

Distribution or Extension

I've run into this little conundrum a time or two since then. There seem to be two general ways to construct an object hierarchy. The line between the two is not sharply drawn, and in fact it may not be a line at all -- it's less a difference of technique than a difference of emphasis. My first approach emphasized the distribution of functionality through an abstract class. When you take this approach, you often design a whole tree full of relatively small and simple abstract classes, none of which are capable of instantiation. Each abstract class adds something fairly simple, conceptually, to the hierarchy. From these abstract classes you derive the "leaves" of the hierarchy tree, which are the fully functional classes that may be instantiated and do real work.

The other approach, by contrast, emphasizes fully workable objects almost from the start. The first objects designed lean toward the general-purpose -- as in Brian's string editor -- but they are nonetheless fully functional objects. Abstract classes are kept to a minimum, and the more general objects are extended to produce additional objects, like the IntegerField and DateField objects.

The two approaches differ in another fundamental way. Using many abstract classes allows you to cast a great many objects into just two or three major object hierarchies. Avoiding abstract classes tends to produce numerous small object hierarchies, sometimes with only two r three classes in each.

OK. Which approach is better? Hear me well: We don't know. This is not the same as saying, it doesn't matter. There is no information as to whether maintainability or reusability is affected over time by the approach taken to OOP design. For every question you unearth, the answer only yields two or three more questions.

Getting Bananas the Hard Way

Using one or two monster hierarchies has the downside of giving you the whole gorilla even when you only want the banana, as so aptly put by Scott Guthery in his article in the December 1989 DDJ, "Are the Emperor's New Clothes Object Oriented?" My answer to Scott is fairly simple: Hey, guy, anybody who chases a gorilla to get a banana deserves whatever he gets. I get my bananas from the produce department at Safeway. Gorillas are not involved in the transaction.

And that's a point that I'm not sure has been made as clearly as it should: OOP is a tool that can be brought to bear on different problems, not all of them requiring a massive hierarchy and pervasive polymorphism. OOP can be used to enforce modularity on small structures, such as the "when" stamp I discussed in last month's column. The when stamp is a banana; it stands pretty much alone and can be used and reused as a modular unit.

I suspect the smart path is to build large object hierarchies only when the hierarchy as a whole is the mechanism you're after. In other words, don't glue together diverse and unrelated items into a single hierarchy just because it seems the politically correct thing to do. I have seen an unannounced product that is, essentially, the infrastructure of an event-driven application, rolled up into a single large and brilliantly conceived object hierarchy. It incorporates text windowing, mouse and keyboard input, dialog boxes, various types of buttons and controls, an event processing loop, and so on -- everything but the parts of the app that do the specific work the application was designed to do. Trying to find and extract a "window" object in the hierarchy for reuse is nonsensical -- the window-ness of the objects in the hierarchy is distributed in a highly stochastic fashion across the hierarchy. If you want the infrastructure, you take it all or leave it on the shelf.

After all, trying to extract the liver from a gorilla will at best leave you with something not especially useful -- and it annoys the hell out of the gorilla.

Object Professional Arrives!

By the time you read this, Turbo Power Software's massive Object Professional library will be on the streets. I've been watching the product grow for some time, and I have beside me a galley proof of the documentation. It's quite a product, and I'll be having more to say about it in the future.

OPRO, as the folks at Turbo Power have begun to call it informally, is an evolutionary step up from Turbo Professional 5.0. It's a massive collection of about 130 object types in 50 units, with 1600 pages (!) of documentation -- something that may set a new record for a toolbox product, and one likely to stand for a good long while.

OPRO follows the "banana model" of object libraries. It's a truck load of relatively small hierarchies, most of which are independent of one another. The largest aggregate of functions supports a slick text windowing system (OPRO does not involve graphics) with overlapping windows, shadows, scroll bars, pick lists, menus, and context-sensitive help windows.

I could spend a whole column just describing what's in OPRO, but space is short. Here are the highlights:

That's not all, either, but I've not had the time to go over more than a fraction of it so far. Most remarkable of all, every last bit of source code is included, right down to the .ASM files. Just reading the code is a helluvan education in creating efficient objects in Turbo Pascal.

OPRO was not an easy product to write, even for Kim Kokkonen and his crew of wizards down on Scotts Valley Drive. (I could hear the groans drowning out the sawmill regularly when I had the window open in the fall.) This is why I recommend that when an application has to happen in the least amount of time, glom onto a major toolkit product and write your application around it. The toolkit may not have every corner of every window done just the way you want it. There are, for example, operational details about Object Professional's windowing system that I don't care for, but these are speckles on the axe. Keep reminding yourself: You're working on the edge, not the shine.

If you can buy the shine somewhere, do it. And don't assume that you can necessarily do a better job in less than a geological eon of pressing the axe against the stone.

Products Mentioned

Big Blue Disk SoftDisk Publishing P.O. Box 30008 Shreveport, LA 71130-0008 $9.95 per issue

Get-TUG-Gether June 29 -- July 1 in Silverdale, Washington Conference fee $95 Turbo User Group P.O. Box 1510 Poulsbo, WA 98370 206-779-9508

Object Professional 1.0 Turbo Power Software P.O. Box 66747 Scotts Valley, CA 95066 408-438-8608 $150 (includes full source code)

Market Notes

As most of you who have ever considered marketing your software professionally are aware, it's virtually impossible to get a product on computer store shelves without a tremendous budget for promotion and more than a little luck. So I watch for ways that a small time operator can make some money with their software, and another good one has turned up recently.

Bob Napp, managing editor of SoftDisk Publishing, is looking for good software to publish in their monthly disk-based magazine Big Blue Disk. Billed as "The Monthly Software Collection," Big Blue Disk is an amiable hodgepodge of DOS software, running from batch language extension utilities to D&D-style games. A recent issue that I examined contained a typing tutor, a dungeon game, a video board detection utility for batch files, an appointment calendar manager, a simple word processor, and a collection of clip art for the Print Shop desktop publishing program, plus a letters column and a few other odds and ends. From the consumer's standpoint it was well worth the $9.95 cover price, and their rates for authors, while not the stuff of which empires are made, certainly seem worth it to me for modest software projects.

Contact Bob at SoftDisk Publishing and get their author kit.

Apologies

...to the C people who have had enough of my C bashing. Truce, truce. After all (and yes, I have violated the spirit of this contention from time to time) a language is a socket wrench, not a religion or a household pet.

And the truce will hold as long as you C guys stop asking me when I'm going to give up my training wheels.

Deal?

Contact Jeff Duntemann on MCI Mail as JDuntemann, or on CompuServe as 76117,1426.