When I have to have WIP that’s live in production, I pretty much have to use all the approaches for side-by-side development.
In some recent muses, we’ve talked about "in situ" vs "side-by-side" approaches to changing code. First, let’s refresh our concepts for these two phrases. In both cases, we have a bunch of code A, and we wish we had a bunch of code B. B might incorporate all of A, or it might be more like A’, or it might be something else altogether.
In the "in situ" approach, we do this by just changing A right on the spot, until it’s not A anymore, it’s just B, and we push it. I half-joked in the earlier thread, this is every noob’s first response to every change-problem. But in situ has its uses. In situ work is most often used for things that are very modest changes. We use it a lot for small bugs or small improvements. A new guard clause. A degenerate case we hadn’t thought of before. An additional term in a calculation. Sorting results.
The advantage to in situ work comes almost entirely from the fact that it is small. We really can — anyway we believed we could when we started — change a few lines of code and get exactly what we want. So we roll the test, it’s red, we make the change, it’s green, we push. Sadly, some changes are bigger than your head. (That’s a B. Kliban allusion.) When you’re an old hand, you can often see these at a glance. When you’re not, or when the codebase is poorly factored, you discover it in the middle of your try at the in-situ approach.
(What you’re discovering is usually a tacit dependency, and one way you can solve these is to throw away your in-situ, and try another in-situ that addresses that change. Rinse, lather, repeat.) Some changes are so big they’re gonna take you more than a session. Enter the "side-by-side" approach. In this approach, instead of morphing A to B, you just implement B right next to A. Later, when you’re satisfied, you’ll "turn off" A and "turn on" B.
The big advantage of side-by-side: you get to take your time, test B adequately, prove it adequately, and share it with a select group of victims while you’re doing it. The select group of victims is of course everyone else on your team. 🙂 We want them to have your new B asap. They will help you (irritatedly) make sure it really replaces A.
So, with that monstrously long intro, let’s consider some of the side-by-side techniques we might have to use.
First, we have to decide how/when to turn it on. There’s usually "levels" to this. 1) Turn it on on my box and my box only. 2) Turn it on for all the team. 3) Turn it on for everyone worldwide catapulting you to immediate fame or shame.
The techniques for actually doing this need to be a) simple and b) removable. We need simple because we’ve all got a lot on our mind. We need removable because all of those techniques add clutter that we want to dispense with as soon as possible.
My most common approach, two command-line flags, one that all developers have on all the time (level 2), and one that only I have on (level 1). You can use any of the standard ways to do this. The big key, though: decide once at the beginning. Once. And doing that opens you to your first real side-by-side technique: some permutation of Strategy, Factory, and possibly AbstractFactory.
Here’s what you are trying to avoid: testing that flag a thousand times during a run. The simplest way to do that: use a pair of concrete Strategy classes, StrategyA or StrategyB, use the flag at the beginning to make the right one. Now clients can call it all blind. That’s sweet when it works, but some changes have to happen in many different places.
The next step back in complexity is to create at the beginning, rather than a Strategy, a Factory, to make the strategies whenever you want. You can parameterize the factory, or you can make it an abstractfactory. AbstractFactory is especially useful when, to implement B, you not only have to make ThisThingB’s, but you have to make ThatThingB’s and TheOtherThingB’s. That is, if some part of the code works with B, then some other part has to be prepared to deal with B, too.
All of this, you can see, is complicated. I told you to keep stories to one day, dint I? I told you. Most one-day stories I can do most parts in-situ. That’s why I like them so much. There’s a couple of hacks in UI settings, by the way, that come up so often they’re worth calling out, and then we’ll stop here.
Broadly speaking, in UI we "stop-at-the-top". If B isn’t ready for prime-time, don’t let the UI ever even see B unless /developer is set. A lot of changes come down to selecting a type, via a radio/combo thing. If the /develop flag isn’t there, don’t put the types for B in that thing. Simple. You can do the same with menu options.
Some changes amount to a whole re-working of the UI. When that happens, I usually use my UI-tool to introduce a new tabpane. The app always shows the A tab in the pane, and only puts the B tab in the pane when /developer is set. Some changes stretch across transport mechanisms. This is why we put version info in transport protocols.
Most of my teams do some kind of JSON transport. The key: make every JSON structure that can be trasnported independently carry a version. Make every request carry a requested version. If you’ve done this, crossing the gap is straightforward. There are a couple more articles on the blog that might help you with side-by-side stuff.
Was that abstract and complicated and vague and hard-to-grasp enough for you? It was for me.
Look. This is nasty advanced geekery. It requires judgment, confidence, experience, and nuance. It is hard.
Don’t do it unless you’re sure you have to.
Have you really tried first to split it? I mean, really. Have you tried splitting it with all your best minds in the room? Have you tried splitting it by rubber-ducking? Have you stood at a whiteboard for an hour?
This is not a cost you want to volunteer to pay.
That’s it for now. For my next trick, watch me pull a rabbit out of this hat: "What are clever ways to split stories so they fit in a day?"
That’s not today. It’s a Sunday afternoon, I got some light dayjob work to do, and I’m hoping for a mellow evening, for you and me both!