Branch by Abstraction is a set-piece technique to effect a ‘longer to complete’ change in the trunk. Say a developer (or a pair of developers), has a change that is going to take five days to complete. There could easily be pressure to create a branch for this - somewhere that can be unstable for a period of time before it completes (and gets merged back somewhere).
抽象分支是一组影响主干中“以后完成”这类变化的一系列技术。比如有一个（或一组）开发人员，需要5天的时间完成一个修改。创建一个分支很容易有压力 - 某个地方在完成前会有一段时间不太稳定（后面再合并回来）。
There may be some aspect of repetition to the coding activities that makes it longer to complete. No matter, the change was predicted as being time-consuming, complex, destabilizing/disruptive to everyone else in the development team. 可能有某些方面的重复使得编码需要更长时间才能完成。无论如何，对开发团队里的每个人来说，修改都被认为是耗时复杂的，且具有破坏性/颠覆性。
- There are also a lot of developers already depending on the code that is subject of the ‘longer to complete’ change, and we do not want them to be slowed down in any way. 有很多开发人员已经依赖于需要较长时间才能完成修改的代码，我们不希望以任何方式延缓他们的开发。
- No commit pushed to the shared repository should jeopardize the ability to go live.
For simplicity’s sake, let us say there is code that is ‘to be replaced’, code ‘to be introduced’.
- Introduce an abstraction around the code that is to be replaced, and commit that for all to see. If needed, this
can take multiple commits. None of those are allowed to break the build, and all of them could be pushed to the shared
repository in order, and as done.
- Write a second implementation of the abstraction for the to-be-introduced code, and commit that, but maybe as
‘turned off’ within the trunk so that other developers are not depending on it yet. If needed, this can take multiple
commits as above. The abstraction from #1 may also be occasionally tweaked, but must follow the same rule - do not
break the build.
- Flip the software ‘off’ switch to ‘on’ for the rest of the team, and commit/push that.
- Remove the to-be-replaced implementation
- Remove the abstraction
Hopefully, your team uses an IDE that can perform complex refactorings on sets on checkouts, in a way that running the build after each is an uneventful validation of the refactorings. 你的团队有望使用IDE来做复杂的重构，在某种程度上，在每次后运行build是重构的静态验证。
Let’s talk about a car having its wheels upgraded. We should never forget that software engineering is nothing like conventional construction, and we want to ram that home. At least, it is nothing like conventional construction where we are not talking about a production line.
让我们来谈谈轮子升级的一辆汽车，我们不应该忘记软件工程并不像传统的建筑，我们希望ram that home。至少它不像传统建筑，在那我们并不会谈到生产线。
- Mechanics must be able to simultaneously work on the upholstery, engine, etc.
- The car must be drivable after every change.
All steps are efficiently performed raised up on car jacks/lifts/ramps, before lowering the car to the ground again. 在汽车再次降低到地面之前，所有的步骤都有效地在汽车千斤顶/举起/斜坡执行升高
- One wheel is removed, put in a container that looks pretty much like a wheel (rotates around an axis,
can bear weight) and replaced on the car. If driven this wheel functions exactly like the
other three wheels.
- The wheel-like container gains a second better/desired/alternate wheel, within exactly the same
physical space (magically). A switch is added inside the car to allow the choice of wheel to be switched conveniently perhaps only before the engine is started, though.
- The same two operations (#1 and #2) are performed on the other three wheels. Or maybe #1 is done four times,
followed by #2 four times. The Mechanics experience will guide which is most efficient.
- After determining that the new wheels are better, the old wheels are removed from the wheel-like containers and are send for recycling.
- The wheel-like containers are also removed from the new wheels, either one by one or all four simultaneously. 车轮状的容器也从新车轮那取出，可以一个一个取，也可以四个同时取出。
At any stage, when lowered from the jacks/lift/ramps, the car could have been driven (a ‘ready to go-live’ metaphor).
在任何阶段，当从下降时，汽车可以一直发动（比喻ready to go-live）。
We said ‘jacks’ above, because that’s what mechanics use in real life. Software, however, does not follow the rules
of gravity, or many of the costs of actual construction. With an IDE for a glove, a single finger could reposition
the car in 3D space to allow easy replacement of the wheels.
A documented case is ThoughtWorks’ Go CI-daemon. They changed an Object-Relational mapping library (for persistence), while not slowing down teammates development activities (rule 1), and not jeopardizing the ability to go live (rule 2). 一个记录的案例是ThoughtWorks的Go CI-daemon。他们改变了一个对象关系映射库（用于持久化），而不是减慢队友开发活动（规则1），而不会危及生存能力（规则2）。 Going from “iBatis” to “Hibernate” for a bunch of reasons, was their plan. 出于一系列原因，他们的计划是从“iBatis”到“Hibernate”。
- Introduced an abstraction around the classes/components using iBatis directly, and ensured that all
classes/components indirectly referring to iBatis were changed to refer to the abstraction instead.
- Wrote a second implementation of the abstraction, introducing Hibernate to the codebase, perhaps tweaking the
abstraction where needed.
- Did a tiny commit that turned on Hibernate for all teammates.
- Removed iBatis, then the abstraction and the on/off old/new switch.
As it happens you could leave the abstraction in place, if your unit tests are able to benefit because of the
possibility of another seam that can be mocked.
Cheaply pause and resume ‘migrations’
The migration from old to new can be paused and resumed later casually. This is because the build guards the second, incomplete, implementation. It does so merely because of a compile stage that turns the abstraction and somewhere between 1 to 2 implementation into object code. If there are unit tests for the two alternates, then even more so.
If on a real branch, the casual restart of the paused initiative is missing. There’s possibly an exponential cost of restart given the elapsed time since the initiative was paused.
Pause and resume is much more likely in an enterprise development organization that does not have limitless coffers.
Cancellation of a project is still cheap
项目的取消依然方便 In the case of abandonment, deleting a real long running feature branch is cheaper, but deletion of a branch by abstraction thing is only incrementally more expensive. 在放弃的情况下，删除一个真正的长时间运行的功能分支是更方便的，但是通过抽象层* thing *删除分支只是递增地更昂贵。
Not a panacea
Branch by Abstraction does not suit all ‘change’ situations.
One is when you have got to support old APIs and previous releases for more than a short period of time. I.e. when your dependent customers (or detached clients apps) can choose their own upgrade moment.
Some years ago the KDE team was mulling their release 5.0 strategy, and wanting to remain parallel to changes in 4.0, so as not to make
mistakes that they had done
previously. TODO: circle back.
Teams employed Branch by Abstraction many years before it got its name (Stacy Curl named it in 2007), but it is unknown when the first implementation was. Before the adoption of BbA, teams had to make a branch for the big lengthy disruptive change, or do it with an incredible amount of choreography: “hey everyone, take a week of vacation now”.
With the Branch by Abstraction technique, Trunk-Based Development was less likely to be temporarily or permanently
abandoned for a multi-branch model.
|26 Apr 2007, Blog Entry|
|Introducing Branch by Abstraction|
|05 May 2011, ContinuousDelivery.com article|
|Make Large Scale Changes Incrementally with Branch By Abstraction|
|21 Jun 2013, Blog Entry|
|Branching Strategies: Feature Branches vs Branch by Abstraction|
|14 Oct 2013, Blog entry|
|Application Pattern: Verify Branch By Abstraction|
|07 Jan 2014, MartinFowler.com article|