Levels of Design

Level 1: Software System

Some programmers jump right from the system level into designing classes, but it’s usually beneficial to think through higher level combinations of classes, such as subsystems or packages.

Level 2: Division into Subsystems or Packages

The main product of design at this level is the identification of all major subsystems. The subsystems can be big: database, user interface, business rules, command interpreter, report engine, and so on. The major design activity at this level is deciding how to partition the program into major subsystems and defining how each subsystem is allowed to use each other subsystem.

If all subsystems can communicate with all other subsystems, you lose the benefit of separating them at all. Make each subsystem meaningful by restricting communications.

communicating directly with every other subsystem raises some important questions:

You might think of the lines between subsystems as being hoses with water running through them. If you want to reach in and pull out a subsystem, that subsystem is going to have some hoses attached to it. The more hoses you have to disconnect and reconnect, the more wet you’re going to get. You want to architect your system so that if you pull out a subsystem to use elsewhere, you won’t have many hoses to reconnect and those hoses will reconnect easily.

The simplest relationship is to have one subsystem call routines in another. A more involved relationship is to have one subsystem contain classes from another. The most involved relationship is to have classes in one subsystem inherit from classes in another.
a program shouldn’t contain any circular relationships in which Class A uses Class B, Class B uses Class C, and Class C uses Class A.

Business rules

Business rules are the laws, regulations, policies, and procedures that you encode into a computer system.

User interface

Create a subsystem to isolate user-interface components so that the user interface can evolve without damaging the rest of the program.

Database access

You can hide the implementation details of accessing a database so that most of the program doesn’t need to worry about the messy details of manipulating low-level structures and can deal with the data in terms of how it’s used at the business-problem level.
centralize database operations in one place and reduce the chance of errors in working with the data.
It make it easy to change the database design structure without changing most of the program.

System dependencies

Package operating-system dependencies into a subsystem for the same reason you package hardware dependencies. If you’re developing a program for Microsoft Windows, for example, why limit yourself to the Windows environment? Isolate the Windows calls in a Windows-interface subsystem. If you later want to move your program to Mac OS or Linux, all you’ll have to change is the interface subsystem.