Moving from the Analysis to the Design level of the architecture entails determination of the hardware and software
component design. This Design-level specification consists of the components to be deployed: hardware, software, and
Hardware components are determined by analyzing the localities, their derived characteristics, and hosted subsystem
operations. With this information, Descriptor-level realizations of the localities can be selected. Descriptor node
diagrams specify the components, servers, workstations, workers, and so forth, without specific choices of technologies
that implement those components. The figure is an example Descriptor node diagram that realizes the Locality diagram
shown in Concept: Locality. The fulfillment Locality is realized as four components: a
warehouse gateway and mailing/postage system, and two workers.
The Descriptor nodes inherit characteristics from their localities through an allocation or budgeting process.
The implementation hardware components, the actual deployed set of hardware, are determined by making
cost/performance/capacity trades from the Descriptor view. In fact, a system might have more than one hardware
configuration, each meeting different price/performance points.
Components are determined by specifying a set of classes, and then compiling and assembling the code associated with
those classes into executable files. A fully considered software component design must reflect a variety of
Locality—where the components need to run
Hosting—processor instruction set and memory restrictions for the executing code
Concurrency—separation of processing into different hosts or memory spaces to address reliability and related
It follows that the information needed to specify components includes the surveys of hosted subsystem operations for
localities and their realized hardware components, surveys of executed operations for processes, along with
collaborations, realizing the subsystem operations, which yield the set of classes to be formed into a component
As a first approximation, assume all classes reside in a single component, giving a one-to-one mapping of component and
subsystem—this is the default advice given in Guideline: Design Subsystem. Next, look for reasons to partition the component further. If the set of classes contains more
than one active class, representing a process, then examine a partitioning of one active class (process) per component,
clustering those classes with the strongest relationships. Some classes can then be used by multiple components. If any
of these classes represent shared state in a common set of instances that are to be accessed by several components,
then there is a case to split them off into another component of their own. If the shared classes are stateless, you
might choose to separate them out into a service component (a stateless functional component), if they are functionally
cohesive. Even in a passive subsystem (no active classes), you can still choose to partition further, for example,
looking for finer-grained components that are reusable. Complete the process by repartitioning/dividing the components
further to account for specific technology choices (such as the J2EE™ platform, or Microsoft® .NET), memory constraints
(such as .exe and .dll trade-offs), shipping media limitations, and so forth.
These tasks result in a set of specific hardware and software components that make up the system.