7.4 Modularity
A key point in Section 7.2 is that to modify software one must understand the program or at least the pertinent parts of the program. Gaining such an understanding is often difficult enough in the case of small programs and would be close to impossible when dealing with large software systems if it were not for modularity— that is, the division of software into manageable units, generically called modules, each of which deals with only a part of the software’s overall responsibility.
Modular Implementation Modules come in a variety of forms. We have already seen (Chapters 5 and 6), that in the context of the imperative paradigm, modules appear as procedures. In contrast, the object-oriented paradigm uses objects as the basic modular constituents. These distinctions are important because they determine the underlying goal during the initial software design process. Is the goal to represent the overall task as individual, manageable processes or to identify the objects in the system and understand how they interact?
To illustrate, let us consider how the process of developing a simple modular program to simulate a tennis game might progress in the imperative and the object-oriented paradigms. In the imperative paradigm we begin by considering the actions that must take place. Because each volley begins with a player serving the ball, we might start by considering a procedure named Serve that (based on the player’s characteristics and perhaps a bit of probability) would compute the initial speed and direction of the ball. Next we would need to determine the path of the ball. (Will it hit the net? Where will it bounce?) We might plan on placing these computations in another procedure named Computer Path. The next step might be to determine if the other player is able to return the ball, and if so we must compute the ball’s new speed and direction. We might plan on placing these computations in a procedure named Return.
Continuing in this fashion, we might arrive at the modular structure depicted by the structure chart shown in Figure 7.3, in which procedures are represented by rectangles and procedure dependencies (implemented by procedure calls) are represented by arrows. In particular, the chart indicates that the entire game is overseen by a procedure named Control Game, and to perform its task, Control Game calls on the services of the procedures Serve, Return, Computer Path, and Update Score.
Note that the structure chart does not indicate how each procedure is to perform its task. Rather, it merely identifies the procedures and indicates the dependencies among the procedures. In reality, the procedure Control Game might perform its task by first calling the Serve procedure, then repeatedly calling on the procedures Computer Path and Return until one reports a miss, and finally calling on the services of Update Score before repeating the whole process by again calling on Serve. At this stage we have obtained only a very simplistic outline of the desired program, but our point has already been made. In accordance with the imperative paradigm, we have been designing the program by considering the activities that must be performed and are therefore obtaining a design in which the modules are procedures.
Let us now reconsider the program’s design—this time in the context of the object-oriented paradigm. Our first thought might be that there are two players that we should represent by two objects: Player A and Player B. These objects will have the same functionality but different characteristics. (Both should be able to serve and return volleys but may do so with different skill and strength.) Thus ,these objects will be instances of the same class. (Recall that in Chapter 6 we introduced the concept of a class: a template that defines the procedures (called methods) and attributes (called instance variables) that are to be associated with each object.) This class, which we will call Player Class, will contain the methods, serve and return, that simulate the corresponding actions of the player. It will also contain attributes (such as skill and endurance) whose values reflect the player’s characteristics Our design so far is represented by the diagram in Figure 7.4. There we see that Player A and Player B are instances of the class Player Class and that this class contains the attributes skill and endurance as well as the methods serve and return Volley. (Note that in Figure 7.4 we have underlined the names of objects to distinguish them from names of classes.)
Next we need an object to play the role of the official who determines whether the actions performed by the players are legal. For example, did the serve clear the net and land in the appropriate area of the court? For this purpose we might establish an object called Judge that contains the methods evaluate Serve and evaluate Return. If the Judge object determines a serve or return to be acceptable, play continues. Otherwise, the Judge sends a message to another object named Score to record the results accordingly.
At this point the design for our tennis program consists of four objects: Player A, Player B, Judge, and Score. To clarify our design, consider the sequences of events that may occur during a volley as depicted in Figure 7.5 where we have represented the objects involved as rectangles. The figure is intended to present the communication between these objects as the result of calling the serve method within the object Player A. Events appear chronologically as we move down the figure. As depicted by the first horizontal arrow, Player A reports its serve to the object Judge by calling the method evaluate Serve. The Judge then determines that the serve is good and asks Player B to return it by calling Player B’s return Volley method. The volley terminates when the Judge determines that Player A erred and asks the object Score to record the results.
As in the case of our imperative example, our object-oriented program is very simplistic at this stage. However, we have progressed enough to see how the object-oriented paradigm leads to a modular design in which fundamental components are objects.