Some kinds of subsystems appear time and again in different systems. Here are
388
some of the usual suspects.
389
Business logic
390
Business logic is the laws, regulations, policies, and procedures that you encode
391
into a computer system. If you’re writing a payroll system, you might encode
392
rules from the IRS about the number of allowable withholdings and the
393
estimated tax rate. Additional rules for a payroll system might come from a
394
union contract specifying overtime rates, vacation and holiday pay, and so on. If
395
you’re writing a program to quote auto insurance rates, rules might come from
396
state regulations on required liability coverages, actuarial rate tables, or
397
underwriting restrictions.
User interface
399
Create a subsystem to isolate user-interface components so that the user interface
400
can evolve without damaging the rest of the program. In most cases, a user-
401
interface subsystem uses several subordinate subsystems or classes for GUI
402
interface, command line interface, menu operations, window management, help
403
system, and so forth.
404
Database access
405
You can hide the implementation details of accessing a database so that most of
406
the program doesn’t need to worry about the messy details of manipulating low-
407
level structures and can deal with the data in terms of how it’s used at the
408
business-problem level. Subsystems that hide implementation details provide a
409
valuable level of abstraction that reduces a program’s complexity. They
410
centralize database operations in one place and reduce the chance of errors in
411
working with the data. They make it easy to change the database design structure
412
without changing most of the program.
413
System dependencies
414
Package operating-system dependencies into a subsystem for the same reason
415
you package hardware dependencies. If you’re developing a program for
416
Microsoft Windows, for example, why limit yourself to the Windows
417
environment? Isolate the Windows calls in a Windows-interface subsystem. If
418
you later want to move your program to a Macintosh or Linux, all you’ll have to
419
change is the interface subsystem. This functionality can be too extensive to
420
implement the details on your own, but it’s readily available in any of several
421
commercial code libraries.
422
Level 3: Division into Classes
423Design at this level includes identifying all classes in the system. For example, a
424
database-interface subsystem might be further partitioned into data access classes
425
and persistence framework classes as well as database meta data. Figure 5-2,
426
Level 3, shows how one of Level 2’s subsystems might be divided into classes,
427
and it implies that the other three subsystems shown at Level 2 are also
428
decomposed into classes.
429
Details of the ways in which each class interacts with the rest of the system are
430
also specified as the classes are specified. In particular, the class’s interface is
431
defined. Overall, the major design activity at this level is making sure that all the
432
subsystems have been decomposed to a level of detail fine enough that you can
433
implement their parts as individual classes.
434
The division of subsystems into classes is typically needed on any project that
435
takes longer than a few days. If the project is large, the division is clearly distinct
436
from the program partitioning of Level 2. If the project is very small, you might
437
FURTHER READING For a
good discussion of database
design, see Agile Database
move directly from the whole-system view of Level 1 to the classes view of 438 Level 3. 439
Classes vs. Objects
440A key concept in object-oriented design is the differentiation between objects
441
and classes. An object is any specific entity that exists in your program at run
442
time. A class is any abstract entity represented by the program. A class is the
443
static thing you look at in the program listing. An object is the dynamic thing
444
with specific values and attributes you see when you run the program. For
445
example, you could declare a class Person that had attributes of name, age, 446
gender, and so on. At run time you would have the objects nancy, hank, diane, 447
tony, and so on—that is, specific instances of the class. If you’re familiar with 448
database terms, it’s the same as the distinction between “schema” and “instance.”
449
This book uses the terms informally and generally refers to classes and objects
450
more or less interchangeably.
451
Level 4: Division into Routines
452Design at this level includes dividing each class into routines. The class interface
453
defined at Level 3 will define some of the routines. Design at Level 4 will detail
454
the class’s private routines. When you examine the details of the routines inside
455
a class, you can see that many routines are simple boxes, but a few are composed
456
of hierarchically organized routines, which require still more design.
457
The act of fully defining the class’s routines often results in a better
458
understanding of the class’s interface, and that causes corresponding changes to
459
the interface, that is, changes back at Level 3.
460
This level of decomposition and design is often left up to the individual
461
programmer, and it is needed on any project that takes more than a few hours. It
462
doesn’t need to be done formally, but it at least needs to be done mentally.
463
Level 5: Internal Routine Design
464Design at the routine level consists of laying out the detailed functionality of the
465
individual routines. Internal routine design is typically left to the individual
466
programmer working on an individual routine. The design consists of activities
467
such as writing pseudocode, looking up algorithms in reference books, deciding
468
how to organize the paragraphs of code in a routine, and writing programming-
469
language code. This level of design is always done, though sometimes it’s done
470
unconsciously and poorly rather than consciously and well. The diagram in
471
Figure 5-2 indicates the level at which this occurs in the routine marked with a 5. 472
CROSS-REFERENCE For
details on characteristics of high-quality classes, see Chapter 6, “Working Classes.”
CROSS-REFERENCE For
details on creating high- quality routines, see Chapter 7, “High-Quality Routines.”
In other words—and this is the rock-solid principle on which the whole of the Corporation’s
Galaxywide success is founded—their
fundamental design flaws are completely hidden by their superficial design flaws.
5.3 Design Building Blocks: Heuristics
473
Software developers tend to like our answers cut and dried: “Do A, B, and C,
474
and X, Y, Z will follow every time.” We take pride in learning arcane sets of
475
steps that produce desired effects, and we become annoyed when instructions
476
don’t work as advertised. This desire for deterministic behavior is highly
477
appropriate to detailed computer programming—where that kind of strict
478
attention to detail makes or breaks a program. But software design is a much
479
different story.
480
Because design is non-deterministic, skillful application of an effective set of
481
heuristics is the core activity in good software design. The following sections
482
describe a number of heuristics—ways to think about a design that sometime
483
produce good design insights. You might think of heuristics as the guides for the
484
trials in “trial and error.” You undoubtedly have run across some of these before.
485
Consequently, the following sections describe each of the heuristics in terms of
486
Software’s Primary Technical Imperative: Managing Complexity.
487