SlideShare a Scribd company logo
FEATURE FLAGS ARE
FLAWED
LET'S MAKE THEM BETTER
Created by Stephen Young / @young_steveo
FEATURE FLAG?
I've seen a lot of names for this concept tossed
around: feature bits, ags, ippers, switches
and the like. There seems no generally
accepted name yet.
— Martin Fowler
SIMPLE TOGGLE
class AmazingRecipe
{
public function getSauce()
{
$useNewRecipe = false;
// $useNewRecipe = true;
if ($useNewRecipe) {
// new formula here
} else {
// original code here
}
}
}
TRADITIONAL
FEATURE 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
SIMPLE TOGGLE
class AmazingRecipe
{
public function getSauce()
{
$useNewRecipe = false;
// $useNewRecipe = true;
if ($useNewRecipe) {
// new formula here
} else {
// original code here
}
}
}
❌
❌
Not Testable
SIMPLE TOGGLE V2
class AmazingRecipe
{
public function getSauce()
{
if ($this->useNewRecipe()) {
// new formula here
} else {
// original code here
}
}
public function useNewRecipe()
{
return false; // true
}
}
←
←
Can Be Stubbed
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' ]
];
}
SIMPLE TOGGLE V2
class AmazingRecipe
{
public function getSauce()
{
if ($this->useNewRecipe()) {
// new formula here
} else {
// original code here
}
}
public function useNewRecipe()
{
return false; // true
}
}
❌❌❌
Not Maintainable
Not Con gurable
Not My Concern
FEATURE ROUTER
class AmazingRecipe
{
public function getSauce()
{
if ($this->useNewRecipe()) {
// new formula here
} else {
// original code here
}
}
public function useNewRecipe()
{
return Flags::enabled('AmazingRecipie.NewSauceFormula');
}
}
FEATURE ROUTER
final class Flags
{
protected static $map = [];
public static function enabled($key)
{
if (empty(static::$map)) {
// hydrate map
}
return !empty(static::$map[$key]);
}
}
TRADITIONAL FEATURE FLAG SYSTEM
Curb Long-Lived Feature Branches
Easy To Use (If This Then That)
Testable
TONS OF APPLICATIONS
Release Toggles - change frequently, short lived
Timed Releases
Operations Toggles - sometimes long lived, rarely change
WHAT'S NOT TO LIKE?
CYCLOMATIC COMPLEXITY
public 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
ALL OR NOTHING
CANARY DEPLOYMENTS
COHORTS
[…] a cohort is a group of subjects who have
shared a particular event together during a
particular time span.
— Wikipedia
MORE CONDITIONS?
if (
Flags::enabled('SomeFeature') &&
$user->canSeeFeature('SomeFeature')
) {
// execute feature code
}
class User
{
public function canSeeFeature($feature)
{
// check the db or user session?
}
}
INTRODUCING SWIVEL
Swivel can enable features for a subset of users.
No more complex control ow; Swivel takes care of
determining code paths.
BASIC CONCEPTS
1. 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.
Swivel calls these Behaviors.
SEGMENT USERS INTO BUCKETS
id user_id bucket_id
1 160 6
2 956 2
3 189 7
4 412 2
ASSOCIATE FEATURES TO BUCKETS
id slug buckets
1 "AwesomeSauce" "[ ]"
2 "AwesomeSauce.Spicy" "[1,2]"
3 "AwesomeSauce.Saucy" "[3,4]"
BOOTSTRAP
$bucket = 5; // From Session or DB
$map = [
'AwesomeSauce' => [1,2,3,4],
'AwesomeSauce.Spicy' => [1,2],
'AwesomeSauce.Saucy' => [3,4]
];
$config = new ZumbaSwivelConfig($map, $bucket);
$swivel = new ZumbaSwivelManager($config);
TOGGLE EXAMPLE
class AmazingRecipe
{
public function __construct(ZumbaSwivelManager $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() { }
}
SHORTHAND EXAMPLE
class AmazingRecipe
{
public function __construct(ZumbaSwivelManager $swivel)
{
$this->swivel = $swivel;
}
public function getSauce()
{
return $this->swivel->invoke(
'AwesomeSauce.New',
[$this, 'getNewSauce'],
[$this, 'getOldSauce']
);
}
}
METRICS FOR CANARY DEPLOYMENTS
SWIVEL LOGGING
PSR-3 LOGGER AWARE
$config = new ZumbaSwivelConfig($map, $bucket, $psr3Logger);
// or
$config->setLogger($psr3Logger);
SWIVEL METRICS
STATSD 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);
}
METRICS FOR A/B TESTING
MORE APPLICATIONS
Release Toggles
Timed Releases
Operations Toggles
Experiments
Permissions?
COMPLEXITY
TRADITIONAL FEATURE FLAGS
PROS
Eliminate Long Lived Branches
Disable Problematic Code
CONS
Complexity Bump
All Or Nothing
COHORT FEATURE FLAGS
PROS
Eliminate Long Lived Branches
Disable Problematic Code
Roll Out Features
A/B Testing
CONS
Complexity Bump
All Or Nothing
SWIVEL FEATURE FLAGS
PROS
Eliminate Long Lived Branches
Disable Problematic Code
Roll Out Features
A/B Testing
Built In Logging
Built In Metrics
CONS
Complexity Bump
SWIVELJS
swivel
.forFeature('AwesomeSauce')
.addBehavior('Spicy', this.getSpicyFormula)
.addBehavior('Saucy', this.getSaucyFormula)
.defaultBehavior(this.getFormula)
.execute();
COMMUNITY PACKAGES
ZF2 module: https://github.com/mrferos/mrf-swivel
Yii extension: https://github.com/DanaLuther/yii-swivel
Yii 2.0 extension: https://github.com/DanaLuther/yii2-swivel
CakePHP 2 Plugin: https://github.com/zumba/swivel-cake
ROADMAP
Bucket Ranges
Con gurable Granularity
CakePHP 3.0 Plugin
QUESTIONS?
GO FORTH AND TOGGLE!
Twitter: @young_steveo
Swivel: https://github.com/zumba/swivel
Joindin: https://legacy.joind.in/17583
THANKS!

