o you want to be agile, do you? You want to work in small increments and continuously deliver business functionality. You want to embrace change, even if that means taking on new requirements late in the game. But wait, won't that be dangerous? It doesn't have to be if you've got a solid Continuous Integration (CI) infrastructure in place.
Agile Development and Friction
Before digging deeply into Continuous Integration, let me talk first about how agile developers want to work in this brave new world, and some of the potential problems along the way. Agile development means working iteratively and incrementally to build a system one feature at a time. The development team slices each project into iterations—but don't think that this just means doing a series of mini-waterfalls, because in agile development the team does all the traditional phases of development and testing simultaneously. The goal of any given iteration is to complete a finite number of business requirements. Completion in this case means "done, done, done." In other words, the development team has coded the feature, it passes all its acceptance tests, it's signed off by quality assurance, and the customer has reviewed and approved the feature.
Think about this for a minute. You want to take a number of business requirements and drive them to a deployable state within a short time frame. To finish, you need to put the new code in front of testers and the actual customers. To do that, you need to pay attention to how your team uses testers during each iteration. You can't just let testers sit idle for the first three quarters of the iteration, and then dump all the code onto them at one time. You'll increase the project's overall throughput if you can push some completed features to the testers as soon as possible to get them engaged early in the iteration.
The point of all this discussion is to emphasize that you need to stage code very frequently in the face of an evolving design and architecture, moving small bits of completed features from development to testers to demo servers frequently within the course of each iteration. You need to make change safe and risk free by building in lots of feedback loops that spot and diagnose problems. I like to think of agile development as a car engine that runs at high RPM. Friction that you might not feel in a sequential development cycle becomes painfully apparent in a more iterative process. Fortunately, you can use some software engineering practices that can enable iterative processes and lubricate the friction. Chief among these practices is Continuous Integration.
What Is Continuous Integration?
|The best practice for effective CI is to perform the integration on a developer workstation before that code escapes into the build server wild.|
Roughly put, Continuous Integration is the practice of doing integrated builds very frequently, usually upon each check-in to source control. CI is first and foremost a development practice, but most teams will use a CI server tool such as CruiseControl.Net
to execute their CI process. The tools are helpful, and maybe even essential, but the practice and the mindset is the important take-away from this article. Forgetting for now the specific choice of CI software, the basic CI workflow looks something like this:
- Check in code to source control. (You are using source control, aren't you?)
- The Continuous Integration software on the build server sees that there are updates to source control since the last build.
- The CI server retrieves the latest version of the code into a working folder on the build server.
- The CI server then runs an automated build script (more on this later).
- For a successful build, the CI server will create a tag in source control to version the build.
- Finally, the CI server will broadcast the success or failure of the automated build. This might be to a monitoring client on each development workstation, instance messenger, or through email.
The build script must be fully automated and run without human intervention (you do want to go fast repeatedly, right?). The script needs to know pertinent folder locations and the resources that your system needs to run. Most build scripts will compile the latest version of the code, set up the development environment (registry settings, putting components in the GAC, setting up IIS virtual directories, you name it), and run the battery of unit tests in the code. Running the automated build should give you a quick indication whether there is anything wrong with the code. CI is all about getting feedback about the state of your code.
More advanced builds will include automated database builds, static code analysis, integration or acceptance tests, and automatic generation of deployment packages. Again, CI is all about moving quickly and safely by automating repeated deployment activities and building feedback loops around your code to spot problems quickly.
|Editor's Note: This article was first published in the May/June 2008 issue of CoDe Magazine, and is reprinted here by permission.|