What is Architecture?
Product architecture was defined by Ulrich and Eppinger in their 1995 book, Product Design and Development, as “the scheme by which the function of a product is allocated to physical components.” This definition draws a distinction between the architecture of a system and its interfaces, which determine how the different components of the system will coordinate their behavior to work together.
Some define product architecture more precisely as the arrangement of functional elements; the mapping from functional elements to physical components; and the specification of the interfaces among interacting physical components. Others have use the metaphor of a skeleton that connects the components of a system and is a crucial part of it.
The structural complexity of an architecture refers to the parts and their connections and any patterns inherent within those connections. The high level structural patterns that are built into a design from its inception have a profound effect on the evolution and lifetime cost of a complex system.
Recently, scholars in the fields of engineering and product design have begun to collapse this distinction by including interface specifications within the definition of architecture. For example, in a definitive white paper, the Engineering Systems Division at MIT defined the architecture of any complex system as “an abstract description of the entities of a system and how they are related.”
Thus the term has come to encompass not only a description of the system’s overall structure and function, but also the constraints that govern the relationships among components and allow them to interoperate.
Patterns and Principles
Certain well-known patterns are employed by man and nature to keep complexity under control even as systems grow. These patterns include hierarchy, modularity, and abstraction layering. Technical architectures in which these patterns are judiciously applied tend to be of higher quality, safer, and benefit from other “ilities” over the course of their life cycles.
In his 2006 book Software Abstractions: Logic, Language and Analysis, Daniel Jackson writes that the creation of conceptual abstractions is central to the design of software:
“Software is built on abstractions. Pick the right ones, and programming will flow naturally from design; modules will have small and simple interfaces; and new functionality will more likely fit in without extensive reorganization. Pick the wrong ones, and programming will be a series of nasty surprises: interfaces will become baroque and clumsy as they are forced to accommodate unanticipated interactions, and even the simplest of changes will be hard to make. No amount of refactoring, bar starting again from scratch, can rescue a system built on flawed concepts. When good abstractions are missing from the design, or erode as the system evolves, the resulting program grows barnacles of complexity. The user is then forced to master a mass of spurious details, to develop workarounds, and to accept frequent, inexplicable failures. The core of software development, therefore, is the design of abstractions. An abstraction … is a structure, pure and simple – an idea reduced to its essential form.”
- High cohesion
- Low coupling
- Private internals
- Defined interfaces
- Small enough components
Modular is a term used to describe architectures composed of distinct modules – semi-autonomous structures with formal boundaries that separate their internal environment from the outside world. Modularity-in-design is one of the things that has caused the computer industry to evolve to its present form.
Modules, in fact, are always distinct parts of a larger system. They are designed and produced independently of one another, but must function together as a whole. Modularity allows tasks—both design tasks and production tasks—to be divided among groups, which can work independently and do not have to be part of the same firm. Compatibility among modules is ensured by “design rules” that govern the architecture, the interfaces, and the standardized tests of the system. Thus “modularizing” a system involves specifying its architecture, that is, what its modules are; specifying its interfaces, i.e., how the modules interact; and specifying tests which establish that the modules will work together and how well each module performs its job.
From an engineering perspective, modularity does many things. First, it makes the complexity of the system manageable by providing an effective “division of cognitive labor.” It also makes possible the graceful evolution of knowledge about the system. In this way, modular systems are “cognitively economic.” Second, modularity organizes and enables parallel work. Work on or in modules can go on simultaneously, hence the start-to-finish time needed to complete the job decreases. Thus modular systems are “temporally economic.” Finally, modularity in the design of a complex system allows modules to be changed and improved over time without undercutting the functionality of the system as a whole. In this sense, as we indicated above, the modular design of a complex system is “tolerant of uncertainty” and “welcomes experimentation” in the modules.
In the last decade, the concept of modularity has caught the attention of engineers, management researchers and corporate strategists in a number of industries. When a product or process is “modularized,” the elements of its design are split up and assigned to modules according to a formal architecture or plan.
From an engineering perspective, a modularization generally has three purposes:
- To make complexity manageable;
- To enable parallel work; and
- To accommodate future uncertainty.
Modular systems contain many independent components, each of which can change or evolve separately with minimal impact on each other or on the system as a whole. Modules hide information in the sense that the use of one only requires a client to understand its interface, not its complex internals. Modularity was recognized as a critical means of controlling software complexity as early as the 1960s. As computer science developed, increasingly sophisticated types of modules were invented including an extreme form, known as object-orientation, which combined data-type abstraction and access control. There are multiple types of modularity including slot modularity, bus modularity, and sectional modularity, each with its own relative advantages.
Modularity is similarly important in physical product design. A perfectly modular product is one in which every internal function is performed by a distinct part. Modular products allow each functional element of a product to be changed independently by changing only the corresponding component. Fully integral products require changes to every component to effect change in any single functional element. The architecture of a product is therefore closely linked to the ease with which change to a product can be implemented.
When designers are working inside a modular technical design, they can independently transform modules in six important ways. Modules in a system can be split, substituted, augmented, excluded, inverted, and ported.
Modularity can also be described as being important using economic terms. Harvard researchers Baldwin and Clark demonstrated how the ability to independently modify subcomponents within a modular system accelerates innovation by creating “real options” in the system’s design that behave similarly to options in the world of finance. Essentially, driving modularity into an integral architecture can transform a single large investment into a much more valuable basket of small investments.
In general, modularity is a useful attribute, but not all systems can be modular. Many systems cannot achieve the level of modularity in software and digital systems due to fundamental power constraints or because multiple types of system-spanning relationships (power, informational, electrical, physical, force translation, etc.) each suggest alternative modularizations, none of which are fully satisfactory.
Finally, modularity is not free. Modular designs contain overhead in the form of “design rules” that add cost to the front-end of a design process and potential recurring costs in the form of ongoing performance limitations. This may be a worthwhile investment in software systems with volatile codebases or complicated problem domains. In systems that are less volatile or complicated, the investment in modularity may not pay off.
The widespread adoption of modularity-in-design in complex engineering systems with high technical potential can set in motion an uncontrollable process of design and industry evolution. The economic consequences of this process—for good and bad—are depicted in the charts and turnover rates described at the beginning of this chapter. Thus modularity-in-design can open the door to an exciting, innovative, but very Darwinian world in which no one really knows which firms or business models will ultimately prevail. This can be a world of growth, innovation and opportunity. But, as the Internet Bubble and Crash taught us, this world can also fall into periods of extreme value destruction, chaos and inefficiency.
Complex systems can be constructed in a hierarchy of levels in which several components perform particular sub-functions that contribute to the over-all function. Hierarchies are pervasive organizing patterns in many large real-world systems because they endow systems with a variety of useful properties. In The Sciences of the Artificial, Herbert Simon writes, “[h]ierarchy … is one of the central structural schemes that the architect of complexity uses.”
When designing a complex structure, one technique is to decompose it into semi-independent components corresponding to its many functional parts. The design of each component can then be carried out with some degree of independence of the design of others.
In a hierarchy of levels of organization, each level is more complex than the one below. Each level is characterized by having emergent properties. Emergent properties do not exist at lower levels. The operation of the processes at the lower levels of the hierarchy result in a higher level of complexity.
Hierarchies are useful structures for classifying, storing, and searching for information. The requirement that a hierarchy contains no cyclic connections reduces the possibility that feedback loops will be formed between widely separated components. These feedback loops, or cycles, can hindering change or lead to unintended non-linear dynamic behavior.
Hierarchical patterns in systems manage complexity because they have a high degree of redundancy and can often be described in economical terms. Hierarchical organization helps developers by reducing the cognitive burden placed on the human mind when examining a system from any one vantage point. Hierarchies also facilitate top-down control and the imposition of safety constraints.
Layers combine the ideas of hierarchy and modularity in a way that contains complexity and endows a system with a variety of beneficial properties. Layers in systems provide services to components above them while relying on services provided by those below. They combine the notion of directionality found in hierarchies with the notion of information hiding found in modules. Conceptual layers in a design are sometimes called abstractions.
In other contexts, technology layers are called platforms. Platforms form rigid structures in an architecture that create stable interfaces upon which modules can rapidly evolve. Although layers are themselves inflexible, layered structures can make an overall system more flexible.
Layered systems are common in large scale hardware and software systems. For example, a personal computer has a layer for the microprocessor, several layers for the operating system including a user interface layer, possible layers for a database system, and additional layers for application software.
Layering hides information better than modularity does because it partitions a complex network of components into two distinct regions that may be considered independently. In addition to hiding details, abstraction layers may embody new higher-level concepts by aggregating diverse facilities into a useful coherent whole. The creation of new abstraction layers is the primary means by which large-scale reuse is achieved in software.
Platform architectures are modularizations of complex systems in which certain components (the platform itself) remain stable, while others (the complements) are encouraged to vary in cross-section or over time. Among the most stable elements in a platform architecture are the modular interfaces that mediate between the platform and its complements. These interfaces are even more stable than the interior core of the platform, thus control over the interfaces amounts to control over the platform and its evolution.
The fundamental architecture behind all platforms is essentially the same: namely, the system is partitioned into a set of “core” components with low variety and a complementary set of “peripheral” components with high variety. The low-variety components constitute the platform. They are the long-lived elements of the system and thus implicitly or explicitly establish the system’s interfaces, the rules governing interactions among the different parts. Most platform definitions focus on the reuse or sharing of common elements across complex products or systems of production.
Certain components remain fixed over the life of the platform, while others are allowed to vary in cross-section or change over time. Thus either by design or simply because it is the longest-lived component in the system, a platform embodies a set of stable constraints, or design rules, that govern the relationships among components.
In particular, fixing the interfaces between components creates specific thin crossing points in the network of relationships between the elements of the system. At these points, the dependencies between the respective components are constrained to obey the interface specification, while other forms of dependency are ruled out. In contrast, when there is no pre-specified interface governing interactions, designers may introduce any form of dependency that seems beneficial.
Interfaces in turn establish the boundaries of modules. Because they define points of weak linkage (thin crossing points) in a network of relationships, modular interfaces reduce both coordination costs and transaction costs across the module boundary. It follows that the existence of modules and modular interfaces in a large system reduces the costs of splitting design and production across multiple firms.
Platform architectures are united in that they partition a system into low- and high-variety components. The two different types of components can be combined into a working system because pre-specified interfaces regulate both sides. The interfaces must be stable relative to the components that depend on them, hence are, by definition, part of the platform. But the interfaces must also be versatile: they cannot overly constrain the complements or they will reduce the variety and flexibility of the system as a whole.
The Role of the System Architect
Modern systems are so complicated that their designs must be decomposed and distributed. This, and the fact that unexpected behaviors can emerge due to interactions between separately designed components, has led to a new role known as a system architect. The role of this person is to analyze stakeholders, study their needs, and serve as their representative throughout the design process. The architect must devise a concept for a complex system and ensure that when built, it functions appropriately.
In 2004, the Massachusetts Institute of Technology ESD Architecture Committee said that “[m]an-made… systems are intended to have certain primary functions, plus other properties that we call “ilities:” durability, maintainability, flexibility, and so on… The primary functions have immediate value while the ilities tend to have life-cycle value…. Complex systems have behaviors and properties that no subset of their elements have… Some of these are deliberately sought as the product of methodical design activity… While achieving these behaviors, the designers often accept certain undesirable … side effects… In addition, systems have unanticipated behaviors commonly called emergent. Emergent behaviors may turn out to be desirable in retrospect, or they may be undesirable.”
The architect must design a system that can function properly, appropriately control and channel its complexity, and make hard tradeoffs. The architect must identify important system-level properties that must be managed centrally, decompose the design into manageable chunks, create design rules and promote design patterns that allow engineers to manage complexity within and between their subsystem boundaries.
Up-front choices that an architect makes constrain the design space, but also reduce ambiguity and reduce the time that will be required to converge to a workable system if done properly. The role of the architect is to identify inherent tensions in the space of possible designs that will lead to chaos if left unmanaged, manage those choices centrally, and leave teams free to innovate independently within the necessary constraints.
Important design rules may seem sub-optimal at the local level. In such cases, the role of the architect is to represent the global perspective. The architect must also represent the long-term perspective by carefully considering total lifecycle costs because maintenance costs sometimes exceed the cost of development by a ratio of ten to one. The choice of product architecture has broad implications for product performance, product change, product variety, and manufacturability.
Architects decompose a design by allocating similar functionality to modules with high cohesion, creating controlled interfaces isolating a module’s internals from its external environment, devising shared utilities for common use, making communication protocols clear, and arranging modules into a hierarchies and layers. The system must be structured in such a way that design teams can operate independently much of the time, know when coordination is required, and be able to coordinate effectively when necessary. The overall structure should be set up in such a way that individual teams evolving separate chunks rarely cause unwanted side-effects elsewhere, designers can recognize threats when they do occur, and the overall conceptual integrity of the system is maintained.
All of this involves a number of hard choices. The architect must contend with multiple competing ways of decomposing a system into hierarchical structures and competing criteria for determining which functionality should be clustered in each module. The architect must also determine how big each module should be and how interfaces between them should be designed. These choices will have a profound impact on how complex different portions of a system will be.
A successful architecture process will yield an abstract description of a large system that, if designed and built, would function appropriately, control complexity, and have the ability to scale and evolve over time.