One of the great things about joining a new team is having the opportunity to re-evaluate your practices in light of the way other people work. You also have a chance to hear new arguments about why others do things differently to the way you do. One recent discussion came about after I spotted that a colleague pretty much always used a branch for each (non-trivial) feature, whereas I always tend to use main/trunk/master [1] by default.
Martin Fowler wrote about both Feature Branches and Feature Toggles a few years ago and ever since I worked on a project where there were more integration branches than a banyan tree [2] I’ve favoured the latter approach. Working with a source control system that doesn’t support branching (or does but very poorly, like SourceSafe) is another way to hone your skills at delivering code directly to the trunk, without screwing up the build (or your teammates).
Branching
The reason for branching at all is usually because you want some stability in the codebase whilst you’re making changes. Your view/working copy [3] is clearly isolated from other developer’s but unless you have the ability to commit your changes in stages it’s not exactly the most productive way to work. The most common non-development branch is probably the Release Branch where changes are made very carefully to maintain stability up to deployment and then to act as a safe place to create fixes and patches to address any serious problems.
I find myself very rarely wanting to branch these days. It’s more likely that I decide to shelve [4] my changes to reuse my working copy for something else, e.g. fix a build/deployment problem, after which I’ll un-shelve and carry on as if nothing happened. I don’t work in the kind of environments where spikes are very frequent; if anything it’s a potentially messy refactoring that is likely to cause me to branch, especially if the VCS doesn’t handle moving/renaming files and folders very well, like Subversion. Using the Repo Browser directly in Subversion with a private branch is probably the easiest way to remain sane whilst moving/renaming large folders as it saves on all the unnecessary shuffling of physical files around the working copy.
Toggling
My preference for publishing changes directly to the integration branch is borne out of always wanting to work with the latest code and keeping merges to a minimum. That probably sounds like I’m being a little hypocritical after what I said in “What’s the Check-In Frequency, Kenneth?”, but I try and keep my commits (and/or pushes) to a level where each change-set adds something “significant”. This also allows me to fix and commit orthogonal issues, like build script stuff immediately without having to cherry-pick the changes in some way.
Generally speaking, new code tends to have a natural “toggle” anyway, such as a menu entry or command line verb/switch that you can disable to hide access to the feature until its ready. When the changes go a little deeper I might have to invent a switch or .config setting to initially enable access to it. This way the feature can be tested side-by-side with the existing implementation and then once the switchover has occurred the default behaviour can be changed and the enabling mechanism removed. The need to do this kind of thing comes out of the way some organisations work - a lack of formal acceptance testing means the change practically reaches production before it’s known whether it will go live or not!
Waste Until Proven Useful?
What I found interesting in our discussion of the branch vs toggle approach was that my colleague felt he needed to keep his “work-in-progress” code out of the integration branch until it was mature. Looking at it from a lean perspective I guess you could argue that a feature that is not enabled is just waste and so shouldn’t exist - it’s dead code. This kind of make sense, but I think it turns a feature into an all-or-nothing proposition and there may be value alone in any refactoring that has been done to get the feature implemented. I would want that refactoring to take effect in the development integration branch as soon as possible to give it time to bed in.
I guess what makes me comfortable with working directly on the trunk is having 20 years experience to draw on :-). I have the ability to break down my changes into small tasks, and I know what kinds of changes are highly unlikely to have any adverse effects. This also presupposes the codebase is being developed by other people that also don’t have a habit of doing “weird stuff” that is likely to just break when seemingly unrelated changes occurs. All the usual good stuff like decent test coverage, low coupling and high cohesion makes this style of working achievable.
[1] Have we reached a general consensus yet on what we call the major “development” integration branch? I know it as “main” from ClearCase, “trunk” from Subversion and “master” from Git. SourceSafe doesn’t have a name for it because it doesn’t exactly make branching easy.
[2] Not sure if they have the most branches, but they sure seem to have a lot!
[3] Once again, I have “view” from ClearCase and “working copy/folder” from Subversion/SourceSafe.
[4] And yet another term - “shelve” or “stash”?
No comments:
Post a Comment