Continuous Integration: Why You Don't Really "Get It"
A vast majority of daily practitioners of Continuous Integration don't really understand it. This is a bold statement, I know. But it is not made to simply capture attention. Most practitioners of Continuous Integration, when asked, will either tell you that CI is about integrating changes often, or that it's about producing frequent builds of your software. Both these answers are incomplete at best. Even articles on Continuous Integration gloss over the thinking behind it and jump straight to the implementation.
This is a guest post from UrbanCode's CEO Maciej Zawadzki
So this blog entry is about the "thinking" behind Continuous Integration. Because only by understanding the core ideas behind CI can you understand what is happening in the industry now or get a glimpse of where it is headed in the future. Once you "get" the core concepts behind CI, it's easy to see that Continuous Delivery is a natural extension of Continuous Integration.
Most people know that CI is based on the observation that the longer development streams diverge -- the longer developers work independently without synching their work -- the more painful the eventual integration will be. Taking the converse of the above statement, the more frequently developers integrate their changes, the more painless those integrations will be. Thus, lets integrate as frequently as possible, continuously, on every change. Hopefully, this is nothing new. Now notice that this is not enough to understand Continuous Integration as it leads to the following question.
Why does it not suffice for developers to simply check-in or commit their changes frequently to practice CI? This question indicates that there is one additional, although rarely stated, aspect to CI -- that in order for a merged change to be successfully "integrated," it should not degrade the code quality. This implied condition -- that each integration will not decrease the code quality -- is the key to understanding CI; the rest is implementation details. It is this condition that shapes the practice of Continuous Integration and gets the ball rolling towards Continuous Delivery.
The familiar implementation of Continuous Integration using a build and test process can be derived from our now explicitly stated condition (that each integration not decrease the code quality). Notice that this condition requires that we be able to determine the quality of code in order to implement CI -- how else would we know whether the quality decreased? And how do we determine the quality of a code base? We test it. And how do we test it? We compile (build) the code and run tests against it. This is why Continuous Integration is implemented as a build and test process.
The fast feedback required by CI necessitates a compromise that leaves a lot of unfulfilled value on the table. It is well known that CI requires fast feedback -- ideally we get feedback on one change before we start integrating the next change. The determination of quality, on the other hand, is one of those crazy things where the more tests we run, the more accurate our picture of the code quality will be. But tests take time, thus creating the need for a compromise. Most implementations of CI compromise by including only some of the tests (typically unit tests) in the build and test process. And this limits CI to having only a partial view of the code quality and leaves a more complete picture of code quality undelivered.
In order to provide a more complete picture of code quality, we need to run more tests. At least for web applications, more tests means in-container tests, and that means deployment to a container. Thus, if we want to provide a more accurate picture of code quality, as our explicitly stated condition suggests, we need to start deploying our code to test environments and run progressively more tests. What shall we call this practice? How about Continuous Delivery.
The purpose of this blog entry was to make explicit that little implied condition in CI -- that the integration must not decrease the quality of the code base. We've demonstrated how this condition can be used to derive the typical implementation of CI (the build and test loop) and Continuous Delivery. Can you spot other industry trends that can be traced back to our non decreasing code quality condition?