Mark Balbes presents a framework for agile project management’s critical techniques. These techniques are required for successful agile development, where rapid requirements changes can be followed through with rapid development changes.
I recently had an impromptu lunch conversation with a small group of agile consultants and developers. We had all come together at a conference and coincidentally sat down at the same table. The developers were explaining how their team was trying to use agile but was not having success. They were almost at the point of giving up and going back to their older processes. The consultants—trained and experienced scrum masters—started asking some probing questions. Was the team customer focused? Check! Did they have a trained scrum master? Check! Did they all receive training? Check! Did they use sprints? Check!
From the answers they gave, everything seemed to be in place. I decided to jump in with a few questions of my own.
- First, I asked about their automated testing framework—they didn't have one.
- Second, I asked about their continuous integration process—they didn't have one.
- Third, I asked if they used test-driven development—they didn't know what that was.
- Fourth, I asked if they paired—they thought I was crazy.
And from this short assessment, I knew why they were failing. You see, agile project management isn't enough. As a mathematician might say, “It's necessary, but not sufficient.”
The underlying goal of agile software development is to rapidly deliver high-quality code that meets the users' needs. The presumption, borne out through years of experience, is that software requirements change rapidly. The project must be able to keep pace with these changes or risk being obsolete before it is even delivered.
Agile project management practices go a long way to making this possible. They keep requirements flexible and allow them to change pretty much on a whim.
The catch is that the software itself has to be able to change on a whim too. It's one thing to be able to say halfway into your project that you are going to make major changes to the requirements. It's another thing to actually do it and still deliver on time.
Below is a framework for agile project management’s critical techniques. These techniques are required for successful agile development, where rapid requirements changes can be followed through with rapid development changes.
Automate Your Testing
Automated tests are nothing new to the disciplined software developer. While some may think this technique was invented when JUnit and other similar frameworks were created, it has actually been around for a long time before that.
And though it's nothing new, it continues to amaze me how many projects are developed without their benefits. A solid bed of automated tests (unit, integration, regression, and user acceptance tests) means that the software can be dramatically changed without the fear that existing functionality is going to break. Fearlessness means that the software can be more aggressively refactored and extended to provide new functionality faster and with higher quality.
Implement Continuous Integration
Continuous integration is usually thought to be an automated process using integration servers like Cruise Control or Jenkins. These servers continuously monitor your source control server (e.g. Subversion or Git) for changes, pull these changes, build the system, run all automated tests, and then publish the results. While this is great, on smaller projects you don't necessarily need this overhead.
Continuous integration is really the act of team members committing their changes to the software often (e.g., multiple times per day), pulling the changes from others, and then running all the tests to ensure that what they are writing has not broken anything already committed to the source code repository. In this way, everyone is working on the same baseline software.
If you think this seems obvious, let me tell you a story from many years ago when I was working on a traditional software project. When I joined the project team, everyone was committing broken code to the repository. They knew that the build only happened on Friday so they had that long to fix their code. One poor guy was in charge of the build. Every Friday, he pulled the latest code, built it, and then published it out for everyone to use as a base for the next week's development.
Sounds easy, right? Only, the build didn't get finished until the following Tuesday or Wednesday because nothing ever worked. And I'm not talking about broken tests—we didn't have a lot of tests. I'm talking about not being able to get the application to compile for days. It took me about a month, but I managed to get a build server running, train the team on how to properly commit working code (and pull down everyone's changes) and monitor the continuous integration build server for failures.
But that isn't the story. The story is about our teammate who was in charge of the complicated back-end data analysis engine. He was working solo. (No pairing on this project.) He had no automated tests. (You can forget about test-driven development.) And he didn't pull down any changes to the software for three months!
Go ahead and read that last sentence again. For three months he worked in total isolation. He didn’t want to pull down new code because he knew it would break what he was building and slow him down. Shame on us for not catching it. We ended up throwing away most of what he had done and reworking it.
Use Pair Programming
Here's the scene: two developers, one keyboard, one mouse, one large monitor, and one story for them to implement together. Can it really work?
Pair programming is perhaps the most controversial of the techniques we're discussing, but it is also one of the most important. Even at my work in Asynchrony, we continue to have differences of opinion on how much to pair program and how much to go solo. On my teams, the rule is that a pair must write all production code. Individuals can perform tasks like spikes and code reviews.
Pairing gives your team depth and breadth of knowledge. It prevents knowledge silos that often lead to bloated code and time-sapping bugs. The members on my teams change, but we can always absorb new members and get them up to speed quickly. After all, they get one-on-one training from their pair. When someone leaves a team, their particular talents leave with them but the knowledge stays.
Practice Test-Driven Development
Test-driven development is an important extension of automated testing. Rather than writing automated tests after the code is written, a single test is written and then just enough production code is implemented to make the test pass. After the test passes, you look at the code to see if it needs to be refactored to a better design. Then you repeat the process: test, code, and refactor. By doing this, you can find your cadence for methodical, predictable progress. Through that cadence, you continually increase your knowledge of what you are building, how to build it, and how to prove that it is working properly. In addition, the automated tests serve as documentation for the design. Unlike unified modeling language (UML) diagrams or other written documentation, the tests are living, breathing proof that the system works.
Test-driven development is not something that is easy to do. It takes practice and a willingness to change how you go about building software. But the rewards, as you’ve seen, are plentiful.
The development techniques I have described are crucial in order for agile to fulfill its promise of delivering high-quality software that can rapidly adapt to changing requirements. They allow software developers to change direction and potentially make sweeping changes to the design and architecture of the software while ensuring that existing functionality doesn't break. This intrinsic flexibility and adaptability in the software coupled with agile project management techniques is what enables an agile project to turn on a dime to meet new and emerging customer needs.