The Pragmatic Architect - To Boldly Go Where No One Has Gone Before
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.
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 email@example.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.
Programmers won't care
Let me explain.
I think one of the most important drivers of architecture is Conway's Law: a system structure will resemble the internal communication structure of the organization creating it.
However, it resembles the organization which is creating it not the organization it is created for.
And here lies the problem: either when you do outsourcing, or just an internal IT team, people don't feel themselves part of the business: they're IT. They're hired by a company to do software development. They don't really care what the company is doing, code is code.
And here comes the bad part: the programmers deal with only their domain: programming.
Once I asked a bunch of highly skilled developers, wether it occured to them at any time to build a framework other than MVC for any big application they were working on: not instead of MVC, but orthogonal to it. They didn't understand what I was speaking about.
There are exceptions of course, mostly in the DSL community, when something is really, really based on the domain we're speaking about: there are nice cartography projects for example, who speak about maps instead of models and views.
But most of the talk is about MVC, perhaps data modeling, never about domain modeling, how things should interact: the discussion is about how a certain domain can be encoded in terms of MVC/MVVM, or, more prominently, with the tools of your own choice.
And this is bad, this is seriously bad for architecture.
Any kind of architecture must start with use cases: at the end of the day, every application is there to solve a problem, a problem people outside the IT community have. These use cases are the needs those people have; the success of an application, by and large, is about how well does it tackle those needs.
Encoding the domain in the solution is not about the ints: heck, it doesn't even matter, type is a way to encode information, but you can encode in names as well.
Encoding the domain is about choosing a path which doesn't have a big jump of "let's forget everything, and compile this to the IT domain": that's like compiling the domain knowledge into assembly: nearly noone is able to decode reasoning from byte code. Our bytecode is java, our bytecode is C++, .net, spring, whatever. It's our responsibility to have a clear connection between the source of the requirement and the implementation.
It cannot be really taught: we don't have general recipes on how to model a domain (yes, I'm aware of the DDD book, I've read it a few times), as every domain is different: yes, we do have UML and such, but we won't go to an IT conference and talk about the domains of our customers.
It's also sad that today all the knowledge needed to understand a non-IT domain is out of the mainstream: we don't speak about UML, we don't speak about documentation, we don't speak about company workflows (in fact, we want the whole company to adapt to Agile instead us adapting to the company), we don't speak about requirements analyis (or when we do, it's about how to translate it to executable [test] code, which is not the point!), so IT is more-and-more enclosed in its own castle.
Domain knowledge is needed, and it should be represented in our programs explicitly: we aren't to solve the problems for ourselves only.
Re: Programmers won't care
I called it monkey coders, vs Business developers.
Monkey coder should not be pejorative, it is not a criticisim of their skills, but what identify their goal : Code, get the money and leave.
That's exactly what happen with outsourced developers like you said. They are not "part" of the company. And they don't have the time to because part of it.
Business developers has the goal of their company, and the only way to have them is to immerse them inside the business... For a long time and every single day. That's what I call passive learning. The worse thing is to enclose them in the IT division with IT people.
Not all development need domain knowledge, so there is a huge need of code monkeys. But when there is big domain knowledge, hiring code monkey is suicide. All the company I know that tried to hire monkey instead of business developers failed... And it was costly.