Architecting enduring solutions
The word architecture is used by a variety of disciplines to describe both a set of artifacts (representations of the architecture) and the actions and methods which produce these artifacts initially, and evolve and apply them over time. As artifacts, architectures are used to describe the structure of a system over time, and how this structure creates or enhances desired properties of the system. As a body of practices, architecture serves to incorporate learning about product structures that is acquired through experience developing and operating similar systems on past projects. This learning is then structured so that it can be applied as similar problems arise in design and construction on current and future ones.
In the book Beautiful Architecture, Grady Booch describes the multi-disciplinary threads which weave through all architectures as follows:
For this balance to be achieved, key stakeholders must actively participate in architecture development and construction, and agree with how the architecture will be used throughout the system's lifecycle. They must be committed to their deliverables, roles and responsibilities, as they unfold manifestations of the system through blood, sweat, and tears. Thus, an architect cannot operate in isolation, but must ensure that the evolving architecture is consistently understood by the system's key stakeholders, as they elaborate design and construction steps which will fully implement this architecture over time. The architecture's elements cannot be represented merely through a static document or drawing. To be useful, the resulting architectural design decisions must be communicated in ways that can be reviewed, discussed, modified, and approved by the stakeholders who are to implement them. Architects must continue to play an active role in shaping follow-on activities, and the architectural artifacts must be supported and maintained with time.
Architectural activities should focus and exploit direct lines of communication between these stakeholders, so that only the factors that are absolutely required by key stakeholders are addressed by the architecture. Heavy architectures are a drain for all to implement, while lightweight architectures may not get you through turbulent times. The point of view that designers have can impact these decisions; As Fred Brooks reminds us,
A key tool for this communications is the use of abstractions and notations that form design representations for the system, and provide views into aspects of the system. Gero describes the key aspects of these representations:
Design requires a representation framework which has sufficient expressive power to capture the nature of the concepts which
support design processes. The use of a knowledge representation schema such as design prototypes allows for this. It separates
the knowledge from the computational processes which operate on it. The use of this representation effectively provides a
translator between structure, which may be seen as the syntax of a design, and function, which may be treated as the semantics of a design. Such an articulation is useful not only in the production of designs but also in their analysis and evaluation.
These views deliberately focus attention on selected details of the system, while omitting other concerns. These different viewpoints are used to prioritize, communicate, and focus on key and unique perspectives. For this communications to illuminate rather than obscure these, these views must themselves remain consistent with each other and compatible with the system's Concepts of Operation.
Architectural development processes must therefore establish a set of patterns which will achieve this communications and cohesion across the team's parallel design efforts over time. The methods should also provide techniques for reducing complexity that would otherwise accumulate with time, and enable pursuit of the most important design elements. Further, these rules must provide criteria and approaches which assure that verification will be performed on candidate builds as they are developed against the architectural structures, behaviors and characteristics that are desired. Often, this involves striking the right tension between elements which are scarce, and exploiting those in abundance.
Design is an iterative process whose predictability is dependent upon foundational precedents. In Casting Software Design in the Function-Behavior-Structure Framework, Philippe Kruchten draws on earlier work by John Gero about how the design process evolves in other disciplines, a cycle that is depicted in the diagram on the right.
Architectural views always live within the framework of a top-down perspective of the system, as an integrated whole. While development typically occurs bottom-up, at the subsystem and component level, integration is best planned from this top-down perspective. As such, architectures shape the elaboration and delivery of functionality so that the desired architectural properties will emerge at the system level, even though these may not be uniquely traceable to any one component These 'emergent' properties include system attributes such as:
Affordability- so the system can be completed and sustained over time
Availability - the robustness and resilience of a system under load
Value - so the system satisfies the needs of its stakeholders
Changeability - so selected aspects of the system can be easily changed in the future, and other elements that are less likely to be changed have less provision for change
Performance- so the throughput of the system can be produced
Capacity- so the level of utilization that is expected of the system can be achieved over time
Interoperability- so interactions expected with other systems can be realized
Modularity- to organize development into independent work assignments and promote integration with minimal rework
Conformability- how the as-designed system will be built as a set of components which will be independently designed, verified, and replicated. How the interfaces to components are specified so they can be reused or acquired from others
Evolutionary growth- how a particular version of a system is related to others in a product family, sharing components and features, with the objective of ensuring that derivative works can be produced as efficiently as possible
Security- how authorization will be performed for system use and data access, ensuring that attacks will be withstood and detected
These properties are not the result of any one component in the system, but are systemic, and emerge from their interactions and collective essence. The architectural process seeks to achieve balance across such properties, by discovering the most important concerns of stakeholders, and the conditions which will satisfy those concerns in a way that maximizes stakeholder collective value. These concerns and the design approach to address them must be written down, so that they are more than malleable concepts in someone's head, but are instead vehicles to communicate tradeoffs and facilitate decision-making in both the short and long term. In the short term, these guide and shape tiered implementation. In the long term, they provide a foundation for system troubleshooting and problem isolation.
Assessing such architectural characteristics before the underlying components are fully realized requries effective architectural reviews to be performed by review teams. These reviews serve the same purpose as brown M&Ms to Van Halen: they provide a means to signal the effectiveness that artifacts will have in satisfying intended properties. As a result, these artifacts need to communicate effectively at multiple levels. This usually requires the artifacts to adopt a set of constructs that weave together many different types of relationships that will be manifest over time and under various pressures and conditions, especially as the system evolves. Here are some examples of the kinds of decisions, structures, and relationships that are useful to explore component and subsystem partitioning in software-intensive systems:
|
Structural Objective |
Example Design Concerns |
Types of relationships |
Representative Implementation Mechanisms |
|
Information Hiding |
Changeability Modularity |
Is a part of Is contained in |
Units Modules Components |
|
Evolutionary growth |
Buildability Adaptability |
Uses |
Inheritance |
|
Concurrency |
Availability Performance Capacity |
Gives work to Gets resources from Shares resources with Contained in |
Processes |
|
System robustness |
Availability Security |
Has access to |
Firewalls Access control directories Load Balancers Network enclaves Protected address spaces |
Booch emphasizes that making tradeoffs across such relationships is a critical aspect of architectural work:
Before an architecture can be used, it's feasibility must be demonstrated. We would look for architectures with a well-defined Uses Structure that would support incremental construction, so that at each iteration of construction we would have a useful, testable system. We would also look for architectures that have well-defined module interfaces and that are inherently testable, so that the construction progress is transparent and visible.
Next, we want architectures that demonstrate Persistence—that is, architectures that have stood the test of time. We work in an era when the technical environment is changing at an ever-increasing rate. A beautiful architecture should anticipate the need for change, and allow expected changes to be made easily and efficiently. We want to find architectures that have avoided the "aging horizon" (Klein 2005) beyond which maintenance becomes prohibitively expensive.
No discussion of architecture is complete without considering two key attributes: cohesion and coupling. Cohesion is the glue that holds a set of components together, and is closely related to coherence of the system overall. Related functionality should operate as if it was cut from one cloth, and designed and built to provide users with an intuitive and consistent experience. Each component should play a clearly defined role with well-defined interfaces, rather than providing a grab bag of loosely related functionality. If components are not cohesive, elaboration of a system's functionality into its constituent elements is much more likely to be incomplete and inconsistent.
Coupling is a measure of the interdependency between components, and can be thought of as the amount of wiring to and from them. In the simplest designs, components have little coupling and are thus not overly reliant on each another. In most systems, however, components interconnect in many complex ways, both directly and indirectly through intermediaries. Such coupling can occur through control mechanisms, data sharing, or aspects of the environment that can affect multiple elements. The management of such interactions are often key factors in determining how well the system-level architectural attributes described above are realized over time, and how easy it will be for the system to adapt to emerging situations.
Architecture is thus as much art as science; there is no standard recipe to follow if you are the individual responsible for crafting and shaping architectures. This is why most writings about architecture emphasize what an architecture is and how it can be represented, rather than how to produce one. As a result, the best way to become a good architect is through a prolonged period of mentoring from other successful architects, active involvement in development efforts from a frame of reference that allows you to observe and evaluate which aspects of different approaches most effectively contribute to achieving desired emergent properties, and by studying successful works of architecture and patterns used by other architects. The below references provide a good start on that journey.
- Bryan Pflug's blog
- Login or register to post comments
