Design is needed at several different levels of detail in a software system. Some
307
design techniques apply at all levels, and some apply at only one or two. Figure
308
5-2 illustrates the levels.
309
CROSS-REFERENCE For
more on working with old systems, see Section 24.6, “Refactoring Strategies.”
CROSS-REFERENCE An
especially valuable kind of standardization is the use of design patterns, which are discussed in “Look for Common Design Patterns” in Section 5.3.
Internal routine design Division into classes within packages Division into subsystems/packages
Division into data and routines within classes
Software system 1 2 3 4 5 310
F05xx02
311 Figure 5-2 312The levels of design in a program. The system (1) is first organized into subsystems 313
(2). The subsystems are further divided into classes (3), and the classes are divided 314
into routines and data (4). The inside of each routine is also designed (5). 315
Level 1: Software System
316The first level is the entire system. Some programmers jump right from the
317
system level into designing classes, but it’s usually beneficial to think through
318
higher level combinations of classes, such as subsystems or packages.
319
Level 2: Division into Subsystems or Packages
320The main product of design at this level is the identification of all major
321
subsystems. The subsystems can be big—database, user interface, business logic,
322
command interpreter, report engine, and so on. The major design activity at this
323
level is deciding how to partition the program into major subsystems and
324
defining how each subsystem is allowed to use each other subsystems. Division
325
at this level is typically needed on any project that takes longer than a few
weeks. Within each subsystem, different methods of design might be used—
327
choosing the approach that best fits each part of the system. In Figure 5-2, design
328
at this level is shown in (2).
329
Of particular importance at this level are the rules about how the various
330
subsystems can communicate. If all subsystems can communicate with all other
331
subsystems, you lose the benefit of separating them at all. Make the subsystem
332
meaningful by restricting communications.
333
Suppose for example that you define a system with six subsystems, like this:
334
Error! Objects cannot be created from editing field codes.
335F05xx03
336Figure 5-3
337
An example of a system with six subsystems. 338
When there are no rules, the second law of thermodynamics will come into play
339
and the entropy of the system will increase. One way in which entropy increases
340
is that, without any restrictions on communications among subsystems,
341
communication will occur in an unrestricted way, like this:
342
Error! Objects cannot be created from editing field codes.
343F05xx04
344Figure 5-4
345
An example of what happens with no restrictions on inter-subsystem 346
communications. 347
As you can see, every subsystem ends up communicating directly with every
348
other subsystem, which raises some important questions:
349
● How many different parts of the system does a developer need to understand
350
at least a little bit to change something in the graphics subsystem?
351
● What happens when you try to use the financial analytics in another system?
352
● What happens when you want to put a new user interface on the system,
353
perhaps a command-line UI for test purposes?
354
● What happens when you want to put data storage on a remote machine?
355
You might think of the lines between subsystems as being hoses with water
356
running through them. If you want to reach in and pull out a subsystem, that
357
subsystem is going to have some hoses attached to it. The more hoses you have
358
to disconnect and reconnect, the more wet you’re going to get. You want to
359
architect your system so that if you pull out a subsystem to use elsewhere you
360
won’t have very many hoses to reconnect and those hoses will reconnect easily.
With forethought, all of these issues can be addressed with little extra work.
362
Allow communication between subsystems only on a “need to know” basis—and
363
it had better be a good reason. If in doubt, it’s easier to restrict communication 364
early and relax it later than it is to relax it early and then try to tighten it up later
365
after you’ve coded several hundred inter-subsystem calls.
366
Figure 5-5 shows how a few communication guidelines could change the system
367
depicted in Figure 5-4:
368
Error! Objects cannot be created from editing field codes.
369F05xx05
370Figure 5-5
371
With a few communication rules, you can simplify subsystem interactions 372
significantly. 373
To keep the connections easy to understand and maintain, err on the side of
374
simple inter-subsystem relations. The simplest relationship is to have one
375
subsystem call routines in another. A more involved relationship is to have one
376
subsystem contain classes from another. The most involved relationship is to
377
have classes in one subsystem inherit from classes in another.
378
A good general rule is that a system-level diagram like Figure 5-5 should be an
379
acyclic graph. In other words, a program shouldn’t contain any circular
380
relationships in which Class A uses Class B, Class B uses Class C, and Class C
381
uses Class A.
382
On large programs and families of programs, design at the subsystem level
383
makes a difference. If you believe that your program is small enough to skip
384
subsystem-level design, at least make the decision to skip that level of design a
385
conscious one.
386