Appropriate Enterprise System Architecture

8/9/98 - Jack Harich - Document Map

Architecture is a system's most important partitions and their interactions. Architectural goals assure that subsequent decisions will result in a "good" system. Our most important goal is supporting the Continuous Change Process.


What is the appropriate logical architecture to use in building enterprise systems that support continuous change? We take a multi-pronged approach here by blending several of the better architectural patterns together, as shown in the example below.


Architectural Patterns

We use the following architectural patterns:

Modular - While not a pattern, we first organize our millions of pieces into black box modules. Each module, aka subsystem, is reusability ready-to-go. Some are large, such as an ORB. Some are small, such as a MessageBox. From small modules we assembly larger modules, from which we assemble systems. Such a black box resuable can be called many things, such as module, subsystem, part or component.

Services Pattern - Our most important partition is to split the entire system into Services and everything else, called domain modules. Services are application type independent, and thus can be reused by many domains. This pattern is the backbone of CORBA services. In the diagram we see various domain modules using the services. Services can also use other services.

Layered Architecture Pattern - This tried and true pattern not only reduces coupling but clarifies it to maximize reuse. You first divide a system into "layers". The key rule is a layer cannot use a layer above it, but can use those below. In the diagram we see that all the domain modules use the Bean Assembler module, which is the lowest layer. The Awards module uses the Data Framework module, etc.

Layers are an inverted pyramid when size (number of modules or classes) is considered. The main advantage of layers is a change in one layer tends to not break layers below it, because the lower layers know nothing about the upper layers. Therefore change impact is minimized. Layering also clarifies system design and reuse. Each layer should be carefully abstracted. If a lower layer does need to use an upper layer this should be done with a loose coupling mechanism such as events and interfaces.

Microkernel Pattern - From the book "Pattern-Oriented Software Architecture" by Buschmann et al, we have:

"The Microkernel architectural pattern applies to software systems that must be able to adapt to changing system requirements. It separates a minimal functional core from extended functionality and customer-specific parts. The microkernel also serves as a socket for plugging in these extensions and coordinating their collaboration."

In our system the Bean Assembler is the microkernel. Most systems have no microkernel, because the concept has not been stressed in the past by the literature and is tough to abstract and build. Many designers use lots of libraries, domain specific reusables, or IDE frameworks, and design their systems around these. This is NOT a microkernel but merely lots of reuse. CORBA, COM or EJB are not microkernels. They are distributed frameworks offering mature services, which fit into the Services partition above.


Coupling Rules

This architecture gives us these simple high level coupling rules:

  1. Services are available to any other module.
  2. Modules can use any module in their layer.
  3. Layers can use any lower layer.
  4. A layer cannot use a layer above it, except via an event with the event and listener interface in the lower layer.

A lack of solid architecture results in a lack of good coupling. Poor coupling results in bird's nest systems, where a myriad of dependencies make change more and more difficult as the system grows or ages due to maintenance.

In Java domain modules and services or service groups are packages. Thus one must plan and enforce package coupling carefully. This is why Paul Reavis values his package dependency enforcer, used during system builds.