BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles The Pragmatic Architect - To Boldly Go Where No One Has Gone Before

The Pragmatic Architect - To Boldly Go Where No One Has Gone Before

This item in japanese

This article first appeared in IEEE Software magazine and is brought to you by InfoQ & IEEE Computer Society.

What makes architects masters of their craft? How do master architects design? Time and again, I’m asked these questions-and I’ve asked them time and again myself. Obviously it isn’t the degree of expertise in software engineering processes, design methods, technologies, and programming that makes the difference. Many architects have technical knowledge that’s both impressive and sound, which is indeed an inevitable basis for design success. Yet, a lot of software projects fail or suffer due to severe challenges in their architecture. The key to mastery is how architects approach design, what they value, and where they focus their attention and work.

What (Missing) Lines Can Tell-or not

Figure 1 shows a top-level diagram anonymized from a past project that its architects created to illustrate the system’s baseline design.

The diagram outlines the system’s key components, their responsibilities, and their core modularization principles. The architects used this sketch to communicate the design to development management and discuss its implications on business aspects such as cost, time, and effort. Yet management wondered after a while why the project experienced significant delays and budget overrun. They hadn’t gotten any hints or indicators from the architects’ reports.

The trouble came from the dotted black lines in the diagram as well as by "lines not shown." The dotted black lines represent a proprietary messaging middleware the project developed. The communication relationships among the outlined components are completely missing from the diagram, particularly those that run through the middleware. The architects didn’t consider these aspects worthy of modeling or reporting because from their perspective, they represented basic technical infrastructure not contributing to the system’s domain and business case. However, much of the budget went into the middleware’s development, and because it experienced problems with robustness and performance, the best developers were withdrawn from other system parts to fi x the deficiencies. In addition, scaffolding the middleware problems required signifi ant effort in the domain components.

(Click on the image to enlarge it)

Figure 1. A high-level architecture sketch to communicate key design decisions with business stakeholders.

Design between Things

Hindsight reveals that the system’s architects focused their attention too much on "obvious" things: user interface, domain-specific components, data management, and persistence. Yet the architecture’s problems weren’t within but between its components: interfaces, interactions, and integration with other systems-including the underlying technical infrastructure. The architecture specification barely addressed these aspects, so the architects and developers didn’t focus on them until problems occurred.

In contrast, pragmatic architects pay more attention to the things between things-that is, things between components and things between the LOC, such as domain concepts hidden behind standard data types. Sure, they also guide the design of the system’s actual components, but while guidance is often sufficient for further decomposition and realization by the development team, the things between things actually require down-and-dirty hands-on work from the architects. There they must be, that’s their territory-especially if there’s uncertainty in how to actually design these "things." Let’s investigate some secrets of pragmatic architects.

Uncover Hidden Domain Concepts

I recently ran a tag-cloud generator over several of our systems’ code. I wanted to get an impression of their most important domain concepts. Surprisingly, the topmost data types across all systems were string and int. Yet I doubt this is the case because in a system for industrial engineering or energy management, other concepts are significantly more important: devices, power lines, sensors, actuators, tags, alarms, and the like. When I looked closer at the code, I found the domain concepts-but they were scattered across sets of more or less unrelated basic types such as string and int.

Such implicitness can require significant effort for developers to understand and realize a system and to assure its production quality. How do I know that an int actually represents a domain-specific concept? How can I enforce the contract of the domain-specific concept when using the int in a concrete computational context? I can’t, other than by commenting and convention, which isn’t really helpful in practice. Figure 2 shows the (commented) code snippet that caused the self-destruction of Ariane 5 on its first flight in 1996.1 The root cause was an inadequate protection from integer overflow.2

(Click on the image to enlarge it)

Figure 2. Snippet from the Ariane 5 code. Inadequate protection from integer overflow caused Ariane 5 to self-destruct on its first flight in 1996.

It would be too brave to claim that the Ariane 5 software error could have been avoided if developers had modeled velocity as a proper value type with a defined usage contract. Yet the example nicely captures the importance of such explicit modeling.

Domain concepts can also get buried under myriad details even if they’re obviously explicit. For example, I once investigated a system because of its complexity. The software included a name service with more than 300 methods in its interface! The service’s actual contract was hardly visible and developers struggled to use it correctly and efficiently. Analysis revealed that it needed fewer than 20 methods to fully specify the service’s required contract.

Pragmatic architects thus pay significant attention and work to portray all domain concepts explicitly in their architectures, such as those represented as coarse-grained components, small domain-specific data types, meaningful interfaces, and so on.3,4 When modeling concepts, pragmatic architects always focus on economy to avoid clutter and complexity and to prominently emphasize the concepts’ essence.4 As a result, implied concepts or collocated capabilities become immediately visible in a system, helping developers recognize and treat them as distinct, explicit, and meaningful types. Usage becomes type-an important practice for creating expressive software designs and robust implementations.

Be Where Things Meet

What is architecture? Eoin Woods reflected on this question for quite a while and found an answer. It’s the driver behind "many of the ideas that architects use every day: frameworks, brokers, layers, interfaces, messaging, connectors ... it’s all about the gaps! [...] The architecture is the glue that binds the work of software designers together into a resilient, flexible, scalable, and ultimately useful system."5