More Related Content

What's hot

Oracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional CompilationOracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional Compilation
Scott Wesley
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
Arnaud Langlade
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
Fabien Potencier
 
Unit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleUnit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by Example
Benjamin Eberlei
 
Bad test, good test
Bad test, good testBad test, good test
Bad test, good test
Seb Rose
 
Unittesting Bad-Practices by Example
Unittesting Bad-Practices by ExampleUnittesting Bad-Practices by Example
Unittesting Bad-Practices by Example
Benjamin Eberlei
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace Ju
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
Workhorse Computing
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Workhorse Computing
 
Neatly folding-a-tree
Neatly folding-a-treeNeatly folding-a-tree
Neatly folding-a-tree
Workhorse Computing
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
Mark Baker
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
Jeff Carouth
 
How to write code you won't hate tomorrow
How to write code you won't hate tomorrowHow to write code you won't hate tomorrow
How to write code you won't hate tomorrow
Pete McFarlane
 
The Perl6 Type System
The Perl6 Type SystemThe Perl6 Type System
The Perl6 Type System
abrummett
 
WordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressWordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPress
Alena Holligan
 
The most exciting features of PHP 7.1
The most exciting features of PHP 7.1The most exciting features of PHP 7.1
The most exciting features of PHP 7.1
Zend by Rogue Wave Software
 
What's New in PHP 5.5
What's New in PHP 5.5What's New in PHP 5.5
What's New in PHP 5.5
Corey Ballou
 
PHP Traits
PHP TraitsPHP Traits
PHP Traits
mattbuzz
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
Fabien Potencier
 
PHP for Python Developers
PHP for Python DevelopersPHP for Python Developers
PHP for Python Developers
Carlos Vences
 

What's hot (20)

Oracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional CompilationOracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional Compilation
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Unit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by ExampleUnit-Testing Bad-Practices by Example
Unit-Testing Bad-Practices by Example
 
Bad test, good test
Bad test, good testBad test, good test
Bad test, good test
 
Unittesting Bad-Practices by Example
Unittesting Bad-Practices by ExampleUnittesting Bad-Practices by Example
Unittesting Bad-Practices by Example
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
 
Neatly folding-a-tree
Neatly folding-a-treeNeatly folding-a-tree
Neatly folding-a-tree
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
How to write code you won't hate tomorrow
How to write code you won't hate tomorrowHow to write code you won't hate tomorrow
How to write code you won't hate tomorrow
 
The Perl6 Type System
The Perl6 Type SystemThe Perl6 Type System
The Perl6 Type System
 
WordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressWordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPress
 
The most exciting features of PHP 7.1
The most exciting features of PHP 7.1The most exciting features of PHP 7.1
The most exciting features of PHP 7.1
 
What's New in PHP 5.5
What's New in PHP 5.5What's New in PHP 5.5
What's New in PHP 5.5
 
PHP Traits
PHP TraitsPHP Traits
PHP Traits
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
PHP for Python Developers
PHP for Python DevelopersPHP for Python Developers
PHP for Python Developers
 

Similar to Feature Flags Are Flawed: Let's Make Them Better - DPC

PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
Yuya Takeyama
 
