Table of Contents
- Software architecture needs to be wrested from committees of people disconnected from developing, and to put it in the hands of the people who can actually make it real and executable, the developers. Only then will we achieve the resilience and sustainability that we need from today’s applications
- Software architecture is about capturing decisions, not describing structure
- Architecting is a skill that agile teams embody, which means that Architect should not be a role
- Architecting means continuously exploring new approaches and different alternatives to best meet quality attributes
- The key activity of architecting is forming hypotheses about how the system will meet quality attribute goals, and then using empiricism to test whether the system meets them, and then repeating this loop until the system meets its quality goals
Software architecture has a contentious reputation in the agile community. In the experiences of many, it is the cause of valueless meetings and irrelevant documentation that is aptly summarized by the expression “the map is not the territory.” And yet, applications with poor architecture can quickly become like vehicles abandoned by the roadside, broken and unrepairable. So is there a useful middle ground between these poles of pointlessness?
Part of the problem is that architecture is an inapt metaphor for the result of the work of architecting software systems. Inspired by the work of building architects, the word conjures images of beautiful designs that hint at utopian futures. But the work of architecting software systems is far more dynamic than the building architecture metaphor supports. Buildings are static, and the work of building architects is done just once. Software, by its nature, is ever-shifting and dynamic; when it stops changing, it starts to die.
To arrive at a better understanding of software architecture, we have to go back to the origins of the word architect: It comes from the ancient Greek word arkitekton, ἀρχι- (arkhi-, “chief”) + τέκτων (téktōn, “builder”). Architecture is created by people building things. That sense has become lost in the work of building architects, many of whom have never poured a foundation, framed a building, or run plumbing or heating pipes. Design and building have become separated. Not so in software, where how something is built influences what is built, and vice versa.
Software architecture is about decisions, not structure
The building analogy has led some software architects to focus too much on structure and behaviors, and not the decisions that produce those structures and behaviors. It’s not that structure and behavior are unimportant, but they are the results of a thought process that is important to preserve if the system is to sustainably evolve over time. Knowing why someone did something is just as important as knowing what they did. What they did should be easy to see in the code, if it is well-organized and commented on, but the why is often lost.
The reason for this is that architectural decisions in software are rarely clear-cut; nearly every architectural decision is a compromise between competing alternatives, and the merit of alternatives is hard to see until you try a few and see how they work. Knowing what was tried and rejected is often more useful than knowing what worked. As an old saying goes, good judgment comes from experience, most of which comes from bad judgment.
This is also one reason why software architects must still be developers; they can’t understand or predict the forces at work in a system without developing and testing something. Software Architect is not some sort of honorarium for people who have retired from active development but still have knowledge the organization finds useful; it has to be more. The act of architecting requires sufficient knowledge of a system to frame useful hypotheses about quality attributes, and the expertise to write code and devise tests (or work closely with team members who can) that can evaluate those hypotheses.
Architecting is a skill; Architect is not a role
In truth, using a title like Software Architect sends the wrong message about the nature of the work. The reality is that lots of software developers do architectural work, they just don’t recognize it as such. Anytime they make decisions about how to handle quality attributes, they are affecting the architecture of the system. Being more aware of how implicit decisions affect the ability of the system to achieve quality goals is the first step in improving the architecture of the system.
So what kind of skills do people need to develop to improve the quality of their architectural work? There are a few:
- An increased focus on quality attributes, which are the key cross-cutting requirements that good architecture should address. It’s easy for teams to focus on functional requirements, as they tend to be tangible, even visible things the system does for its users. But it’s the quality attributes of a system that shape whether it will remain viable over the long term: things like scalability, performance, security, supportability, and maintainability, to name a few.
- An ability to conceptualize and address system-wide concerns. Quality attributes are most often determined by forces that affect the whole system, not just one part. While modularized design and separation of concerns are important to building good systems, they also make it harder for team members to have a holistic view of the system.
- An understanding of the complete lifecycle of a system. This requires having experience not just developing a system, but also testing it, deploying it, running it in production, maintaining it over time, and making substantial modernization to it when it needs to do significantly new things. Understanding the lifecycle of a system and how it responds to change is essential to making good decisions that limit technical debt that, over time, can threaten the viability of a system.
- An ability to balance concerns and compromise. There is rarely one right answer in architecture work. Architecture often involves making trade-offs between conflicting Quality Attribute Requirements (QARs) and constraints.
- An ability to learn from experience and synthesize new approaches. This involves the ability to take the results from trying things in a directed way (running experiments) and to generalize that learning in the form of principles that can guide further experiments. Some of these principles take the form of “standards,” which is a somewhat misleading term because standards need to be constantly tested using experiments to determine when they are no longer useful. We’ve seen many developers justifiably frustrated with organizational “standards” that made sense at one time but which now keep teams stuck in the past.
- An ability to demonstrate leadership. The ability to raise concerns, foster discussion of different perspectives, and facilitate consensus helps a team confront and overcome complex architectural problems. Anyone on a team could do this, and anyone who is architecting must do this.
Architecting means continuously exploring
Architecting modern software applications is a fundamentally explorative activity. Teams building today’s applications encounter new challenges every day: unprecedented technical challenges as well as providing customers with new ways of solving new and different problems. This continuous exploration means that the architecture can’t be determined up-front, based on past experiences; teams have to find new ways of satisfying quality requirements.
As an example of how exploration is essential to discovering the architecture, consider the following: Assume that you are part of a team working on a software system originally designed to handle structured, tabular data stored in a SQL database. This system now needs to be enhanced to handle unstructured data, including images and videos, and the volumes are expected to significantly increase over what the system currently handles. You consider adding a NoSQL database to your technology stack to handle the new data types, but since your team does not have significant experience with this technology, experimentation is essential to select the right database product and configure it to meet the new data volume requirements.
As the team works through these technical issues, they form hypotheses about which approaches will best meet their desired QARs, which are assumptions as well and will change over time. They build a part of the solution to test these hypotheses, and they make decisions based on the results. The cumulative result of these decisions about how to meet QARs is the architecture of the system. The team may communicate these decisions in different ways, including using documentation and diagrams, but the docs and diagrams are not the architecture, it’s the decisions, and their why, that matter.
Important information about these decisions includes things like:
- The cost of reversing a decision, should that become necessary. If you have to replace a service, a DBMS, or even a framework, it would help to know how expensive you think this might be. In some cases, it may mean rewriting the application.
- Clearly articulating any constraints or assumptions. Understanding the working constraints and assumptions that you’ve made may help the team who has to renovate your work in the future. For example, knowing that you’ve assumed that you will have no more than X concurrent users, and this has caused you to make certain decisions about concurrent threads or processes will help your future colleagues understand where they might need to change something if that constraint is exceeded.
- How you’ve met specific quality attribute requirements (QAR). For each QAR, you should describe what you’ve done to ensure that it will be met, and not just in theory, but what tests you’ve run to prove it. Link to specific test cases and their associated automated tests, so that when the QARs change you will be able to easily reevaluate the architectural quality of the system.
- What options you’ve considered as your rationale for decisions. Knowing what things you considered and rejected is often even more useful than knowing what you decided; it shows your thought process and provides insights into constraints you may have been under when you made the decision. If these constraints are removed in the future, knowing why you made certain decisions will help future developers make better decisions.
Figure 1: Relationships between QAR, Decision, and Technical Debt
- What technical debt you’ve knowingly incurred. Some decisions will, inevitably and unavoidably, create technical debt; for example, the decision to meet reliability goals by using a SQL database has some side effects on technical debt (see Figure 1). The now long-past “Y2K problem” was a conscious decision that developers made at the time that reduced data storage, memory use, and processing time needs by not storing century data as part of standard date representations. The problem was that they didn’t expect the applications to last so long, long after those constraints became irrelevant. Had they communicated their decisions and described the potential impact more precisely, there may not have been such a scramble to respond at the end of the last century.
Software architecture, as a discipline, needs a makeover. Its image suffers from a lot of old ideas about what problems it needs to solve and how it should go about solving those problems. Viewing software architecture as a continuous activity focused on forming hypotheses about how the system will meet quality attributes, and then using empiricism to prove that the system meets them, is the essence of a continuous approach to software architecting. What also needs to change is to wrest software architecture from committees of people disconnected from developing, and to put it in the hands of the people who can actually make it real and executable, the developers. Only then will we achieve the resilience and sustainability that we need from today’s applications.