Enabling Techniques for Software Architecture
Enabling Techniques for Software Architecture
This is a summary from the classic [POSA].
Abstraction
Abstraction is one of the fundamental principles humans use to cope with complexity. Grady Booch defines abstraction as: The essential characteristics of an object that distinguish it from all other kinds of objects and thus provide crisply defined conceptual boundaries relative to the perspective of the viewer. Robert C. Martin has a more succinct definition: The amplification of the essential and the elimination of the irrelevant.
Finding the Right Level of Abstraction
This a frequent topic in software design discussions.
Consider the following UML sketch:
In Booch's terms, the "Systems" are "viewer". Read from bottom to top, it is clear that the level of abstraction for the "viewer" is increasing.
- The "Registration System" enrolls a "Student" in courses in a course taught by an "Instructor."
- The "Health Care System" registers a "Person" with a provider.
- The "Billing System" manages financial transactions for the Registration System and the Health Care System and expects payment from a "Party."
The complexity of the "Billing System" would increase if the "Party" abstraction was removed, and would approach unmanageability if the the "Person" abstraction was removed because, in Martin's terms, the irrelevant is not eliminated. On the other hand, if the "Registration System" association was with with "Party", then it's complexity would exceed the unmanageable (downcasting, etc, etc) - because, in Martin's terms, the essential is not amplified.
Encapsulation
Encapsulation deals with grouping the elements of an abstraction that constitute its structure and behavior, and with separating different abstractions from each other. Encapsulation provides explicit barriers between abstractions, fostering non-functional properties like changeability and reusability.
Information Hiding
Information hiding involves concealing the details of a component's implementation from its clients, to better handle system complexity and to minimize the coupling between components. Any details of a component that clients do not need to know in order to use it properly should be hidden by the component.
java.util.Collection java.util.Map java.util.TreeMap
Modularization
Modularization is concerned with the meaningful decomposition of a software system and with its grouping into subsystems and components. The major task is to decide how to physically package the entities that form the logical structure of an application.
Modules serve as physical containers for functionalities or responsibilities of a system. Modularization is closely related to encapsulation.
Layers pattern, MVC, J2EE
Separation of Concerns
Different or unrelated responsibilities should be separated from each other within a software system. Collaborating components that contribute to the solution of a specific task should be separated from components that are involved in the computation of other tasks.
The canonical instance of the pathological violation of this principle: a SQL stored procedure that outputs html.
Coupling and Cohesion
These are principles originally introduced as part of the structured design approach ([DYKSTRA]). Coupling focuses on inter-module aspects, while cohesion emphasizes intra-module characteristics.
Coupling measures of the strength of association between one module and another. Strong coupling complicates a system, since a module is harder to understand, change, or to correct if it is highly interrelated with other modules. Complexity can be reduced by designing systems with weak coupling between modules.
Cohesion measures the degree of connectivity betwenthe functions and elements of a single module. There are several forms of cohesion: [BAL85].
- functional
- logical
- procedural
- communicational
- sequential
- informal
Sufficiency, Completeness and Primitiveness
Grady Booch states [BOOCH94] states that 'Every component of a software system should be sufficient, complete, and primitive.
- Sufficiency
- a component should capture those characteristics of an abstraction that are necessary to permit a meaningful and efficient interaction with that component.
- Completeness
- a component should capture all relevant characteristics of its abstraction.
- Primitiveness
- all operations of a component can be implemented easily without dependencies and/or complexities.
Separation of Policy and Implementation
A component of a software system should deal with policy or implementation, but not both:
- Policy
- A policy component deals with context-sensitive decisions, has knowledge about the semantics and interpretation of information, and the assembly of many disjoint computations into a result or the selection of parameter values. To use another lexicon, a policy component is domain-specific, and can implement the business rules of that domain.
- Implementation
- An implementation component deals with the execution of a fully-specified algorithm in which no context-sensitive (domain-specific) decisions have to be made. The context and interpretation are external.


