Merging is HARD WORKSometimes impossible for git/svn to auto-mergemasterfeature Afeature BBOOM!
MeclassFooServiceinterfaceFooServiceclassDefaultFooServiceclassCachingFooServicechanged class to interfaceOther devclassFooService● altered a bunch of existing methods● added a bunch of new methodsBOOM!Real life example (happened last week)Took over an hour to merge manually
Branch by AbstractionThe name is misleading...Using B by A, we DONT BRANCH!NO BRANCHES == No MERGING
Branch by Abstraction● All dev is done on master● Incomplete work is disabled using feature flags● master is always stable, ready for rollout● Changes performed by introducing abstraction
Making a change using B by A1. Add abstraction layer around the code you want tochange. (Extract interfaces, etc.)2. Add the new implementation, but keep using theold implementation in production.3. Flip the switch! (Update flags, switch Guice modules, etc.)4. Remove old implementation if no longer needed
Example: Switching to a new auth API1. Refactor concrete class LoginService intointerface + impl classclassLoginServiceinterfaceLoginServiceclassLegacyLoginServiceUpdate surrounding code to use LegacyLoginService(Maybe add a factory to provide the implementation?)
Example: Switching to a new auth API2. Add new implementation (+ unit tests, of course!)interfaceLoginServiceclassLegacyLoginServiceAdd feature flag to allow switching between implementations intest environmentinterfaceLoginServiceclassLegacyLoginServiceclassNewLoginService
Example: Switching to a new auth API3. Flip the switch!Update the value of the feature flag in production
Example: Switching to a new auth API4. Remove old implementationinterfaceLoginServiceclassLegacyLoginServiceinterfaceLoginServiceclassDefaultLoginServiceclassNewLoginServiceRefactor (change class names, etc.) if necessary
Example: Switching to a new auth APIFinished!Remember:● All this happened on master● Codebase was stable throughout the process● Both new and old impls were subject to CI● No merging!
Branch by Abstraction: Prerequisites● Reasonably good, modular codebase○ Easy to introduce abstractions● Good devs!○ Can be trusted not to break the build● A good suite of unit tests● A feature flag system○ Ideally, well-integrated with toolchain○ e.g. enable features using checkboxes in Jenkins