Spring, Summer, Winter and Fall
[[ Yes, it’s Violent Femmes Reference Time again! ]] I’ve gone and set up some Mercurial repositories and clones and whatnot now, some of which are publicly accessible, some which are local to my workstation, and somewhat to my surprise I can see the season’s cycle [[ XTC reference time! ]] that Aaron, Dirk and Sebas talked about show up in a fairly natural fashion. And I’ve come up with another mixed metaphor, that development life is a highway [[ Tom Petty? ]] and you can ride it all night long, but there must be some way to get out .. nah. I’ll just explain later.
💔
The top three repositories are publicly accessible. Master is the gold standard, the released stuff, the this-is-totally-stable-and-usable repository. Staging pulls from Master and is the beta-and-release-candidate repository, where things end up that are probably releasable; this is stable for enthusiast users to follow and is where the developers coordinate and polish before things get into master. Then there’s Devel, which pulls from Staging and which is where alpha-development happens. Here, things may – but shouldn’t, unless you want to score a dozen turds or more – break and things can change or be backed out or reconsidered. Developers should be watching this.
In my setup, Devel is publicly anonymously world-writable. I made that choice consciously because I want to make it possible for anyone to contrbute patches in a straightforward way. Consider Devel a playground, if you will. It’s possible that Devel gets abused and that the clone is thrown away and re-cloned from Staging; it depends on how things turn out in practice. Right now I’m still in “do not assume the worst” mode. Staging, on the other hand, is writable for a few and then Master is writable for a select few. I suppose I could have labeled this “Linus”, “Lieutenants”, “Development Communities” to get the same across for those aware of how Linux kernel development works.
Down on the bottom row, there are the local repositories, not public, not accessible from outside my local workstation. Let’s go from right to left: Local Devel is a whole forest of repositories for feature development, bugfixing, documentation and what have you. I need to remember that cloning is cheap and you should clone for each line (coherent thought expressed as a sequence of patches or changes) of development instead of trying to juggle multiple lines of effort in one repo. That’s probably the biggest change for my personal style of working and one that already suggests itself as highly convenient in the long run. But change is an effort.
Right, so we have Local Devel where stuff happens; this is where commits might be the most frequent and there might be multiple concurrent lines of development going on. Local Devel tries to stay in sync with Devel (the public one) and may publish results to Devel as well for review by other developers. Changes move from Local Devel via Devel to Local Staging for quality checking by me (since this is local to my machine). If I think it’s OK, then I dare to push it out to the public Staging; similarly changes propagate from Local Staging through public scrutiny to Local Master for a final check before being pushed to the global Master.
Looking at the diagram in another dimension, we have the rightmost column which is most active and where most of the development and experimentation occurs; the center column where stabilization occurs and the leftmost column where, basically, release happens.
This ties in with our seasons metaphor; Local Devel is spring, where a thousand features bloom in a thousand repositories. They grow and mature in the summer, where they bask in the warmth of the sun and the glare of curious and critical eyes – that’s the public Devel. Then they reach fruition at the end of summer and the beginning of autumn; growth slows and the fruits of our labor become available to all. Finally, winter sets in and preserves and freezes what once was a tender tendril of code but is now a full grown feature.
Hm. I’m not sure that the “winter” metaphor works all that well; things are completed but not unchanging or hibernating.
And anyway, we need to remember that if it’s summer here it’s August in Greece (and nothing every gets done in August in Greece, it’s far too hot) so we have the different seasons happening at the same time. I’ve never been to the southern hemisphere so I don’t really know what that’s like. It also strikes me that the metaphor, agricultural as it is, needs a little work to handle cultural contexts like Calgary where the growing season is just a tad under 180 days – that’s less than half the year and the rest is hard-frozen winter stillness. Really Aaron, you should be used to freezes taking up half your time.
So at this point it looks like a four seasons [[ Vivaldi reference! I knew you were waiting for that one. ]] metaphor makes a fair amount of sense in that it reflects naturally a division of public (stuff you feel is less-or-more done) and private (spring, where you sow your wild oats) as well as changes in maturity of the codebase.
Part of the process of working with a DVCS is merging and pushing between repositories; the interesting merges in this little diagram are the diagonal ones, where a decision needs to be made about moving a feature or group of patches from one season to the next. It’s like growing up from the Farm Leagues, and there need to be scouts watching what’s happening and tryouts and testing and then thumbs up to the move. Gatekeepers or a release team play a big role in doing exactly these diagonal pulls and there ought to be a succinct question that needs to be answered positively in order to move from Devel to Staging and from Staging to Master. Something like “can I rely on this as a developer for the next three months?” and “can I rely on this as a user in a binary compatible fashion for the next two years?” comes to mind, but that is kind of library-and-infrastructure oriented.
If pulling stuff between repos and maturing chunks of code like fine cheese is easier with a DVCS, it introduces a new kind of discipline that is needed to work successfully in getting code to Master and it requires new processes and people to watch over those processes. Someone has to make the call that some bit of code is good; is it done? Is it ripe? And if it is ripe, is it a Limburger cheese, or a fine Cheddar?
There is another way of looking at this development model – here focussing on a single repo, which is a single coherent unit of software (I don’t think a single repo like we use now for all of KDE is feasible at all) – is as a highway. Code hits the off-ramp and goes out into the wide world. It’s done with the highway. It is released. It only does that when it’s done, though, when it’s good and ready. The rightmost lane is for code looking for an exit. There’s a center lane for passing and doing the speed limit, and then there’s a left lane where Muttley gets to drive like a maniac. On this highway, all the on ramps enter on the left – road safety isn’t all that important to Dirk Dastardly, after all. Moving to the right [[ yes, Paul Adams, I am roundly discriminating against your ridiculous driving habits ]] means slowing down, driving more calmly, cooperating with other drivers more. You can’t be a maniac and on an off ramp at the same time. You have to trade in your sports car for a station wagon.
I think that if you plot that repositories diagram over time with each repo as a lane of traffic and each coherent chunk of code as a vehicle, you’ll find that it does look like the traffic situation. Merge right, slow down (the rate of change).
What’s missing in all of these views of the development process is a metaphor for understanding how dependencies across repositories work. When developing your application KFrobnitz you depend on other applications for DBus interfaces and on libraries and frameworks elsewhere. For you as a developer, KFrobnitz is in spring, in the fast lane. But for the things you depend on like the KDE workspace or KDE runtime (those are product names) or kdelibs (currently an SVN module) should you be looking for them in spring, summer, winter or fall? Spring doesn’t make much sense – even if it is publicly available. Too wild, too woolly. I think a rule of thumb would be:<ul><li>If your app pushes the limits of what it depends on and might drive development there, use summer / the center lane.</li><li>If your app is intended for use on the next release of what it depends on, use fall / the right lane.</li><li>If your app continues to develop features for the released version of your dependency, use winter / what’s gone down the off-ramp.</li></ul>You can ask that question for each of your dependencies and thus pick the right set of things to build on. Now, if you’re working somewhere lower in the stack like on libraries you might be concerned about breaking applications higher in the stack. So there you pick winter or fall versions of applications you care about or which are representative and build those against your spring as a check that you’re not breaking stuff.
I think the message is that in any one software development environment (by which I mean the whole stack that you are building) you should avoid having spring in more than one place. No Wacky Races between repositories; only one should be going fast while the rest chug along. That way software productivity (not just DVCS based) lies.
The diagram of repositories was not archived by the Wayback Machine, and is marked with a 💔.