Continuous Integration has been out there for some years by now. The book, Continuous Integration: Improving Software Quality and Reducing Risk dates from 2007, but the first mention of the term has came up earlier in 1994.
So, it’s been nearly 20 years since this idea is present in the software industry. During this time new tools, new practices and new possibilities appeared.
“Continuous Integration is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early”(1).
Its main goal is to detect errors earlier so they can be fixed. It helps in delivering software faster, because it allows you to deploy small changes with higher confidence due to automated tests.
Continuous Integration forces committing to the master branch and for each commit, tests are run in a production-like environment, a build is generated and outputs a deployable package.
Here at Plataformatec we do not follow Continuous Integration, although we’ve inherited some of its best practices. Some time ago, Rodrigo Flores came out with the name of what we do, and since then, we’re calling it Discrete Integration.
Discrete, as in discrete mathematics, means we’re working with fundamentally discrete structures rather than continuous, in other words, the objects studied by discrete mathematics do not vary smoothly, but have distinct, separated values(2).
One of those objects studied by discrete mathematics are graphs which can be representations of git branches. Git branches are the core of discrete integration. But in order to elucidate some important points, let me give you some context of Continuous Integration.
Continuous Integration adopters push code to master branch on a daily basis. Because of that, you’re going to need a mechanism to hide incomplete code that is being pushed, such as Feature Toggles. In other words, you will need to prevent pieces of code to be executed because they’re not yet ready for production.
So, at Plataformatec, we tend to use toggles just when it is really required. For instance in an incremental rollout of a feature or when someone wants to control, for some reason, the software behaviour. And that’s because for Discrete Integration feature toggles are not necessary. Only fully implemented code is merged into the master branch.
In order to keep your work tidy, branches need to be merged as soon as possible. I personally call it the “minimum mergeable state”. You can think of when a task is complete or a user story is done – actually, it can be done anytime -, but the idea is to reach this minimum state so that you avoid integration problems.
To accomplish that, we use to shrink user stories to its smallest mergeable state. For instance, you could deliver firstly a page with a blog post form, then, you add a draft support, then an autosave feature and so on. Although autosave may be part of the draft feature, since autosave will be saved like a draft, it makes sense to be implemented afterwards. The three user stories are independent and deliverable, we’re just iteratively incrementing.
Sometimes, when pulling master’s code, conflicts will happen, but there’s nothing to do about it. What I mean is that Discrete Integration does not fear conflicts, since it is part of a developer work, although we do mitigate conflicts to happen.
As stated, shrinking user stories is not enough, that’s why Discrete Integration encourage developers to communicate. It can be done by a Chat tool, like Campfire, face to face, through Pull Requests or by a bit of each one. We even wrote a guideline where you can read more about its philosophies.
For us, Pull Requests are an import source of knowledge sharing, it also spreads collective code ownership, allows asynchronous code architecture discussions, decreases bug ratios and increases engagement and business knowledge.
It’s worth pointing out that commits into the master branch still happens. Sometimes you need to fix a typo, change a configuration line or other small changes. Although we would still send the commit link or ask for review before pushing, we’ve learned that it’s important to communicate all the changes, even small ones.
So, if you don’t push code directly into the master branch, you’re not using Continuous Integration by definition.
How close are you to Discrete Integration? Which practices did you miss? Please, let us know in the comments below!