• No results found

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 312

The 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

316

The 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

320

The 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.

335

F05xx03

336

Figure 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.

343

F05xx04

344

Figure 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.

369

F05xx05

370

Figure 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

Common Subsystems