You can work on features and architecture changes that take months to finish, yet still release your code every day. You accomplish this with "feature switches" that hide new features.
Feature switches can go directly into your code as IF statements that detect the type of user or system running the code. Typically, they have four states:
Hidden: Nobody sees the feature.
Test: Only internal testers on internal test systems see the feature.
Beta: Beta test users and systems see the feature.
Full release or "Unveil": Everyone sees the feature.
The "Unveil" is the big event, the final release. Hooray! It is the definition of done.
The unveil technique is what allows us to unblock. Developers can build and release hidden features without waiting for product owners (or story owners, or product managers, or the CEO) to approve a release. Your design team can do usability testing with beta users. The unveil can be scheduled when the product owner, marketing team, and everyone else is ready, long after the developers have moved on to other tasks.
Everyone does it
Web application developers often use feature switches to turn on features for specific types of users or user accounts.
Assembla employees usually find themselves running beta features not yet unveiled to customers.
A bank developer told me that when he puts his card into an ATM, he gets a menu with new beta test choices not shown to regular account holders.
Hardware vendors often leave empty sockets in their computers, phones and other devices that can be filled later with new components. Semiconductor companies leave space on chips, or even complete circuits that are switched off.
Software installed locally on clients and servers sometimes has hidden features that can be unlocked by special keys, either when a new feature is fully tested or when the customer pays an upgrade fee. Developers of client and mobile apps can expose new services to particular user types.
Wherever you find rapid development, you will find feature switches.
No long-running feature branches
Today, contributors sometimes keep many changes in an isolated version of the code and then merge and release all of them at once. They do this to avoid the interruptions that would come from users seeing and reacting to each change individually.
This results in the dreaded Long-Running Feature Branch. The Long-Running Feature Branch allows the contributor to work undisturbed and make many changes without interruption. However, it creates serious problems. While your contributor is working, you can't easily see his work and manage or help him. When he merges the changes back into the main version, it creates a lot of bugs. Often the merge itself requires a lot of manual labor to interweave changes that were made during the Long Run. It's hard to find and fix bugs because you have so much new code to look through.
If you use feature switches, you can eliminate Long-Running Feature Branches.
Advantages of switches
After you add switches you can take frequent small changes from every contributor. There will be fewer bugs in each contribution, and the bugs are much easier to find because you have less new code to look through.
Contributor work is visible and measurable. You never wonder why someone disappeared for a month.
Deployment and the test infrastructure can be simplified. You don't need a special deployment of a branch version for "beta.myproduct.com" or a special download. Features can be turned on for specific test, beta, or release installations, or for specific users.
Unblock! Developers can release features without being blocked by testers or product management. They can work and release at full speed by hiding new features, letting the other groups unveil features after test, marketing and other issues are addressed.
Features can be deployed incrementally. You can deploy significant changes to data structure and infrastructure bit by bit, testing changes and receiving feedback at a controlled pace.
The final "unveil" release is much less stressful and more reliable, because new features have been integrated, tested, and deployed (for some audiences) for some time before the unveil.
Life of a switch
Setup: You will need a few <condition> functions which tell you about deployment configurations and user accounts, so you can control who sees your feature.
Install: Put your switches into the menu or top service level, so you don't have to scatter them deeper in the code. You should be able to run unit tests without hitting the switches. Use a switch at the same level with a matching IF NOT <condition> to switch off the old feature when the time comes.
Overlap: You can deploy both versions, and possibly run automated tests for both versions. You can incrementally deploy changes to data structure and infrastructure as well as features. With experience, you can run both versions of your feature, data structure, or architecture. This seems complicated, but in most cases it is simpler and less stressful than releasing many new features to everyone in a big bang.
In fact, by allowing new and old features to overlap in one set of code you can answer the classic question "how do you change the engines while the plane is flying?"
Unveil: When everyone is happy, you turn on the feature for all audiences and unveil.
Remove: After new features have been unveiled to everyone, reduce the number of lines of maintained code by deleting the switches and obsolete code.
When you use feature switches there is a little bit of extra work to add the switches, test two versions of the code during the overlap period, and remove the switches. However, on balance you save work because your developers are unblocked and because the release is fully tested and deployed before you unveil.