Thinking in Objects
I wrote The Object-Oriented Thought Process for anyone who needs to understand the basic object-oriented concepts before jumping into the code. A basic understanding of object-oriented theory is very important because, quite often, programmers do jump right into the code. Most of the software professionals whom I teach have attempted to make the shift from structured to object-oriented without changing the way that they think. This is a mistake.
Object-oriented development is a design technique rather than a coding convention. In developing an OO model, you must focus much more on the design than the code (this is true to a certain degree in structured development as well). To create a solid design, you must first understand the concepts involved in designing the object model.
One of the first thought process skills you must master is how to actually think in terms of objects. This may be easier than you think because in the real world you do think in terms of objects. It is simply a matter of changing your software development paradigm to think in terms of objects rather than thinking of a program as simply code and data. In this installment, we will consider how you start thinking in terms of objects.
How to Think in Terms of Objects
As with most things in life, there is no single right or wrong way to approach a problem. There are usually many different ways to tackle the same problem. So, when attempting to design an OO solution, don't get hung up in trying to do a perfect design the first time. What you really need to do is brainstorm and let your thought process go wild. Do not try to conform to any standards or conventions when trying to solve a problem, because the whole idea is to be creative. Thus, before you start to design a system, or even a class, think the problem through and have some fun! In this article, we explore the fine art and science of OO thinking.
The move from the procedural world to an OO world is not trivial. Changing from FORTRAN to COBOL, or even to C, requires that you learn a new language; however, making the move from COBOL to C++, C# .NET, Visual Basic .NET, or Java requires that you learn a new thought process. This is where the overused phrase OO paradigm rears its ugly head. When moving to an OO language, you must go through the investment of learning OO concepts and the corresponding thought process first. If this paradigm shift does not take place, one of two things will happen: Either the project will not truly be OO in nature (for example, it will use C++ without using OO constructs), or the project will be a complete object-disoriented mess.
Three important things you can do to develop a good sense of the OO thought process are covered in this article:
- Know the difference between the interface and implementation
- Think more abstractly
- Give the user the minimal interface possible
We have already met some of these concepts in Article 1, and here we will now go into much more detail.
Knowing the Difference Between the Interface and the Implementation
As we saw in Article 1, one of the keys to a strong OO design is to understand the difference between the interface and the implementation. Thus, when designing a class, what the user needs to know and what the user does not need to know are of vital importance. The data hiding mechanism inherent with encapsulation is the means by which nonessential data is hidden from the user.
Caution: Do not confuse the concept of the interface with terms like graphical user interface (GUI). Although a GUI is, as its name implies, an interface, the term interfaces, as used here, is more general in nature and is not restricted to a graphical interface.
Remember the toaster example in Article 1? The toaster, or any appliance for that matter, is simply plugged into the interface, which is the electrical outlet—see Figure 1. All appliances have access to electricity by complying with using the correct interface: the electrical outlet. The toaster doesn't need to know anything about the implementation, or how the electricity is produced. For all the toaster cares, a coal plant or a nuclear plant could produce the electricity—the appliance does not care which, as long as the interface works.
Figure 1: Power plant revisited.
As another example, consider an automobile. The interface between you and the car includes components such as the steering wheel, gas pedal, brake, and ignition switch. For most people, aesthetic issues aside, the main concern when driving a car is that the car starts, accelerates, stops, steers, and so on. The implementation, basically the stuff that you don't see, is of little concern to the average driver. In fact, most people would not even be able to identify certain components, such as the catalytic converter and gasket. However, any driver would recognize and know how to use the steering wheel, because this is a common interface. By installing a standard steering wheel in the car, manufacturers are assured that the people in their target market will be able to use the system.
If, however, a manufacturer decided to install a joystick in place of the steering wheel, most drivers would balk at this, and the automobile might not be a big seller (except for some eclectic people who love bucking the trends). On the other hand, as long as the performance and aesthetics didn't change, the average driver would not notice if the manufacturer changed the engine—part of the implementation—of the automobile.
It must be stressed that the interchangeable engines must be identical in every way—as far as the driver's perceptions go. Replacing a four-cylinder engine with an eight-cylinder engine would change the rules, just as changing the current from AC to DC would affect the rules in the power plant example.
The engine is part of the implementation, and the steering wheel is part of the interface. A change in the implementation should have no impact on the driver, whereas a change to the interface might.
What Users See
Interfaces also relate directly to classes. End users do not normally see any classes—they see the GUI or command line. However, programmers would see the class interfaces. Class reuse means that someone has already written a class. Thus, a programmer who uses a class must know how to get the class to work properly. This programmer will combine many classes to create a system. The programmer is the one who needs to understand the interfaces of a class. Therefore, when we talk about users in this article, we primarily mean designers and developers—not necessarily end users. Thus, when we talk about interfaces in this context, we are talking about class interfaces, not GUIs.
Properly constructed classes are designed in two parts—the interface and the implementation.