See post 1
So, we made some software for a client. We finished phase 1 and they asked us to begin phase 2, while they integrate phase 1 with their wider systems and go live with it.
Then they started asking for numerous changes to phase 1, which we did by branching the repository, doing each change in phase 1 branch and merging it into phase 2 branch. But the things they're asking for in their production version are becoming increasingly complicated and therefore difficult to merge.
So from now on I'm going to add a config flag called 'enablePhase2' which switches between phase 1 and the unfinished phase 2 at runtime. This way we can do everything in the trunk and can make changes either to their 'in production' version (phase 1) or to the cutting edge new phase 2 functionality. When we make them a release they can deploy it in production in phase 1 mode or test our latest phase 2 features by changing the config file.
I'm hoping this will make things easier. Just wondering if anyone else has used such a technique to manage development of multiple versions concurrently and has any insights
"Did you branch your repository?"
"No, it's just the way I'm standing"
Is there any chance you can tell them to wait for v2 for the more complicated stuff?
Unless you are very careful/lucky/clever, my concern would be that over time as different behaviours accumulate there will be a tendency towards increasing complexity in the code and both dev and support will become increasingly difficult.
Then they started asking for numerous changes to phase 1, which we did by branching the repository, doing each change in phase 1 branch and merging it into phase 2 branch. But the things they're asking for in their production version are becoming increasingly complicated and therefore difficult to merge.
I have no useful suggestions to offer. I'm just popping by to say that this sounds very much like my ex's experience in the NHS IT programme. Implementations were often held up by constantly changing requirements from the client. This, and meetings with no conclusion beyond the next meeting, ate up huge amounts of time.
Is there any chance you can tell them to wait for v2 for the more complicated stuff?
Unfortunately not, well we could but we prefer to give people what they want, which right now is new features in the version that is in production.
I have no problem with evolving requirements, its a smallish project in which we can get stuff done fast and generally its fun to work on.
I'm just not used to working concurrently on multiple versions. Just since starting the thread I've managed to make it so that I can flip between versions by setting a flag so I'm hopeful that this is the right way forward
Feature flags was the standard approach at our place to this kind of issue when we did have multiple teams (several dozen) working a single monolithic codebase, to allow teams to add and test complexity while maintaining a single live branch. It's all about micro services now as we try to get away from that architecture, but for a small team on a relatively small project I think you are on the right lines.
I have no useful suggestions to offer
Make a bad Carry On style joke, then, ffs!
Feature flags. That's a good name for what I'm doing.
So far its mostly just taking buttons off the ribbon and making certain things non-editable in phase 1.
If we start needing more than one of such flag or finding it's value being checked in more complicated places that's when I will start to worry
It's a fairly standard technique and there's plenty of best-practice literature out there. As you say, it should be used to avoid complexity, as soon as it becomes a source of complexity itself you may need to re-think.
Main thing is to encapsulate all the feature flags into a clean feature flags API so it's clear to find all the places each one has been used
It's not uncommon for such flags to become redundant, and it's easy for them to go zombie.
Dead, but still lurking in the landscape and killing things.
Where is for actual version separation though, that almost feels more like a case for a set of global constants and conditional compilation rather than runtime decisions.
Make a bad Carry On style joke, then, ffs!
Oooh Matron - the TFT screens!