feature flags are flawed: let's make them better

34
FEATURE FLAGS ARE FLAWED LET'S MAKE THEM BETTER Created by Stephen Young / @young_steveo

Upload: stephen-young

Post on 17-Jan-2017

189 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Feature Flags Are Flawed: Let's Make Them Better

FEATURE FLAGS ARE FLAWED

LET'S MAKE THEM BETTERCreated by Stephen Young / @young_steveo

Page 2: Feature Flags Are Flawed: Let's Make Them Better
Page 3: Feature Flags Are Flawed: Let's Make Them Better

FEATURE FLAG?I've seen a lot of names for this concept tossed

around: feature bits, �ags, �ippers, switchesand the like. There seems no generally

accepted name yet.

— Martin Fowler

Page 4: Feature Flags Are Flawed: Let's Make Them Better

SIMPLE TOGGLEclass AmazingRecipe { public function getSauce() {

$useNewRecipe = false;

// $useNewRecipe = true;

if ($useNewRecipe) { // new formula here } else { // original code here } } }

Page 5: Feature Flags Are Flawed: Let's Make Them Better

TRADITIONALFEATURE FLAGS ARE…

FLAWED...ACTUALLY PRETTY USEFUL AND NOT REALLY FLAWED PER SE, BUT THEY COME WITH A FEW

CHALLENGES AND I THINK WE CAN IMPROVE THE MODEL, SO

LET'S MAKE THEM BETTER

Page 6: Feature Flags Are Flawed: Let's Make Them Better

SIMPLE TOGGLEclass AmazingRecipe { public function getSauce() { $useNewRecipe = false; // $useNewRecipe = true;

if ($useNewRecipe) { // new formula here } else { // original code here } } }

❌❌

Not Testable

Page 7: Feature Flags Are Flawed: Let's Make Them Better

SIMPLE TOGGLE V2class AmazingRecipe { public function getSauce() { if ($this->useNewRecipe()) { // new formula here } else { // original code here } } public function useNewRecipe() { return false; // true } }

Can Be Stubbed

Page 8: Feature Flags Are Flawed: Let's Make Them Better

MOCK TOGGLE/** * @dataProvider newFormulaProvider */ public function testGetSauce($useNew, $sauce) { $sut = $this->getMock('AmazingRecipe', ['useNewRecipe']); $sut->expects($this->once()) ->method('useNewRecipe') ->will($this->returnValue($useNew)); $this->assertEquals($sauce, $sut->getSauce()); }

public function newFormulaProvider() { return [ [ false, 'old Recipe' ], [ true, 'new Recipe' ] ]; }

Page 9: Feature Flags Are Flawed: Let's Make Them Better

SIMPLE TOGGLE V2class AmazingRecipe { public function getSauce() { if ($this->useNewRecipe()) { // new formula here } else { // original code here } } public function useNewRecipe() { return false; // true } }

❌❌❌

Not MaintainableNot Con�gurableNot My Concern

Page 10: Feature Flags Are Flawed: Let's Make Them Better

FEATURE ROUTERclass AmazingRecipe { public function getSauce() { if ($this->useNewRecipe()) { // new formula here } else { // original code here } } public function useNewRecipe() { return Flags::enabled('AmazingRecipie.NewSauceFormula'); } }

Page 11: Feature Flags Are Flawed: Let's Make Them Better

FEATURE ROUTERfinal class Flags { protected static $map = []; public static function enabled($key) { if (empty(static::$map)) { // hydrate map } return !empty(static::$map[$key]); } }

Page 12: Feature Flags Are Flawed: Let's Make Them Better

TRADITIONAL FEATURE FLAG SYSTEMCurb Long-Lived Feature Branches

Easy To Use (If This Then That)

Testable

Tons of Applications

Continuous DeliveryTimed ReleasesOperations Toggles

Page 13: Feature Flags Are Flawed: Let's Make Them Better

WHAT'S NOT TO LIKE?

Page 14: Feature Flags Are Flawed: Let's Make Them Better

CYCLOMATIC COMPLEXITYpublic function getSauce() { if ($this->useNewRecipe()) { if ($this->testSpicyVersion()) { // add spice } if ($this->fixEnabled()) { // fix bug in new code } } else { // original code here if ($this->fixEnabled()) { // fix bug in old code } } }

Complexity: 5

Page 15: Feature Flags Are Flawed: Let's Make Them Better

ALL OR NOTHING

Page 16: Feature Flags Are Flawed: Let's Make Them Better

CANARY DEPLOYMENTS

Page 17: Feature Flags Are Flawed: Let's Make Them Better

COHORTS[…] a cohort is a group of subjects who haveshared a particular event together during a

particular time span.

— Wikipedia

Page 18: Feature Flags Are Flawed: Let's Make Them Better

MORE CONDITIONS?if ( Flags::enabled('SomeFeature') && $user->canSeeFeature('SomeFeature') ) { // execute feature code }

class User { public function canSeeFeature($feature) { // check the db or user session? } }

Page 19: Feature Flags Are Flawed: Let's Make Them Better

INTRODUCING SWIVELSwivel can enable features for a subset of users.

No more complex control �ow; Swivel takes care ofdetermining code paths.

Page 20: Feature Flags Are Flawed: Let's Make Them Better

BASIC CONCEPTS1. Segment users into 10 cohorts. Swivel calls these Buckets.

2. Associate a Feature to a number of active Buckets.

3. Write code that runs when a particular Feature is enabled.

4. Group Features under common Parent Feature to togglemultiple at once.

NewExperienceNewExperience.NavLinksNewExperience.DashboardNewExperience.Pro�le

Page 21: Feature Flags Are Flawed: Let's Make Them Better

SEGMENT USERS INTO BUCKETSid user_id bucket_id

1 160 6

2 956 2

3 189 7

4 412 2

Page 22: Feature Flags Are Flawed: Let's Make Them Better

ASSOCIATE FEATURES TO BUCKETSid slug buckets

1 "AwesomeSauce" "1,2,3,4"

2 "AwesomeSauce.Spicy" "1,2"

3 "AwesomeSauce.Saucy" "3,4"

Page 23: Feature Flags Are Flawed: Let's Make Them Better

BOOTSTRAP$bucket = 5; // From Session or DB

$map = [ 'AwesomeSauce' => [1,2,3,4], 'AwesomeSauce.Spicy' => [1,2], 'AwesomeSauce.Saucy' => [3,4] ];

$config = new \Zumba\Swivel\Config($map, $bucket);

$swivel = new \Zumba\Swivel\Manager($config);

Page 24: Feature Flags Are Flawed: Let's Make Them Better

TOGGLE EXAMPLEclass AmazingRecipe { public function __construct(\Zumba\Swivel\Manager $swivel) { $this->swivel = $swivel; }

public function getSauce() { return $this->swivel->forFeature('AwesomeSauce') ->addBehavior('Spicy', [$this, 'getSpicyFormula']) ->addBehavior('Saucy', [$this, 'getSaucyFormula']) ->defaultBehavior([$this, 'getFormula']) ->execute(); }

protected function getSpicyFormula() { } protected function getSaucyFormula() { } protected function getFormula() { } }

Page 25: Feature Flags Are Flawed: Let's Make Them Better

METRICS FOR CANARY DEPLOYMENTS

Page 26: Feature Flags Are Flawed: Let's Make Them Better

SWIVEL LOGGINGPSR-3 LOGGER AWARE

$config = new \Zumba\Swivel\Config($map, $bucket, $psr3Logger);

// or

$config->setLogger($psr3Logger);

Page 27: Feature Flags Are Flawed: Let's Make Them Better

SWIVEL METRICSSTATSD STYLE METRICS INTERFACE

interface MetricsInterface { public function count($context, $source, $value, $metric); public function decrement($context, $source, $metric); public function endMemoryProfile($context, $source, $metric); public function endTiming($context, $source, $metric); public function gauge($context, $source, $value, $metric); public function increment($context, $source, $metric); public function memory($context, $source, $memory, $metric); public function set($context, $source, $value, $metric); public function setNamespace($namespace); public function startMemoryProfile($context, $source, $metric); public function startTiming($context, $source, $metric); public function time($context, $source, \Closure $func, $metric); public function timing($context, $source, $value, $metric); }

Page 28: Feature Flags Are Flawed: Let's Make Them Better

METRICS FOR A/B TESTING

Page 29: Feature Flags Are Flawed: Let's Make Them Better

COMPLEXITY

Page 30: Feature Flags Are Flawed: Let's Make Them Better

TRADITIONAL FEATURE FLAGSPROS

Eliminate Long Lived BranchesDisable Problematic Code

CONSComplexity BumpAll Or Nothing

Page 31: Feature Flags Are Flawed: Let's Make Them Better

COHORT FEATURE FLAGSPROS

Eliminate Long Lived BranchesDisable Problematic CodeRoll Out FeaturesA/B Testing

CONSComplexity BumpAll Or Nothing

Page 32: Feature Flags Are Flawed: Let's Make Them Better

SWIVEL FEATURE FLAGSPROS

Eliminate Long Lived BranchesDisable Problematic CodeRoll Out FeaturesA/B TestingBuilt In LoggingBuilt In Metrics

CONSComplexity Bump

Page 33: Feature Flags Are Flawed: Let's Make Them Better

QUESTIONS?

Page 34: Feature Flags Are Flawed: Let's Make Them Better

GO FORTH AND TOGGLE!Twitter: @young_steveo

Lanyrd: http://lanyrd.com/2016/syntaxcon/sfbqxr

Swivel: https://github.com/zumba/swivel

Swiveljs: https://github.com/zumba/swiveljs

Swivel Cake: https://github.com/zumba/swivel-cake

THANKS!