Or at least the best one that currently exists.
In the last article I explained why Continuous Integration is not the best option to achieve success in software development, due to its weaknesses. It fails when it’s about committing frequently, avoiding regressions and undesirable bugs and making teams effective and productive.
Getting into branch per task
What I’m about to explain now is the following:
- Assume that we are using SCRUM or a different Agile iterative methodology flavor (say Lean or XP)
- Assume we’re always working on short tasks (8-16 hours of work),
- Then, why don’t we implement a way of working where every single task is coded on a different branch, starting from a stable point in the mainline?
This will achieve the following benefits:
- Every single developer can experiment whatever he/she wants in his/her isolated branch. His/her work won’t disturb the others’.
- Since their work is isolated, developers can checkin as frequently as they need; the code doesn’t need to build correctly in the middle of the process (although it is always a good practice), but at the end of the task.
- Since the “in-progress” changes don’t need to be perfect, the tests can eventually fail, and the developer can run the whole test suite in an automated environment to check the progress. If this operation can be carried out automatically, the developer won’t have to waste time at all.
- At the end, the integrator (a role that can be played by any experienced developer) can decide what features he/she wants to include in a certain mainline. You can choose what features to include and thus customize your release to a certain customer or specific situation!!
- Since a task maps to a branch it is quite easy to trace the changes done during the progress of a task; what attempts were made and then discarded or successfully finished. Of course there may be tasks that are discarded at the end and not integrated anywhere: prototypes, analysis of new features or third-party components and so forth.
- Since tasks are isolated, we can test much more and don’t have any ten-minute limitation. This way, when the task is integrated in the mainline we can ensure that it’s bug-free with pretty much more confidence. This depends on our testing environment and code coverage, of course.
… and Cons
Still there are two drawbacks that must be taken into account:
Branches should be short lived.
The longer a branch evolves on its own, the more difficult will be to merge it back to the mainline. Since we plan to have short tasks (8-16 hours, right?) that’s not a big deal. But what about feature integration branches or special releases branches? They should be merged back to the mainline frequently (after running our fantastic test suite), so that the branches don’t get outdated from the main development line. The same holds true for tasks that need to modify a big number of files: they should be rebased before running tests and marking the task as “resolved” or “ready to integrate”. To achieve this we need to educate the team, making them concerned about the benefits of doing this. At the end of the day this is a win-win situation: developers work on their isolate environments as long as they finish their tasks ready to integrate. If a difficult manual conflict arises during the integration we have two options: call the developer for help and / or eventually discard the task and rebase it, if we don’t have the confidence to merge the changes manually without running the task test suite again.
The Build Master role.
The other disadvantage that Branch per Task detractors claim is that a Build Master role is needed. That’s true, but I don’t find such a shame on it. I think it’s a good thing having a responsible for the whole release process management, like a quality assurance manager reviewing the whole process in the distance. This role can be assumed by any developer inside the team, and he/she decides if a certain feature is trustworthy enough to deliver to a certain customer or on the other hand, keep it in the “lab” mainline and release it in the near future. Needless to say the release process must be as automated as possible so that any single developer can trigger it anytime (did somebody say: ‘also anywhere?’ hum… that sounds quite interesting!)
The merging nightmare
Every now and then, authors who strongly discourage this pattern state that branching and merging is a nightmare, something like chaos. As I explained in the previous article, when they say branching is a mess they really mean that merging can be a mess.
But with the appropriate tools we can minimize this problem, reducing it to just those cases where two or more developers have changed the same lines of code. In addition to this, it’s worth to mention the profits that some researchers have made about semantic merge; these improvements will probably make merging an even simpler and more effective operation in the near future.
I’ve been using the Branch per Task pattern for years and the benefits are clear: the mainline is pristine since nobody checks in there but the integrator, the changes are isolated and all the people work happy on their own, much less stressed and worried about breaking the build.
CI patches that smell…
Getting back to Continuous Integration (CI), I’d like to mention a strategy that some authors recommend when it comes to new features and hiding them till they’re ready to be public. They say that to avoid the problem of having new features not stable enough available for customers (as we don’t want to resign about having our mainline always releasable) we could use configuration files to hide those features. Something like if a parameter is false then the feature is hidden. I think that’s an ugly and wrong solution for several reasons:
- It’s not always easy to implement, but maybe for commands and graphical options, not for changes in complex algorithms, just to give an example. Nevertheless it can work reasonably good in simple scenarios such as new and independent options that don’t interfere with the rest of the existing product (context menu options, command options and so forth).
- It’s tricky and messy, and thus it smells really bad. It can force you unnecessarily to search for a workaround in order to get something hidden, in detriment of the design of the feature and the code. It’s possible that ugly code will be created that should be removed as soon as the feature is public, but you’ll need to take that into account or the code will remain there for ages.
- It’s difficult to track and keep under control which features are hidden and which are not. There’s not a branch, changeset or whatever entity that tells you the truth about it, and if somebody asks you what is public and what is not you’ll have to go and check those configuration files, open them and read them. Not to mention if you have several mainlines (labs, fix, main, customer-x-delivery-mainline).
… and a MUCH better approach
Now, let’s get back again to Branch per Task to face this problem: just develop the feature as it was to be published the day after the task is finished. Then decide where you want to integrate it: maybe in a “labs” mainline, or “main”, or even “fix”, or “customer-x-baseline”. Finish. Go and take a coffee. No tricks. No configuration files. Use configuration files for its natural purpose: save user preferences, not internal issues that can be hacked manually by a naughty boy with some spare time.
Branch per Task and Continuous Delivery
This strategy fits perfectly with the continuous delivery methodology: I build a new release everyday: I decide what I want to integrate and when I’m done with that I run the tests and build the release. Done. Then I continue developing new features, fixing some bugs, thinking about new testing opportunities of new features or studying some NCover reports. When the time is over I go home and play basketball, run for a while, do some exercise or meet my folks to drink some beer.
So, if you really want to keep your progress under control, and when I say under control I mean decide what you want to deliver and discard at a certain point whatever you don’t need without strange patches and some ugly code, I strongly recommend you to get rid of your Continuous Integration strategy today and start implementing Branch per Task in your organization.
Please, feel free to send me your insights.