|"Architecture" is a concept central to the Rational Unified Process (RUP), but appears to have much less emphasis in Extreme Programming. Where's the architecture?|
[This became a chapter in Extreme Programming Explored.]
What is architecture?
The IEEE definition (P1471 description) is "An architecture is the highest-level concept of a system in its environment."
In RUP, architecture is seen as supported by multiple views, usually including logical view, implementation view, process view, deployment view, and use-case view. The use-case view is regarded as critical as it ties the others together.
Architecture is often described as the spine or skeleton of the system, embodying the decisions that have global impact and/or would be difficult to change. Extreme Programming has less emphasis on architecture than other methods because architecture has less impact in XP. XP says "embrace change," while architecture-driven approaches say, "Some things are hard to change – so plan the skeleton first."
On the other hand, architecture in the sense of "the essential structure" has meaning even in XP. It addresses architecture through several mechanisms:
- First Iteration
- Small Releases
- Pair Programming, Coding Standards, and an Open Workspace
Early on, during the release planning game, the team has the opportunity to do spikes – quick explorations into the nature of a potential solution.
Based on the stories and the spikes, you'll decide on an approach to the system's structure. For example, suppose you have stories about managing orders over the Internet, and the security that requires. You might quickly converge on a a solution with a web server, an application server, a database, and a pair of firewalls.
Another story might tell you performance constraints. To investigate performance, you might do a spike simulating many browser clients simultaneously sending queries to the system. This can help tell you how big your boxes have to be.
Another story might give you availability requirements. You'll explore replicating servers, database failover, and so on, to make sure you technically know how to manage high availability, and to help the customer assess costs.
You'll also do spikes for functionally, to explore how to implement various parts of the system.
Thus, the spikes you do in the exploration phase can guide you to a deployment architecture. Since the spikes begin early on, you have some lead time for ordering and installing hardware and software. Don't underestimate the value of having this part dealt with early on – I've seen many projects stuck in a panic as they try to get end-to-end communications all at the last minute during final installation. Addressing this early addresses a high-risk part of many projects.
What if the customer just doesn't want stories about performance, availability, etc?
That's their prerogative. You have an obligation to let them know your perception of the risks, but the call is theirs to make.
What if the structure has to change later?
If it has to, it has to. All you can do is give it your best analysis. With a solution in place, you'll be able to identify any problems sooner than you otherwise would, giving you more time to fix the problem.
During the exploration phase, and all along the way, you'll seek an effective metaphor that helps guide your solution. For the online ordering system, the metaphor might be centered around forms and orders.
The metaphor acts as a key part of what RUP would call the logical design. It identifies the key objects and their interactions. This helps orient you when you're trying to understand the functionality at the highest levels.
The metaphor may change over time as you learn more about the system, and as you get inspired in your understanding of it. This is an example of the fluidity of the architecture – if the conceptualization can be improved in XP, it will be changed.
The first iteration is key in making the system come together. From Extreme Programming Explained, p. 113: "…the first iteration must be a functioning skeleton of the system as a whole… For the first iteration, pick a set of simple, basic stories that you expect will force you to create the whole architecture. Then narrow your horizon and implement the stories in the simplest way that can possibly work. At the end of this exercise you will have your architecture." Page 134: "The first iteration puts the architecture in place. Pick stories for the first iteration that will force you to create 'the whole system,' even if it is in skeletal form."
Michael Hill talks about using the first iteration to produce a ZFR ("ziffer" – Zero Feature Release). The team produces a system that does exactly nothing, but does it in a way that the whole architecture is in place for the system.
There are several things the first iteration can do to make it easy to put in place:
Skinny. You don't need all the features of any component. For example, you would make sure the web server, application server, database, and firewalls were all present and could talk to each other in the simplest way possible.
The book The C Programming Language, by Kernighan and Ritchie, had many good features, but the one that's stayed with me the longest is the use of a "Hello, world" program: a minimal program that printed that phrase on the console:
printf ("Hello, world!n");
It's a small program, but notice what it takes to get it to run: access to an account, the account set up so tools can run, running the compiler and the linker, and running the program itself. This is often the key: if you can get any program working, you can modify it as far as you need to. If you can't get even that simple program working, what chance do you have of getting a realistic program to work?
Configuration. Major pieces of software like web servers and firewalls have many ways they can be configured. By focusing the first release on an end-to-end version of the system, you help ensure that the configuration is right while your system is still simple to understand.
This is a sort of debugging. You change one thing at a time: the configuration, not two things (configuration and program). This way you know that, since your components work in a simple configuration, it's the configuration at fault and being fixed.
Shed Functionality. The focus is on an end-to-end solution. If the first iteration gets in trouble, drop any functionality you need to. The first iteration doesn't have to be useful – it has to be installable.
One-Button Interface. I find it useful to think of the simplest story that will drive through the system, and give it the simplest interface possible:
I've violated this approach too many times. There is always a lot of pressure to add more features "while we wait for the hardware to get here." I worked on a web project that should have taken this approach:
If we'd gotten that working (through dozens of configuration issues), nothing else would have been that hard.
XP's small releases help gel the architecture quickly. Since you're only installing a few months' work, you'll be forced to get the essential structure in place quickly. You're delivering the stories the customer values most. Because you get feedback quickly (from real use), weak areas in the architecture show up so you can correct them.
Pair Programming, Coding Standards, and an Open Workspace
There's a level at which architecture dictates things "on the ground". It's lovely to have a software architecture document that explains wonderful things about how the code should work, but it's only valuable if it reflects what people actually do.
XP forgoes the Software Architecture Document that RUP values, but still has an architecture. Pair programming (including switching pairs) helps ensure that the people know and use the approach the team is using. If a better approach is found, the team can share and learn that. (The open workspace makes it easy to communicate.) Coding standards help ensure that code is written consistently
Who defines the deployment (technical) architecture? When?
The team defines the architecture. This is done during the exploration phase of release planning. As the team understands the stories and spikes potential solutions, it learns what it needs to.
How is the architecture documented?
As it will for all documents, the team produces enough to do the job at hand, plus whatever else the customer wants beyond that – badly enough to pay for. XP is light on documentation, but works hard to ensure that the team understands and communicates important information within the team.
Why produce a "skinny" version of the system? Wouldn't it be better to get, say, persistence "done right" on the first iteration, then concentrate on business logic in the next iteration, and so on?
By doing a skinny version, you're exercising all parts of the system, so you find out early on if there's a problem with any part. If you don't deliver a vertical slice of useful functionality in a release, you run the risk that the customer gets stuck with a well-designed part of a system that can't do anything. It's better to have 10% of 100% of the system, than 100% of 10% of the system.
If everybody is the architect, isn't nobody the architect?
In a sense, that's right. In XP, the team is responsible for the architecture. Alistair Cockburn describes XP as a high-discipline process, and this is one of the places that shows up. If the team makes no effort to maintain the metaphor, and doesn't bother converging to a consistent error-handling style, and doesn't focus on a functional system, it will not deliver what it needs to. (The presence of a Coach can help maintain the team's discipline.)
Where is the XP approach going to have trouble?
I worry about two places in particular, addressed by RUP but not explicitly by XP: the process/thread structure, and the data model. Threading and synchronization are hard to get right, and plagued by subtle bugs and sensitivity to change. Isolate them as much as possible, but they're still risky.
The data model is risky because it tends to be less fluid than the application code. (Consider migrating a 50-million-row table to a new structure, or converting data through a process that takes days.) This may reflect my comfort level more than inherent limitations of XP, but I struggle to manage these areas through the XP philosophy.
My team isn't XP – how much of this can I use?
You probably can't rely on the intense communication and oral history in XP: you'll need to document more.
Take advantage of spikes: explore to learn what your architecture needs.
Strive for a skinny implementation as your first iteration. So many problems are related to system configuration, that an early iteration with minimal functionality can help explore these areas thoroughly.
Although XP doesn't focus on architecture, it has several mechanisms that ensure it is addressed:
- First Iteration
- Small Releases
- Pair Programming, Coding Standards, and an Open Workspace
We talked about each these areas, and explored some questions about how they work in practice.
- Extreme Programming Explored, by Bill Wake. This article is the basis for chapter 5.
[July 3, 2000.]