Be pragmatic, be SOLID
Be pragmatic, be SOLIDBe pragmatic, be SOLID
Be pragmatic, be SOLID
Krzysztof Menżyk
 
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
PROIDEA
 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middleware
Kuan Yen Heng
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
Lars Jankowfsky
 
DRUPAL 8 STORAGES OVERVIEW
DRUPAL 8 STORAGES OVERVIEWDRUPAL 8 STORAGES OVERVIEW
DRUPAL 8 STORAGES OVERVIEW
DrupalCamp Kyiv
 
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Krzysztof Menżyk
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
Tagged Social
 
Best Practice Testing with Lime 2
Best Practice Testing with Lime 2Best Practice Testing with Lime 2
Best Practice Testing with Lime 2
Bernhard Schussek
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
SWIFTotter Solutions
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
Marcello Duarte
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
Sam Hennessy
 
Why async and functional programming in PHP7 suck and how to get overr it?
Why async and functional programming in PHP7 suck and how to get overr it?Why async and functional programming in PHP7 suck and how to get overr it?
Why async and functional programming in PHP7 suck and how to get overr it?
Lucas Witold Adamus
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
jsmith92
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
XSolve
 
Concurrent test frameworks
Concurrent test frameworksConcurrent test frameworks
Concurrent test frameworks
Andrea Giuliano
 
Functional php
Functional phpFunctional php
Functional php
Jean Carlo Machado
 
Demystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHPDemystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHP
Alena Holligan
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth
 

Similar to Feature Flags Are Flawed: Let's Make Them Better - DPC (20)

PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
Be pragmatic, be SOLID
Be pragmatic, be SOLIDBe pragmatic, be SOLID
Be pragmatic, be SOLID
 
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middleware
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
DRUPAL 8 STORAGES OVERVIEW
DRUPAL 8 STORAGES OVERVIEWDRUPAL 8 STORAGES OVERVIEW
DRUPAL 8 STORAGES OVERVIEW
 
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
Best Practice Testing with Lime 2
Best Practice Testing with Lime 2Best Practice Testing with Lime 2
Best Practice Testing with Lime 2
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Why async and functional programming in PHP7 suck and how to get overr it?
Why async and functional programming in PHP7 suck and how to get overr it?Why async and functional programming in PHP7 suck and how to get overr it?
Why async and functional programming in PHP7 suck and how to get overr it?
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Concurrent test frameworks
Concurrent test frameworksConcurrent test frameworks
Concurrent test frameworks
 
Functional php
Functional phpFunctional php
Functional php
 
Demystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHPDemystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHP
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 

Recently uploaded

Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
Fwdays
 
Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
Neo4j
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
c5vrf27qcz
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
Enterprise Knowledge
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
akankshawande
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
Alex Pruden
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
LizaNolte
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
Jakub Marek
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
Neo4j
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
Tatiana Kojar
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
Jason Yip
 
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
"Scaling RAG Applications to serve millions of users",  Kevin Goedecke"Scaling RAG Applications to serve millions of users",  Kevin Goedecke
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
Fwdays
 
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
saastr
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
ScyllaDB
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
Ivo Velitchkov
 
Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...
Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...
Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...
saastr
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
christinelarrosa
 

Recently uploaded (20)

Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
 
Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
 
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
"Scaling RAG Applications to serve millions of users",  Kevin Goedecke"Scaling RAG Applications to serve millions of users",  Kevin Goedecke
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
 
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
 
Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...
Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...
Overcoming the PLG Trap: Lessons from Canva's Head of Sales & Head of EMEA Da...
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
 

