Chapter 6. Object-Oriented Programming

Windows and web programs are enormously complex programs that present information to users in graphically rich ways, offering complicated user interfaces, complete with drop-down and pop-up menus, buttons, listboxes, and so forth. Behind these interfaces, programs model complex business relationships, such as those among customers, products, orders, and inventory. Users can interact with such a program in hundreds, if not thousands, of different ways, and the program must respond appropriately every time.

To manage this complexity, programmers have developed a technique called object-oriented programming. It is based on a very simple premise: you manage complexity by modeling its essential aspects. The closer your program models the problem you are trying to solve, the easier it is to understand (and thus to write and to maintain) that program.

Programmers refer to the problem you are trying to solve and all the information you know that relates to your problem as the problem domain. For example, if you are writing a program to manage the inventory and sales of a company, the problem domain would include everything you know about how the company acquires and manages inventory, makes sales, handles the income from sales, tracks sales figures, and so forth. The sales manager and the stock room manager would be problem-domain experts who can help you understand the situation better.

A well-designed object-oriented program is filled with objects (things) from the problem domain. For example, if the problem domain is an ATM for banking, the things (objects) in your domain might include customers, accounts, monthly statements, and so forth.

At the first level of design, you'll think about how these objects interact and what their state, capabilities, and responsibilities are:

State

A programmer refers to the current conditions and values of an object as that object's state. For example, you might have an object representing a customer. The customer's state includes the customer's address, phone number, and email, as well as the customer's credit rating, recent purchase history, and so forth. A different customer would have different state.

Capabilities

The customer has many capabilities, but a developer cares about modeling only those that are relevant to the problem domain. Thus, a customer object might be able to make a deposit, transfer funds, withdraw cash, and so forth.

Responsibilities

Along with capabilities come responsibilities. The customer object is responsible for managing its own address. In a well-designed program, no other object needs to know the details of the customer's address. The address might be stored as data within the customer object, or it might be stored in a database, but it is up to the customer object to know how to retrieve and update her own address. (The monthly-statement object should not know the customer's address, though it might ask the customer object for the customer address. This way, when the customer moves, the responsibility for knowing the new address is located in a single object: the customer.) This ability for an object to own responsibility for its own internal state and actions is known as encapsulation.

Of course, all of the objects in your program are just metaphors for the objects in your problem domain.

Humans are model-builders. We create models of the world to manage complexity and to help us understand problems we're trying to solve. You see models all the time. Street maps are models of roadways. Globes are models of the Earth. Atomic models are models of the interaction of subatomic particles.

Models are simplifications. There is little point to a model that is as complex as the object in the problem domain. If you had a map of the United States that had every rock, blade of grass, and bit of dirt in the entire country, the map would have to be as big as the country itself. Your road atlas of the United States eschews all sorts of irrelevant detail, focusing only on those aspects of the problem domain (such as the country's roads) that are important to solving the problem (getting from place to place). If you want to drive from Boston to New York City, you don't care where the trees are; you care where the exits and interchanges are located. Therefore, the network of roads is what appears in the atlas.

Albert Einstein once said: "Things should be made as simple as possible, but not any simpler." A model must be faithful to those aspects of the problem domain that are relevant. For example, a road map must provide accurate relative distances. The distance from Boston to New York must be proportional to the actual driving distance. If 1 inch represents 25 miles at the start of the trip, it must represent 25 miles throughout the trip, or the map will be unusable. (Although not every map has to include a strict scale, depending on what you're using it for, but a road map needs to.)

A good object-oriented design is an accurate model of the problem you are trying to solve. Your design choices influence not only how you solve the problem, but also how you think about the problem. A good design, like a good model, allows you to examine the relevant details of the problem without confusion or distraction.