More on VCS, branching, merging, etc.
Martin Fowler has posted a good discussion about the various flavors of processes to manage branching and merging. There’s a lot of good information in there. His conclusion is that cherry picking with the VCS is undesirable, that cherry picking should be done in software, and that continuous integration is the preferred process. It’s a good read (with pretty diagrams), although I don’t agree with his conclusion.
In particular, he ignores the fact that some categories of changes can not be continuously integrated. For example, systemic architecture changes are one category which often can not be continuously integrated. Also, the examples provided by Martin entirely ignore parallel branches (in the feature-set sense, rather than the VCS sense) of the software, and/or long-lived support for releases. Of course, these are exceptions, and nothing in Martin’s suggestion prevents the use of cherry picking to solve these cases.
Martin’s suggestion is that it is better to do cherry-picking in the software through configuration, or licensing, or whatever, than to do it via the VCS. I don’t believe that these approaches are mutually exclusive. You can have a modular architecture and VCS-controlled cherry picking at the same time, and I’d argue that this is where the DVCS niche lies. With a truly modular software architecture, you should be able to cherry-pick features from multiple development branches, on demand; the very nature of the modular architecture will ensure that conflicts are minimized. Furthermore, by the time you’ve invested the effort for a modular architecture, you don’t need software-controlled plug-ins; in effect, you’ve forced yourself to isolate and compartmentalize feature sets, which is what you need to do to reduce merge conflicts.
So, a modular architecture is just a generalization of good loose coupling of software components. There’s nothing inherent in this that requires a plug-in architecture or any other sort of software-driven cherry-picking. Once you have a modular architecture, you don’t need continuous integration, in the sense that Martin suggests.
Martin proposes that incomplete features can be “hidden” by simply hiding the UI that drives the features. This is often not possible, if the features are woven into the business logic of the tool – as is often the case where changes are made to existing features. The thing that bothers me the most is the concept of delivering half-baked, functionally untested code; it increases the opportunity for bugs, and eliminates the possibility of dropping features entirely. If a company develops feature A and then, at some point, decides to never deliver feature A (maybe the market has changed, perhaps some disruptive technology has rendered feature A obsolete), and that company has been doing continuous integration, then that feature is irrevocably interwoven into to the code base with numerous merges. The company is now in a position to spend significant resources un-weaving the feature, or be forced to deliver zombie code in their product. Again, this is solvable by sufficient isolation of the feature, but if you have that level of isolation, then why do you need continuous integration in the first place?
Cherry picking with the VCS can be powerful, and continuous integration should be used only where necessary. The key is that software absolutely must have a good, modular design, and if at all possible, architectural and interface changes should be continuously integrated. With VCS based cherry picking, organizations have the opportunity to decide to cut bait on a feature, and the overall code quality of released products will improve by the very fact that they don’t contain hidden, unused, and un-functionally-tested code. With VCS based cherry picking, organizations have the opportunity to decide to cut bait on a feature, and the overall code quality of released products will improve by the very fact that they don’t contain hidden, unused, and un-functionally-tested code.