As a boy I fixed those old tube radios. Take out the tubes, walk to the drug store and put them in the tube tester, and replace the defective ones. If the only problem was a defective tube I was in great shape. But if the problem went deeper, I was in big trouble. Wires everywhere. Everything connected to everything else. No modularity whatsoever. Even a simple 5 tube superhet required superior intelligence to troubleshoot. Complex tube circuit repair was rocket science.
Along came semiconductors and circuit boards. Now the Troubleshooter could easily isolate to the board level. Boards became plug-in, giving rise to board swapping. Now the average person could be trained to be a technician.
A similar evolution took place in software. The goto-ridden spaghetti code that required near-geniuses to code and debug gave way the more modular to structured programming, which was accessible to the slightly smart. The structured programming which tended to get flaky at 20,000 lines of code or so was replaced by the ultra-modular object oriented programming, which could reliably produce huge systems which were easy to test and debug. This issue of Troubleshooting Professional discusses how Object Oriented Programming (OOP for short) has influenced source code Troubleshooting.
So kick back, relax, and read this issue. And remember, if you're a Troubleshooter, this is your magazine. Enjoy!.
Structured programming replaced spaghetti programming in the early 80's, leaving thousands of programmers bitter and jobless. But for a series of failures with a Heathkit ET-6800 Microprocessor Trainer, I might have been one of those bitter and jobless spaghetti programmers.
If you've never seen a Heathkit ET-6800 Microprocessor Trainer, they were 1982's ultimate bare-bones, solder it yourself computer designed to teach you microprocessors. Motorola 6800 processor (you read right, two zeros), machine instructions punched in via a hex keypad. Output viewed via several 7 segment led digits. No disk, no tape.
I wanted mine to play music, so I soldered the hot of an RCA connector to one of the LED's, and plugged it into an amplifier. I began to program my "Computer Guitar".
Every time my program grew to about 50 instructions, my program collapsed under its own weight. No matter how many times I tried, I couldn't get all my features in without having the thing crash.
Desperate, I recalled a conversation where my friend Paul talked of a new technique called "Structured Programming". I looked up structured programming in my microprocessor textbook. A single paragraph told of a process (functional decomposition) to break down the program to a series of tasks and subtasks, and call them as subroutines with returns rather than using goto's. I gave it a try.
Wow! That puppy came right up. 5 real-time keypad notes, slide guitar action, real-time variable tempo, everything. Over a hundred instructions, and no problem coding or debugging it. I became a believer.
That single breakthrough triggered a successful programming career. Other programmers went right to the terminal and typed in their programs. When they painted themselves into a corner, they used goto's to get themselves out. Their programs crashed and burned.
I was different. Knowing first hand the power of structured programming, I took classes and read countless books on the subject. In class I always designed with functional decomposition before coding, and never used a goto. In March of 1984 I got my first programming contract. The years went by and my income rose steadily, as word got out that my programs came in early, under budget, and rock solid. My clients thought I walked on water. I owed it all to my design process. Then the world changed...
Early 1990's, Object Orientated Programming took over. I just didn't get it. Why was it needed? What was so special about it. I wrote C++ with a C accent, and the code was miserable. Clients fed me a steady stream of legacy apps. It was obvious within two years my programming career would end, just like the careers of the spaghetti dinosaurs a decade earlier.
But the Heathkit ET-6800 experience had made me very conscious of design process. I understood the real difference between spaghetti and structured programming was design process, not language. The flowcharts that worked so well with spaghetti Fortran created spaghetti code in supposedly structured C. Could the structured functional decomposition that worked so well in C be the reason I was producing convoluted, non-OOP code in C++. I went out seeking an answer.
I talked to people. I read books. I enrolled in a Visual FoxPro user group and joined a subgroup devoted to learning OOP. One day I was lying down, trying to concentrate on an OOP design book I just couldn't grasp. Sleep overcame me. When I woke up, I understood! Just like that, I knew the process to design OOP apps.
Two weeks later I became the OOP coach of a Powerbuilder team. The ensuing years brought plentiful work in modern languages. My career prospects look brighter than ever thanks to the realization I gained on that 256 byte computer -- It's the design process that counts!
Object Oriented Programming offers our best hope for designing, coding, testing, debugging, maintaining and enhancing large, complex programs. And it's easy -- once you know it. Unfortunately, the vast majority of today's programmers were trained in Structured Programming, not OOP. Often they just don't understand. Let's start our examination of OOP with what it isn't.
There's a rumor going around (probably spread by language vendors and consultants) that if you program in C++, or Java, or Smalltalk, or Delphi or Powerbuilder or FoxPro that you're doing OOP. Nothing could be farther from the truth. You can program all those languages (except maybe Smalltalk) the old way (procedurally, non-OOP).
And you can hack out crud in any language. My first C++ program was a medium sized subsystem in 1990. It used some classes. It even used some right. But the whole design was a hack, and everybody including myself is afraid to touch it today (yes, it's still running). Fortunately, my recent C++ programs are modular, simple, and maintainable by a junior programmer. Same language, different result. You need an OOP enabled language to do OOP, but that's just a small part.
"Just buy our super whiz-bang, drag and drop development environment and trained monkeys can produce wonderful programs with a week's training!" Yeah, sure, and by the way, wanna buy the Brooklyn Bridge? But language vendors (and the consultants and training companies they spawn) keep making these claims, and desperate companies keep buying. Some development environments are a productive tool in the hands of an experienced OOP programmer (and some aren't). Trained monkeys belong in the circus.
Want to build a skyscraper? Just buy our crane!
Sounds silly, doesn't it. Of course you need a crane to build a skyscraper, but you'd better provide a great crane operator. Same with Design Tools (CASE, etc.). They're wonderful, or even necessary, with huge projects. But their use requires personnel to be more skilled, not less.
You want the ultimate in efficiency? Don't use OOP. Those virtual functions and function address lookups will slow you down every time. If you want ultimate efficency, don't even use structured programming (subroutines). For the ultimate machine-efficient code, use assembler with nothing but goto's. Don't clog up the stack with return addresses.
Buried in this fact is the big hint as to what OOP *IS*. If it doesn't help the computer, who does it help? The programmer! At a slight run-time expense to the computer, OOP makes the programmer's job vastly easier.
OOP is a thought pattern. A thought pattern for programmers to make their job much easier. The old-style programmer thinks of his program as instructions or tasks done repeatedly in loops. The OOP programmer thinks of his program as a machine with component parts. To clarify this, here is the way each programmer would describe a car:
|Thought Pattern about a car|
|Structured Programmer||A little gas goes in the engine, then the engine turns a small amount, then the transmission turns a little bit, then the driveshaft turns a little bit, then the differential turns a little bit, then the wheels turn a little bit, then the car moves a little bit. These actions are repeated over and over in a loop until the driver turns off the ignition.|
|Object Oriented Programmer||Gasoline feeds the engine, which turns the transmission, which turns the driveshaft, which turns the differential, which turns the wheels, which move the car. The engine stops when the driver turns off the ignition.|
If the objects are designed right, they have one or a few input requirements (just like in a car the engine needs gas, radiator connection and electricity), and one or a few outputs (just like in a car the engine connects to a transmission to deliver its power). Thus the object can be constructed, operated and tested by itself. Building the application out of independently built and tested objects, you can achieve a much higher level of reliability with less interdependencies in which bugs can hide. Not only does Object Oriented Programming foster Quality by Design, but it also fosters Quality by Inspection (debugging), by making it much easier to disconnect objects to take measurements (in the debugger or with a test object), or to make simulators for the objects.
Once you have the OOP thought pattern, you can use the OOP tools -- the language, the language add-ons, the development environments, and the design tools.
Consciously subdue past habits. Do not think of the program as a series of tasks. Do not subdivide it into subtasks. Think of it as a machine or apparatus. What parts would the machine need in order to represent the real-world problem it's designed to solve. Can you design each part so it depends on no other objects (or very few other objects)? Considering each of these parts a major component (like a car's engine), what common parts would it be made from (in a car like screws, nuts, wires, etc).
Start by analyzing the real-world system you're automating. Make an entity-relationship diagram (dust off that old Systems Analysis textbook). The blocks in that diagram are excellent candidates for objects. Now see if you can change it around so each object has (ideally) one input and one output, and needs knowledge zero, one or at the most two other large objects in the system. If there are groups of similar objects, see if you can create a common ancestor from which to inherit. Finally, code each object. Build a little test jig to test it. When all the objects are coded, put them together, make necessary modifications, and test the app. You'll find the app as a whole to be much more robust than those made with the old structured programming.
OOP is a thought pattern replacing the structured programming thought patterns. Many very fine experienced programmers have trouble "getting it". Some even work in object languages. There are millions of lines of C++ code looking like C. I've been guilty of this myself. Here are some recommendations for learning the thought pattern:
Object Oriented Technology: A Managers Guide by David A. Taylor, Ph.D. ISBN 0-201-56358-4. This short book discusses the concepts without the details, which is just what an experienced programmer new to OOP needs. An additional benefit is language independence -- all explanations are via simple descriptive pictures rather than code. This is a must-read for the experienced programmer going OOP for the first time.
Object Oriented Analysis and Design With Applications by Grady Booch. ISBN 0-8053-5340-2. The opposite of the David A. Taylor book, this goes into the minutest of details discussing OOP, and includes C++ code as well as detailed, intricate pictures. This book presents complete methods including how to make object diagrams, and how to translate them to code. Don't worry if you don't understand everything in this book -- few will. This book is one of the ultimate authorities on Object Orientation.
The Object-Oriented Page is a website with links devoted to Object Orientation. A must-read for continuing OOP education.
Code Corner is a recent addition to Troubleshooters.Com, containing great info on OOP and other programmming issues..
We drown in bugs as software complexity grows geometrically. Already the end-user is expected to troubleshoot the software he buys, or pay an expert to do it. Experts find computer troubleshooting increasingly difficult. How long before the computer industry drowns in their own bugs?
The quality-by-inspection (otherwise known as debugging and troubleshooting) in use the last 45 years no longer works. Developers can no longer sit down at a terminal, hack together a bunch of features and call it an app. One of the best ways to design in quality is to correctly use Object Oriented Programming (OOP). Because OOP lets the programmer design the application as a system of parts with simple interfaces, well designed OOP programs are ultra-modular. The fact that objects can be created and tested alone, without the rest of the program, makes side-effect bugs almost a thing of the past. Because tests are done on objects with simple input requirements and output specifications, automated testing of the objects is easy, further reducing bugs.
Today's software is too complex to assure quality by inspection alone. Quality must be designed in.
The above article notwithstanding, inspection (debugging) is still a necessary part of programming. Yes, I know there are books and software out there promoting "zero defect software", but how many people have actually seen software that was "zero defect". My bet is it's easier to find someone who can levitate. The good news is that well designed OOP programs are an order magnitude easier to debug.
Because the parts are self-contained except for simple, well defined interfaces, they can be disconnected quite easily. Depending on your needs, you can disconnect an object and insert a software probe in its place to measure output of the previous stage, or simulate input to the next stage. The probe, of course, is an object you create whose total purpose is to act as a meter.
A few weeks ago, I debugged a large C++ program that hung the computer, and the debugger didn't help. I solved it in 2 hours by disconnecting objects to narrow it down, finally, to a fwrite() to an unopened file. Remembering the horror of day-long debugging of such problems in the C days, I was thankful to have a clean way to isolate sections of the program.
Wannabe Object Oriented Programming. It's an easy trap to fall into:
At least two C++ implementations ship with application frameworks whose classes map to the operating system rather than common elements of the problem domain (the problem you're trying to solve). Furthermore, their classes are so interlinked that nothing can be tested alone (could that be because the operating system they map to is inherently non-modular?).
Other language implementations are "object based", meaning the programmer can use objects supplied with the language (mainly user interface elements), but can't make his own (like simulations of the problem to be solved or automation to be done). That's just 80's programming in 90's clothes.
Study OOP. Code OOP. Promote OOP. Shun WOOP.
I have extensively used and can personally vouch for the OOP implementation and general quality of the following languages: Sun JDK (Java), Borland's Delphi, Powersoft's Powerbuilder, and Borland Turbo C++ for DOS, and any ANSI implementation of C++.
From research I've done, and some personal use, I also recommend the following: Powersoft Jato (A Java implementation, I think it's now called PowerJ), Powersoft's Optima++ (C++), Symantic Visual Cafe (Java), Microsoft Visual Fox Pro, and Borland's C++ Builder.
We anticipate two to five articles per issue, with issues coming out monthly. We look for articles that pertain to the Troubleshooting Process. This can be done as an essay, with humor, with a case study, or some other literary device. A Troubleshooting poem would be nice. Submissions may mention a specific product, but must be useful without the purchase of that product. Content must greatly overpower advertising. Submissions should be between 250 and 2000 words long.
All submissions become the property of the publisher (Steve Litt), unless other arrangements are previously made in writing. We do not currently pay for articles. Troubleshooters.Com reserves the right to edit any submission for clarity or brevity. Any published article will include a two sentence description of the author, a hypertext link to his or her email, and a phone number if desired. Upon request, we will include a hypertext link, at the end of the magazine issue, to the author's website, providing that website meets the Troubleshooters.Com criteria for links and that the author's website first links to Troubleshooters.Com.
Submissions should be emailed to Steve Litt's email address, with subject line Article Submission. The first paragraph of your message should read as follows (unless other arrangements are previously made in writing):
After that paragraph, write the title, text of the article, and a two sentence description of the author.
http://www.troubleshooters.com is Steve Litt's website.
http://www.troubleshooters.com/codecorn/index.htm is the home of Code Corner.
http://www.arrakis.es/~devis/oo.html contains The Object-Oriented Page.
http://www.engines.com/company/c_founder.html is Dr. David A. Taylor's page.
http://www.rational.com/world/bios/booch_bio.html is Grady Booch's page at Rational Software.
http://java.sun.com: Sun Computers, home of the Java JDK.
http://www.borland.com: Borland International, makers of Delphi, Turbo C++ for DOS, and C++ Builder.
http://www.powersoft.com: Sybase/Powersoft, makers of Powerbuilder, Optima++, Jato/PowerJ.
http://cafe.symantec.com/index.html: Symantic Visual Cafe (Java).
Microsoft Visual Fox Pro Webpage.