MSWX Software Experts
“Agile” is an approach for developing software systems in an environment where requirements are always evolving.
Traditional engineering goes back to Roman military and civil engineering practices. The solutions to many building problems are based on fixed requirements and reuse of standard designs. Once the decisions of size, capacity, and functionality have been decided, engineer apply standard approaches to build a structure that works effectively.
Note that the construction cost might be higher than for a single-purpose design, but there are advantages to standardization. A standard design results in a structure with well-understood repair and maintenance costs. For a physical structure that may need to serve the same purpose for hundreds of years, this is a valuable characteristic.
On the other hand, when requirements change, the “fixed design” might be in trouble. If a town grows, it might need a bigger marketplace or wider main roads, and the “standard design” might not support the ability to evolve gracefully.
If we are going be in a rapidly evolving environment, we need to think about future requirements... and maybe the architectural issues that support flexibility.
In a software system, the architecture is the overall structure that the design and code fits into. The architecture defines the major components and interfaces, the run-time scenarios that fulfill the main needs of the system’s users, and the flow of data between multiple participants.
Architecture is concerned with ensuring the system really meets the key system requirements. It can be very difficult just looking at the “code” of the system whether the system meets certain critical properties (performance, security, reliability). Architects create models and documentations that help everyone in the software development workchain to check that the system will be OK.
Most architectures are not completely novel and new – they will use existing software components and frameworks, but they will also define some of the ways that the system can evolve. New modules can be added and existing interfaces can be adjusted to meet new requirements.
Reliability is an important system property that is addressed by architecture. Some “standard architecture patterns” are often applied: redundant data stores, multiple independent servers, and procedures for working around networking issues. There are also a number of high-level design concerns – following design rules that support a low failure rate of key operations, fast recovery after a failure, and so on. Reliability will suffer if different developers make conflicting decisions on how distributed processing will function or decisions on what should be the order of the recovery steps after a failure.
How do we document the architecture? Architecture isn’t just one thing – it is more than just a single simple picture. Some developers create a “layer diagram” and say “this is the architecture.” Other developers build an “architecture model” as a big set of detailed UML class diagrams with detailed definitions of all of the components and interfaces. For some people, the architecture is the set of messages and interaction scenarios between system components. And for other people, the architecture is the collection of SQL stored procedures that are used to perform data queries and updates.
Architecture isn’t just one thing, because architectural thinking is used at many different levels of the system structure. At the highest level, the external message interfaces and “architectural layers” are a good way to explain the coarse-grained structure of the system. On the other hand, architects need to ensure that some key fine-grained structures of the system are designed to meet some critical constraints – in order to satisfy the system’s performance and reliability requirements. A good architect will be comfortable doing analysis at multiple levels of abstraction when defining the key characteristics of the architecture.
There is a lot of “reuse of design ideas” in the process of defining the architecture of a system – using well-tested approaches that are built into some standard application frameworks and that are defined by common architectural styles and patterns. An experienced architect knows when to strictly follow a “standard architecture” and when to tailor the structure to meet a system’s special needs. This is especially true for systems where the requirements are constantly evolving – systems that will require some significant extensions and rework over time.
Agility in the software world is a product development strategy: using small teams and short iterations to build working software in an incremental process. The goal of an agile process is to build a small working system quickly, then add more functionality at a steady pace. In early iterations, the system may be usable but very incomplete. The development teams can focus on the most critical functionality early – so there is a lower risk of that critical behavior being incorrect or missing when the final system is shipped.
Each iteration produces a set of tested software (and usually in a “deployable” form, although you might not choose to ship the result of every iteration to a customer). This means that there is a lot of different kinds of work that are happening in each short iteration: requirements, specification, design, development of new code, testing new functionality, testing old functionality (to make sure that the recent code additions and changes don’t break old code), and deployment (creating deployment packages and customer documentation). It isn’t easy for a conventional organization to do this in a short iteration cycle – but small teams working on a small set of key requirements can succeed in being very agile.
Why is this agility a good idea? This development approach is really useful for handling new customer requirements – in a problem domain where the requirements are evolving rapidly. It is possible to react quickly to customer feedback – add new customer-suggested features or fix small customer-reported bugs within a few weeks instead of many months. Also, the agile approach improves teamwork: agile development avoids the traditional division of work into separate multi-month tasks for isolated developers – multiple team members often work together to build and test new components quickly, and they usually create a more streamlined and testable design than a single developer would create.
Agile development puts a big value on test automation, because there is a lot of system functionality needs to be retested in multiple iterations. The creation of new code and automated tests in parallel has long been considered a good disciplined approach for building high-quality software. Agile development is often the complete opposite of “unstructured hacking,” because the developers are encouraged to keep their code base simple, clean, and testable.
Agile teams need to do some planning work, but it is a simpler and more lightweight planning process than traditional development. In most of the standard agile development methodologies, developers work with product managers and customers to create a simple “backlog,” a set of individual customer-focused work items. The planning process is mostly “backlog management” – create and refine individual work items, order the items according to priority and customer value, identify the items to work on in the current iteration, check that each item is complete (design, code, and tests are finished, functionality is “deployed”).
Agile development is often very “developer-centric” – and the design work is done in each iteration is often narrowly focused on the work items scheduled for that iteration. Where is the architecture defined and analyzed?
In many of the standard agile methodologies (particularly Extreme Programming – XP), the development process is supposed to avoid creating large complex design documents. There is only supposed to be enough design work to implement the current set of “user stories.” Any extra forward-looking design is discouraged, because in the agile philosophy, the teams are not at all sure what the future feature set and backlog will look like. They could spend a lot of time and effort preparing a design to implement the majority of the backlog items... only to have half of the backlog items canceled and replaced with a very different set of user needs.
On the other hand, it can be a real challenge to do design and coding work without a well-thought-out architecture. It is very easy to “paint yourself into a corner” – for example, you might find that the only way to make some additions to an existing design to add a new feature will inevitably cause the system to fail some of its key reliability, performance, and security constraints. This is something that can happen in either agile or traditional development, but agile development’s “feature at a time” approach results in a greater risk of “fragile design.” If there are no “guide-rails” to keep the developers from adding new modules in an undisciplined manner, the code may become too complex to analyze all of the possible failures or security holes.
The main issue to think about is: “How to we resolve the apparent contradiction between good architectural practices and the agile development approach?”
The rest of this talk will explain some of the ways that good architecture practices can work together with an agile approach. Here is an initial summary – the key messages about agile and architecture:
In addition, there are a couple of good agile strategies that architects can try to be more agile, and that agilists can use to be more architecture-aware:
The most difficult work situation is trying to work together with other people who have a different value structure. Architects want to be organized and prescriptive – they would like to have the role of every system component defined and documented, and they would like to create some architecture rules for developers to follow to prevent disasters. Agilists want to be self-organizing and reactive – and they want to avoid doing wasteful activities, including extra documentation that might quickly go out of date.
This topic was discussed in two workshops at the ACM OOPSLA and SPLASH conferences:
The workshop participants identified several “myths” that these two communities have about each other. The myths are at least somewhat justified by the values and habits of most agilists and architects.
Are these criticisms fair? Sometimes yes. Part of the problem is an organizational issue: in many large companies, there is an architecture team or architecture organization, a bunch of experts who create documents and Powerpoint presentations, but not much code. They are often very isolated from development groups, their documents are not always read by most developers, and their architecture rules are frequently resisted by developers as too impractical. Agilists are often isolated as well, because their agile teams have been set up as a “new experiment” – and they get the message that they can make decisions without working together with other teams.
In order to understand how agilists and architects can work together best, we need to consider what are the “best” characteristics and behaviors of these two roles.
Architects need good communication skills, not just technical skills. A good architect has some of the following characteristics:
These characteristics make an architect a valuable collaborator on any software project – especially when there is an evolving set of user needs and an evolving code base.
Agilists are known for their flexibility and resourcefulness. A good agilist has some of the following characteristics:
Agilists not only “get things done,” but they make sure that they respect their teammates, customers, and members of other teams responsible for other components, interfaces, and tests.
Refactoring is the process of making many simple changes to an existing design and code base. The changes are “behavior preserving” – and the main intent of these small code adjustments and refinements is to make the design and code cleaner and easier to work with. Refactoring is a necessary step in agile development, because a rapidly-changing system can get unnecessarily complex. We need to do some “cleanup work” to adjust to changes in the design and changes in the feature set of an application.
Refactoring can have an impact on the architecture. In an agile world, the architecture of a system may need to evolve to meet new environmental challenges – distributed processing, new interfaces, cloud computing environments, and so on. Agile developers and architects need to work closely together to do both low-level and high-level refactoring tasks.
One of the agile principles from XP is YAGNI (You Aren’t Going to Need It). This principle says that is can be wasteful to “design for the future” – it is better instead to design the “simplest” thing that meets the selected agile work items. If the development of the next set of features comes into conflict with your early design, you may choose to do some refactoring to adjust your design.
This is an idealized “agilist” view of system evolution. In most systems, the decisions on the design of data storage and retrieval are going to be connected to many different performance and reliability requirements, so there really should be some early architectural analysis. The job of the architect is to identify the parts of the system structure where “doing the simplest thing” is not the right way to start. The architect ought to be involved in trying out early versions of the initial overall design, to make sure that the design approach will support the evolving system without a lot of chaotic refactoring.
This “early trial” process is done in several ways in the standard agile methodologies. In some cases, the agile team sets up an initial “architecture-centric” first iteration – sometimes called “iteration 0.” The work items in this iteration are aimed at prototyping a combination of tools, standard components, and interconnections that will serve as the system’s initial architectural framework. Some agile teams will expand this focus on infrastructure, by doing several initial infrastructure iterations to prepare for work on user-facing features.
As the system evolves, it may be necessary to add an occasional “architecture iteration” – where no new functionality is added, but some of the existing design clutter and duplication is refactored away.
The best approach for incorporating architecture into the agile process is to include special “architecture infrastructure” stories throughout the product backlog – which makes it possible to do a little bit of architecture work in every iteration. This is consistent with the approach suggested by Philippe Kruchten in his talk “What Colour is Your Backlog?” (See Kruchten’s talk on YouTube.) Kruchten suggests having four different “colors” of backlog items:
The purpose of this approach is to make the essential architecture and refactoring work visible. There is always a temptation to focus solely on the “green” items, but this practice is actually a violation of basic agile principles. Agile teams need to do enough rework to control the “overhead” of adding new user-facing functionality... without infrastructure investment, new work items will take increasing effort to code and test: this should become apparent from the results of the “retrospectives” where the agile teams regularly reflect on how well their team is doing.
In some cases, communication with an “external architecture team” starts to become inefficient. It may be feasible to have a “lead architect” as part of the agile team. It is good for the architect to be a full-fledged team member, so the architect can see the impact of his/her architectural choices immediately. This “resident architect” will also act as a design coach to other team members.
There are several ways that architects need to pass along important information to project staff:
One last key role for architects is to be in a position to “combat the forces of evil.” Architects are often more visible and credible to project managers, so they may help the team get relief from undue bureaucracy when they complain about impediments to the agile team (such as inconsistent human resources policies, inability to get adequate lab facilities for building and testing each iteration, too many report requests from random managers, and so on).
An architecture model doesn’t need to be a “big design up front.” It is better to have “just enough” modeling and documentation – a limited set of architecture documents that help all of the developers stay organized. In the standard “Organizational Patterns” (from the book Organization Patterns of Agile Software Development by James Coplien and Neil Harrison), the most important advice about components and interfaces is the “Architect Controls Product” – which explains that the architects are advisors, not absolute dictators. One of the key ideas in this pattern is that
Architects and developers should consider using a lightweight process of “just enough software architecture.” One of the best practical guides to building small, focused, risk-based architectural artifacts is the book Just Enough Software Architecture by George Fairbanks. (For a short introduction to small focused architecture, see the following talk on Architecture Haiku.)
How do we know if we have architecture “gaps” in our project? We should look for “architecture smells.”
In the refactoring literature, there is a lot of discussion of “code smells.” When code smells bad, it is an indication that the code structure probably needs to be improved. There are a number of standard code smells – duplicated code, monster methods, cryptic function names, and classes with all data and no meaningful behavior – each of them could trigger one or more code refactoring steps.
There are also “architecture smells.” We want to look for indications that that we are doing extra design and development work that could be avoided with more attention to architecture.
If our code has some of these “smells,” the code may be trying to tell us something – our developers have been somewhat undisciplined in their design and coding work, and therefore haven’t been spending enough time on addressing architectural issues.
The following partial list of architecture smells was proposed in the SPLASH 2010 workshop:
Two questions: What “positive actions” should agilists take to ensure that there is adequate attention to architecture in the agile development process? What “positive actions” should architects take to keep the architecture small and flexible to be used to support an agile software development process?
There are five things to be done:
This work is licensed under a Creative Commons Attribution 4.0 International License.