Release your
software anytime
Feature Toggles
Alabe Duarte
@alabeduarte
Software Engineer
The need to
release
frequently
Competitive
Advantage
Accurate
Decisions
Continuous Delivery
https://electric-cloud.com/solutions/continuous-delivery/
Small
Releases
Risk
Reduction
Confidence
https://spotifylabscom.files.wordpress.com/2014/03/spotify-engineering-culture-part1.jpeg
Constraints....
The Starting
Point
Continuous Delivery - deployment pipeline
Commit
Stage
Acceptance
Test
Staging Production
Continuous Delivery != Continuous Deployment
Commit
Stage
Acceptance
Test
Staging Production
Commit
Stage
Acceptance
Test
Staging Production
Continuous Delivery
Continuous Deployment
MANUAL
AUTO
The software
has to work
Who practices CD?
Continuous
Delivery is a
journey
Tech
Process
People
Tech
✓ Deployment Pipeline
✓ Test coverage
✓ Automation
Process
✓ Communication
✓ Value driven
✓ Feedback loop
People
✓ Quality Mindset
✓ Team player
✓ Discipline
“Everybody has
responsibility for the
release process”
https://electric-cloud.com/solutions/continuous-delivery/
Feature
Toggles
(Flags/Switch/Flipping)
if (featureToggle.isOn) {
// display flash sale
// hide top downloaded games
} else {
// display top downloaded games
}
Situations where feature toggles may be applied
‱ White-labeled product
‱ Seasonal releases
‱ Experiment toggles
‱ Operational toggles
‱ Release toggles
White-labeled product
Seasonal Releases
Experimental toggles
http://growthmetricsco.com/ab-testing-your-shopping-cart-page/
Release toggles
fork
commit pull requestcommit
master
merge
Let’s say we have a team
A TEAM
fork
commit pull requestcommit
master
merge
fork
commit pull requestcommit merge
“Every commit must be
production ready, it may
be released to the
customer any time.”
fork
commit pull request
master
merge
fork
commit pull request merge
Release toggles (feature branches example)
Example
Feature #1
Heart Beating
Status
it('indicates that heart is beating', () => {
const dataIntervals = [
{ timestamp: '2017-03-16T06:00', signal: 1 },
{ timestamp: '2017-03-16T06:30', signal: 0 },
{ timestamp: '2017-03-16T07:00', signal: 1 },
];
expect(heartMonitor.getStatus(dataIntervals)).to.eql(HeartBeating);
});
it('indicates that heart has stopped beating when signal remains the same', () => {
const dataIntervals = [
{ timestamp: '2017-03-16T06:00', signal: 0 },
{ timestamp: '2017-03-16T06:30', signal: 0 },
{ timestamp: '2017-03-16T07:00', signal: 0 },
];
expect(heartMonitor.getStatus(dataIntervals)).to.eql(StoppedBeating);
});
class HeartMonitor {
getStatus (dataIntervals) {
const allSignals = dataIntervals.map( (data) => data.signal );
const flatLine = allSignals.every( (signal) => signal === 0 );
return flatLine ? STATUS.STOPPED_BEATING : STATUS.HEART_BEATING;
}
}
HeartMonitor
✓ indicates that heart has stopped beating when signal remains the same
✓ indicates that heart is beating
2 passing
Feature #2
Indicates Stop
Beating Status
when the line is
flat
Stopped Beating!
describe('HeartMonitor', () => {
const featureToggle = { stopBeatingWhenSignalRemainsTheSame: true };
const heartMonitor = new HeartMonitor(featureToggle);
it('indicates that heart is beating', () => {
// ...
expect(heartMonitor.getStatus(dataIntervals)).to.eql(HeartBeating);
});
it('indicates that heart has stopped beating when all signals are zero', () => {
// ...
expect(heartMonitor.getStatus(dataIntervals)).to.eql(StoppedBeating);
});
it('indicates that heart has stopped beating when signal remains the same', () => {
// ...
expect(heartMonitor.getStatus(dataIntervals)).to.eql(StoppedBeating);
});
describe('when toggle is OFF', () => {
const featureToggle = { stopBeatingWhenSignalRemainsTheSame: false };
const heartMonitor = new HeartMonitor(featureToggle);
it('indicates that heart is beating when non zero signals remain the same', () => {
// ...
expect(heartMonitor.getStatus(dataIntervals)).to.eql(HeartBeating);
});
});
// ...
class HeartMonitor {
constructor(featureToggle) {
this.featureToggle = featureToggle;
}
getStatus (dataIntervals) {
const flatLine = this.isFlatLine(dataIntervals);
return flatLine ? STATUS.STOPPED_BEATING : STATUS.HEART_BEATING;
}
isFlatLine (dataIntervals) {
const allSignals = dataIntervals.map( (data) => data.signal );
return allSignals.every( (signal) => {
return this.featureToggle.stopBeatingWhenSignalRemainsTheSame ?
signal === allSignals[0] : signal === 0;
});
}
}
HeartMonitor
✓ indicates that heart is beating
✓ indicates that heart is beating when non zero signals remain the same
✓ indicates that heart has stopped beating when signal remains the same
when toggle is OFF
✓ indicates that heart is beating when non zero signals remain the same
✓ indicates that heart has stopped beating when all signals are zero
4 passing
Visualising flag statuses
http://blog.launchdarkly.com/launched-flag-status-indicators/
Toggle recycling
Pragmateam/feature-toggles
github.com
Stability
&
Flexibility
open/close
principle from
S.O.L.I.D
Branch by Abstraction
A B
F
C
Branch by Abstraction
A B
F
C
F’
Branch by Abstraction
A B C
F’
F F
Branch by Abstraction
A B C
F’
F F
Branch by Abstraction
A B C
F’
F
https://www.greenbird.com/2016/09/02/microservices-hitting-the-brick-wall-once-again/
Microservices
Microservices - Serverless Architecture
https://softwareengineeringdaily.com/2016/08/23/serverless-architecture-with-mike-roberts/
Microservices - Event Driven Architecture
https://dzone.com/articles/publish-subscribe-pubsub-taken-to-the-next-level-w
“The art of
destroying
Software”
by Greg Young
Wrapping up
Don’t let your
team down
Be aware of
your boundaries
Small
Releases
Release
Frequently
➔ https://continuousdelivery.com/
➔ http://continuous-delivery.co.uk/
➔ https://pragprog.com/book/mnee/release-it
➔ https://martinfowler.com/articles/feature-toggles.html
➔ https://martinfowler.com/bliki/BranchByAbstraction.html
References
https://goo.gl/VJEbQ3
#PragmaThanks

Release your software anytime - feature toggles