Logical versus Physical Design
Almost all principles and patterns that aid in software design and architecture address logical design.4 Logical design pertains to language constructs such as classes, operators, methods, and packages. Identifying the methods of a class, relationships between classes, and a system package structure are all logical design issues.
It’s no surprise that because most principles and patterns emphasize logical design, the majority of developers spend their time dealing with logical design issues. When designing classes and their methods, you are defining the system’s logical design. Deciding whether a class should be a Singleton is a logical design issue. So is determining whether an operation should be abstract or deciding whether you should inherit from a class versus contain it. Developers live in the code and are constantly dealing with logical design issues.
Making good use of object-oriented design principles and patterns is important. Accommodating the complex behaviors required by most business applications is a challenging task, and failing to create a flexible class structure can have a negative impact on future growth and extensibility. But logical design is not the focus of this book. Numerous other books and articles provide the guiding wisdom necessary to create good logical designs. Logical design is just one piece of the software design and architecture challenge. The other piece of the challenge is physical design. If you don’t consider the physical design of your system, then your logical design, no matter how beautiful, may not provide you with the benefits you believe it does. In other words, logical design without physical design may not really matter all that much.
Physical design represents the physical entities of your software system. Determining how a software system is packaged into its deployable units is a physical design issue. Determining which classes belong in which deployable units is also a physical design issue. Managing the relationships between the deployable entities is also a physical design issue. Physical design is equally as, if not more important than, logical design.
For example, defining an interface to decouple clients from all classes implementing the interface is a logical design issue. Decoupling in this fashion certainly allows you to create new implementations of the interface without impacting clients. However, the allocation of the interface and its implementing classes to their physical entities is a physical design issue. If the interface has several different implementations and each of those implementation classes has underlying dependencies, the placement of the interface and implementation has a tremendous impact on the overall quality of the system’s software architecture. Placing the interface and implementation in the same module introduces the risk of undesirable deployment dependencies. If one of the implementations is dependent upon a complex underlying structure, then you’ll be forced to include this dependent structure in all deployments, regardless of which implementation you choose to use. Regardless of the quality of the logical design, the dependencies between the physical entities will inhibit reusability, maintainability, and many other benefits you hope to achieve with your design.
Unfortunately, although many teams spend a good share of time on logical design, few teams devote effort to their physical design. Physical design is about how we partition the software system into a system of modules. Physical design is about software modularity.