Feature Flags Are Flawed: Let's Make Them Better - DPC

  • 1. FEATURE FLAGS ARE FLAWED LET'S MAKE THEM BETTER Created by Stephen Young / @young_steveo
  • 2.
  • 3. FEATURE FLAG? I've seen a lot of names for this concept tossed around: feature bits, ags, ippers, switches and the like. There seems no generally accepted name yet. — Martin Fowler
  • 4. SIMPLE TOGGLE class AmazingRecipe { public function getSauce() { $useNewRecipe = false; // $useNewRecipe = true; if ($useNewRecipe) { // new formula here } else { // original code here } } }
  • 5. TRADITIONAL FEATURE 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
  • 6. SIMPLE TOGGLE class AmazingRecipe { public function getSauce() { $useNewRecipe = false; // $useNewRecipe = true; if ($useNewRecipe) { // new formula here } else { // original code here } } } ❌ ❌ Not Testable
  • 7. SIMPLE TOGGLE V2 class AmazingRecipe { public function getSauce() { if ($this->useNewRecipe()) { // new formula here } else { // original code here } } public function useNewRecipe() { return false; // true } } ← ← Can Be Stubbed
  • 8. 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' ] ]; }
  • 9. SIMPLE TOGGLE V2 class AmazingRecipe { public function getSauce() { if ($this->useNewRecipe()) { // new formula here } else { // original code here } } public function useNewRecipe() { return false; // true } } ❌❌❌ Not Maintainable Not Con gurable Not My Concern
  • 10. FEATURE ROUTER class AmazingRecipe { public function getSauce() { if ($this->useNewRecipe()) { // new formula here } else { // original code here } } public function useNewRecipe() { return Flags::enabled('AmazingRecipie.NewSauceFormula'); } }
  • 11. FEATURE ROUTER final class Flags { protected static $map = []; public static function enabled($key) { if (empty(static::$map)) { // hydrate map } return !empty(static::$map[$key]); } }
  • 12. TRADITIONAL FEATURE FLAG SYSTEM Curb Long-Lived Feature Branches Easy To Use (If This Then That) Testable
  • 13. TONS OF APPLICATIONS Release Toggles - change frequently, short lived Timed Releases Operations Toggles - sometimes long lived, rarely change
  • 14. WHAT'S NOT TO LIKE?
  • 15. CYCLOMATIC COMPLEXITY public 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
  • 18. COHORTS […] a cohort is a group of subjects who have shared a particular event together during a particular time span. — Wikipedia
  • 19. MORE CONDITIONS? if ( Flags::enabled('SomeFeature') && $user->canSeeFeature('SomeFeature') ) { // execute feature code } class User { public function canSeeFeature($feature) { // check the db or user session? } }
  • 20. INTRODUCING SWIVEL Swivel can enable features for a subset of users. No more complex control ow; Swivel takes care of determining code paths.
  • 21. BASIC CONCEPTS 1. 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. Swivel calls these Behaviors.
  • 22. SEGMENT USERS INTO BUCKETS id user_id bucket_id 1 160 6 2 956 2 3 189 7 4 412 2
  • 23. ASSOCIATE FEATURES TO BUCKETS id slug buckets 1 "AwesomeSauce" "[ ]" 2 "AwesomeSauce.Spicy" "[1,2]" 3 "AwesomeSauce.Saucy" "[3,4]"
  • 24. BOOTSTRAP $bucket = 5; // From Session or DB $map = [ 'AwesomeSauce' => [1,2,3,4], 'AwesomeSauce.Spicy' => [1,2], 'AwesomeSauce.Saucy' => [3,4] ]; $config = new ZumbaSwivelConfig($map, $bucket); $swivel = new ZumbaSwivelManager($config);
  • 25. TOGGLE EXAMPLE class AmazingRecipe { public function __construct(ZumbaSwivelManager $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() { } }
  • 26. SHORTHAND EXAMPLE class AmazingRecipe { public function __construct(ZumbaSwivelManager $swivel) { $this->swivel = $swivel; } public function getSauce() { return $this->swivel->invoke( 'AwesomeSauce.New', [$this, 'getNewSauce'], [$this, 'getOldSauce'] ); } }
  • 27. METRICS FOR CANARY DEPLOYMENTS
  • 28. SWIVEL LOGGING PSR-3 LOGGER AWARE $config = new ZumbaSwivelConfig($map, $bucket, $psr3Logger); // or $config->setLogger($psr3Logger);
  • 29. SWIVEL METRICS STATSD 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); }
  • 30. METRICS FOR A/B TESTING
  • 31. MORE APPLICATIONS Release Toggles Timed Releases Operations Toggles Experiments Permissions?
  • 33. TRADITIONAL FEATURE FLAGS PROS Eliminate Long Lived Branches Disable Problematic Code CONS Complexity Bump All Or Nothing
  • 34. COHORT FEATURE FLAGS PROS Eliminate Long Lived Branches Disable Problematic Code Roll Out Features A/B Testing CONS Complexity Bump All Or Nothing
  • 35. SWIVEL FEATURE FLAGS PROS Eliminate Long Lived Branches Disable Problematic Code Roll Out Features A/B Testing Built In Logging Built In Metrics CONS Complexity Bump
  • 37. COMMUNITY PACKAGES ZF2 module: https://github.com/mrferos/mrf-swivel Yii extension: https://github.com/DanaLuther/yii-swivel Yii 2.0 extension: https://github.com/DanaLuther/yii2-swivel CakePHP 2 Plugin: https://github.com/zumba/swivel-cake
  • 38. ROADMAP Bucket Ranges Con gurable Granularity CakePHP 3.0 Plugin
  • 40. GO FORTH AND TOGGLE! Twitter: @young_steveo Swivel: https://github.com/zumba/swivel Joindin: https://legacy.joind.in/17583 THANKS!