There’s a lot of truth in this conclusion. I’m sure all of us know stories about component interfaces that don’t support the workflows our systems had to support. In many projects, integration- be it systems integration or "just" the integration of its constituent components-is the biggest cost position. The gaps-the space where things meet, the interaction between components-are where nobody feels responsible, except pragmatic architects! It’s a nontrivial task indeed to design component interfaces that are concise as well as meaningful and support the workflows to implement between components. It’s difficult to define interactions between components that correspond to tasks that users execute on the system.6 And it’s even harder to integrate a system with other systems such that it supports cross-system workflows without degrading the individual qualities of each system involved. A quick look at the patterns literature on these topics supports this observation.7,8

This "void" is actually what requires much of an architect’s attention and hands-on work. Yet the focus is less on an adaptation between things- interfaces, interactions, components, systems-that must be connected; it’s predominantly on the harmonization between these things along the workflows to be supported.6 The goal is the leanest adaptation, not the most impressive mapping! This is where architecture happens; decisions here heavily influence system life-cycle costs. The war story from the beginning of this column is also located exactly here: where things meet.

We can expand the idea of designing "in-between" toward all types of self-contained systems’ artifacts-for example, parts that reside on different computational nodes, within different processes, or within different threads. I’ve seen projects fail because of a naïve gluing among their processing entities. It’s simple to create working interaction among entities distributed across computers, processes, and threads. It’s mastery in design, however, to create an interaction among (distributed) processes that minimizes network interaction or the need for synchronization among threads.7

Use Uncertainty as a Driver

We all complain about vague system requirements. Yet even if business stakeholders conduct the most careful requirements elicitation, it won’t resolve all the ambiguities and uncertainties: That’s a fact. Likewise, software engineers can elaborate alternative solutions to specific requirements and spend endless time in discussions on which alternative to use. But architects must face the challenge to design, develop, and deliver systems that meet the requirements that are business-relevant when the systems are released and that remain so over the systems’ lifetime. The longer the development time and the longer the system’s lifetime, the bigger the uncertainty.

An all-too-typical escape architects choose in such a situation is genericity- which in its extreme can lead to flexibilitis, where architectures become overloaded with flexibility mechanisms that theoretically support all potentially envisioned system configurations but hardly fulfill the concrete (nonfunctional) requirements of any meaningful configuration.9

Pragmatic architects are aware of this danger zone and thus use uncertainty as a driver for decisions.10 First, they acknowledge that there’s a choice between options and work toward isolating the variable aspects of their designs to limit the effect of variation or choice. They further seek system usage scenarios that help clarify uncertainty in the requirements or the selection of a particular design choice to realize the scenarios as prototypes or as part of a walking skeleton. 9 And they welcome the feedback loops that prototypes and walking skeletons offer to drive or adjust their decisions. Again, architects design between things-in this case between ambiguous and uncertain requirements or alternative design options.

The title of this column is "to boldly go where no one has gone before." Architecture design is exactly about that. Go between things: between and across the lines of code to discover hidden domain concepts, between the components of your system and other systems to guide the design of interfaces and workflows, and also between uncertain or optional alternatives to drive a decision. It’s the architect’s job to uncover the things "in between" as early as possible, make them explicit, and decide about them. This, paired with sound knowledge in relevant architecture methods and technologies, as well as their deliberate practice, is architecture mastery: thoughtful design at a software system’s pain points that ultimately decide its success or failure.

References

1. J-J. Levy, "Un Petit Bogue, Un Grand Boum!" (in French), 2010.
2. J-L. Lions et al., "Ariane 501 Inquiry Board Report," 1996.
3. E. Evans, Domain Driven Design, Addison- Wesley, 2004.
4. F. Buschmann and K. Henney, "Five Considerations for Software Architecture, Part 1, IEEE Software, vol. 27, no. 3, 2010, pp. 63-65.
5. E. Woods, "Architecting in the Gaps," 2011.
6. F. Buschmann, "Unusable Software Is Useless, Part 1," IEEE Software, vol. 28, no. 1, 2011, pp. 92-94.
7. F. Buschmann, K. Henney, and D.C. Schmidt, Pattern-Oriented Software Architecture-A Pattern Language for Distributed Computing, John Wiley and Sons, 2007.
8. G. Hohpe and B. Woolf, Enterprise Integration Patterns-Designing, Building, and Deploying Messaging Solutions, Addison-Wesley, 2003.
9. F. Buschmann, "Learning from Failure, Part 2: Featuritis, Performitis, and Other Diseases," IEEE Software, vol. 27, no. 1, 2010, pp. 10-11.
10. K. Henney, "Use Uncertainty as a Driver," 97 Things Every Software Architect Should Know, R. Monson-Haefel, ed., O’Reilly, 2009, pp. 321-361.

Frank Buschmann is a senior principal engineer at Siemens Corporate Technology, where he’s a principal architect in the System Architecture and Platform Department. Contact him at frank.buschmann@siemens.com.

 

 

This article first appeared in IEEE Software magazine. IEEE Software's mission is to build the community of leading and future software practitioners. The magazine delivers reliable, useful, leading-edge software development information to keep engineers and managers abreast of rapid technology change.

Rate this Article

Adoption
Style

BT