View
6.004
Download
0
Category
Preview:
DESCRIPTION
A look at some of the problems introduced by feature branches, and a short introduction to using Branch by Abstraction as an alternative.
Citation preview
Branching Strategies
Chris Birchall
2013/06/21#m3_dev
Branching strategies
Feature Branchesvs
Branch By Abstraction
Feature Branches
● master branch is used for rollouts
● Little work done directly on master
● For every feature/bugfix, cut a branch
● To rollout a feature, merge to master
master
feature A
feature B
Feature Branches: Problems
Merging is HARD WORK
Merging is HARD WORK
Sometimes impossible for git/svn to auto-merge
master
feature A
feature B
BOOM!
Me
class FooService
interface FooService
classDefaultFooService
classCachingFooService
changed class to interface
Other dev
class FooService
● altered a bunch of existing methods
● added a bunch of new methods
BOOM!
Real life example (happened last week)
Took over an hour to merge manually
Feature Branches: Problems
Merging is SCARY
Merging is SCARY
Do you trust your tools to merge correctly?
Have had problems with buggy tools (e.g. git-svn)
Feature Branches: Problems
Merging is A CHANGE
to the codebase
Merging is A CHANGE to the codebase
Merging counts as a change to the codebase
→ Need to perform manual tests before rollout
End up doing same tests before and after merge
Feature Branches: Problems
Feature branches are not
subject to CI
Feature branches are not subject to CI
Jenkins is only working against master
Manually creating a job per feature branch is silly
Can automate it, but it's complicated and brittle
Feature Branches: Problems
Feature branches go ROGUE
Feature branches go ROGUE
Branch can diverge massively from master
Becomes impossible to merge safely
Branch lives for weeks, months, ...
A solution?
Branch by Abstraction
Branch by Abstraction
The name is misleading...
Using B by A, we DON'T 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 A
1. Add abstraction layer around the code you want to
change. (Extract interfaces, etc.)
2. Add the new implementation, but keep using the
old 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 API
1. Refactor concrete class LoginService into interface + impl class
class LoginService
interface LoginService
classLegacyLoginServic
e
Update surrounding code to use LegacyLoginService
(Maybe add a factory to provide the implementation?)
Example: Switching to a new auth API
2. Add new implementation (+ unit tests, of course!)
interface LoginService
classLegacyLoginServic
e
Add feature flag to allow switching between implementations in
test environment
interface LoginService
classLegacyLoginServic
e
classNewLoginService
Example: Switching to a new auth API
3. Flip the switch!
Update the value of the feature flag in production
Example: Switching to a new auth API
4. Remove old implementation
interface LoginService
classLegacyLoginServic
e
interface LoginService
classDefaultLoginServic
e
classNewLoginService
Refactor (change class names, etc.) if necessary
Example: Switching to a new auth API
Finished!
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
Thank you!
Further reading:
http://paulhammant.com/blog/branch_by_abstraction.html/
Recommended