aboutsummaryrefslogtreecommitdiff
%!PS-Adobe-3.0 
%%DocumentMedia: SLIDE 842 595 0 () () 
%%EndComments 
%%BeginDefaults 
%%PageMedia: SLIDE
%%EndDefaults 
<< /PageSize [842 595] /ImagingBBox null >> setpagedevice 

/reencode {
	exch
	findfont
	dup length dict
	begin
	{       
		1 index /FID ne
		{ def }
		{ pop pop }
		ifelse
	} forall
	/Encoding ISOLatin1Encoding def
	currentdict
	end
	definefont pop
} def
/Times /Times reencode
/Courier /Courier reencode
/Times-Italic /Times-Italic reencode
/Helvetica /Helvetica reencode


/headerheight 75 def

/frontfontsz  60 def
/authorfontsz 40    def
/titlefontsz  40     def
/mainfontsz   30      def
/codefontsz   18      def
/tinyfontsz   18      def

/titlefont  /Helvetica     findfont titlefontsz  scalefont def
/mainfont   /Courier      findfont mainfontsz   scalefont def
/codefont   /Courier      findfont codefontsz   scalefont def
/tinyfont   /Times      findfont tinyfontsz   scalefont def
/frontfont  /Helvetica findfont frontfontsz  scalefont def
/authorfont /Times-Italic    findfont authorfontsz scalefont def
/authorfonttwo /Times findfont authorfontsz scalefont def


/pagewidth  842 def
/pageheight 595 def
/leftmargin 30  def
/topmargin  595 def

/pad 10 def

/titlefonth  titlefontsz  pad add def
/mainfonth   mainfontsz   pad add def
/codefonth   codefontsz   pad add def
/tinyfonth   tinyfontsz   pad add def
/frontfonth  frontfontsz  pad add def
/authorfonth authorfontsz pad add def

/headermargin
	pageheight headerheight titlefonth sub 2 div titlefontsz add sub
def
/rightmargin pagewidth leftmargin sub def
/tbtop topmargin def
/ypos topmargin def

/xcur { currentpoint pop      } def
/ycur { currentpoint exch pop } def

/wordbreak ( ) def
/linewrap {
	/proc exch def
	/linelength exch def
	/textstring exch def
	/breakwidth wordbreak stringwidth pop def
	/curwidth 0 def
	/lastwordbreak 0 def
	/startchar 0 def
	/restoftext textstring def
	{
		restoftext wordbreak search
		{
			/nextword exch def pop
			/restoftext exch def
			/wordwidth nextword stringwidth pop def
			curwidth wordwidth add linelength gt
			{
				textstring startchar
				lastwordbreak startchar sub
				getinterval proc
				/startchar lastwordbreak def
				/curwidth wordwidth breakwidth add def
			}
			{
				/curwidth curwidth wordwidth add
				breakwidth add def 
			} ifelse
			/lastwordbreak lastwordbreak
			nextword length add 1 add def
		}
		{
			pop exit
		} ifelse
	} loop
	/lastchar textstring length def
	textstring startchar lastchar startchar sub 
	getinterval proc
} def

/line {
	0 0 0 setrgbcolor
	0.5 setlinewidth
	leftmargin ypos moveto
	rightmargin ypos lineto
	stroke
} def

/center {
	dup
	/str exch def
	/sw str stringwidth pop def
	/xpos pagewidth sw sub 2 div xcur sub def
	xpos 0 rmoveto
} def

/objcenter {
	pagewidth exch sub 2 div 0 translate
} def

/s {
	/tbtop topmargin def
	/ypos topmargin def
	1 1 1 setrgbcolor
	0 setlinewidth
	newpath
	0 pageheight moveto
	pagewidth pageheight lineto
	pagewidth 0 lineto
	0 0 lineto
	closepath
	fill
	stroke
} def

/l {
	/h exch def
	/ypos ypos h sub def
	leftmargin ypos moveto
} def

/title {
	frontfonth l
	frontfont setfont
	0.5 0.5 0.9 setrgbcolor
	{ pagewidth leftmargin 2 mul sub }
	{ frontfonth l center show }
	linewrap
	frontfonth 2 div l
	frontfonth l
} def

/author {
	authorfont setfont
	0 0 0 setrgbcolor
	{ pagewidth leftmargin 2 mul sub }
	{ authorfonth l center show }
	linewrap
} def

/authortwo {
	authorfonttwo setfont
	0 0 0 setrgbcolor
	{ pagewidth leftmargin 2 mul sub }
	{ authorfonth l center show }
	linewrap
} def

/header {
	/ypos pageheight headerheight sub def
	0 0 0 setrgbcolor
	0 setlinewidth
	newpath
	0 pageheight moveto
	pagewidth pageheight lineto
	pagewidth ypos lineto
	0 ypos lineto
	closepath
	fill
	stroke
	leftmargin headermargin moveto
	titlefont setfont 
	0.5 0.5 0.9 setrgbcolor
	center show
	leftmargin ypos moveto
} def

/n {
	mainfont setfont
	0 0 0 setrgbcolor
	{ pagewidth leftmargin 2 mul sub }
	{ mainfonth l show }
	linewrap
} def

/cn {
	codefont setfont
	0 0 0 setrgbcolor
	{ pagewidth leftmargin 2 mul sub }
	{ codefonth l show }
	linewrap
} def

/tn {
	tinyfont setfont
	0 0 0 setrgbcolor
	{ pagewidth leftmargin 2 mul sub }
	{ tinyfonth l show }
	linewrap
} def

/is {
	/level1 save def
	/showpage {} def
} def

/ie {
	level1 restore
} def

/bs {
	/tbtop ypos def
} def

/be {
	/tm tbtop pad sub def
	/bm ypos pad sub def
	newpath
	leftmargin 10 sub tm moveto
	rightmargin tm lineto
	rightmargin bm lineto
	leftmargin 10 sub bm lineto
	closepath
	0 0 0 setrgbcolor
	0.5 setlinewidth
	stroke
} def
showpage
%%Page: 1 1
s
( Rollout, feature flag, experiment, operational toggle) title
(Different use cases for backend, frontend and mobile ) authortwo
showpage
%%Page: 2 2
s
() n
() n
() n
( "Feature flags" tend to come up when talking about continuous deployment) title
showpage
%%Page: 3 3
s
() n
() n
() n
() n
(CI: continuous integration) authortwo
() n
(CD: continuous delivery) authortwo
() n
(CD: continuous deployment) authortwo
showpage
%%Page: 4 4
s
( Types) header
() n
() n
() n
(1. rollout) n
(2. feature flag) n
(3. experiment) n
(4. operational toggle) n
showpage
%%Page: 5 5
s
( Rollout) header
( For *rolling out* a new version of software) title
(Short-lived using percentages) n
(- a new deployment of kubernetes) n
(- new APK released to the Play Store) n
showpage
%%Page: 6 6
s
( Feature flag) header
( For turning a feature *on* or *off* ) title
(Medium-lived using allow list, A/B test, percentage, app version, etc.) n
(- :new-chargeback-flow) n
(- :new-debit-card-activation-screen) n
showpage
%%Page: 7 7
s
( Experiment) header
( For analysing behaviour) title
(Medium-lived using allow list and A/B test) n
(- :debit-withdrawal-test) n
showpage
%%Page: 8 8
s
( Operational toggle) header
( For disabling features in #crash-like situations) title
(Long-lived using percentage) n
(- :bank-barcode-payment) n
(- :savings-bank-barcode-query-provider) n
showpage
%%Page: 9 9
s
() n
() n
(We know know about the types) authortwo
( But they have different relevance for backend, frontend and mobile) title
showpage
%%Page: 10 10
s
( backend) header
() n
() n
(1. rollout: k8s blue/green, canary and ~common-rollout~ common-xp) n
(2. feature flag: ~common-rollout~ common-xp and datasets) n
(3. experiment: common-xp) n
(4. operational toggle: ~common-rollout~ common-xp ) n
showpage
%%Page: 11 11
s
( frontend) header
() n
() n
(1. rollout: CDN and page refreshes) n
(2. feature flag: percentages and maybe IPs \(no :customer/id on the website\)) n
(3. experiment: via dynamic backend control) n
(4. operational toggle: via dynamic backend control ) n
showpage
%%Page: 12 12
s
( backend) header
() n
() n
(1. rollout: app stores) n
(2. feature flag: via dynamic backend control) n
(3. experiment: via dynamic backend control) n
(4. operational toggle: via dynamic backend control ) n
showpage
%%Page: 13 13
s
() n
() n
(Key differentiator is) authortwo
( how much *control* we have over the environment) title
showpage
%%Page: 14 14
s
( backend) header
( full control) title
showpage
%%Page: 15 15
s
( frontend) header
( partial control) title
(We choose when to make a new version available ) n
showpage
%%Page: 16 16
s
( mobile) header
( very limited control) title
(- app stores can restrict updates \(worse for iOS\)) n
(- customers still have to download new versions ) n
showpage
%%Page: 17 17
s
( Costs) title
(- more complex code) n
(- compatibility with old app versions) n
(- nesting is exponential) n
showpage
%%Page: 18 18
s
( Benefits) title
(- dynamicity) n
showpage
%%Page: 19 19
s
( weighting costs × benefits) header
( The less control we have, the more we value dynamicity ) title
showpage
%%Page: 20 20
s
( weighting costs × benefits) header
() n
() n
() n
(- backend: sometimes worth the cost) n
(- frontend: almost always worth the cost) n
(- mobile: *always* worth the cost) n
showpage
%%Page: 21 21
s
() n
() n
() n
( Best practices) title
showpage
%%Page: 22 22
s
( dynamic content > feature flag) title
(Always true for mobile, almost always for frontend ) n
showpage
%%Page: 23 23
s
( Use :include-list for named groups ) title
(Always true for backend, frontend and mobile ) n
bs
({:rules) cn
( #{{:types   :include-list) cn
(    :content {:filename "debit-team-members.txt"}}}}) cn
be
showpage
%%Page: 24 24
s
( Always use :app-version) title
(Only for mobile) n
bs
({:rules) cn
( #{{:types   :app-version) cn
(    :content {:min-version #{{:platform :android) cn
(                              :code     1000000}) cn
(                             {:platform :ios) cn
(                              :code     2000000}}}}}}) cn
be
showpage
%%Page: 25 25
s
( Extend ~common-rollout~ common-xp if required) title
(That's how :include-list, :app-version, etc. were born) n
showpage
%%Page: 26 26
s
( Beware of many nested feature flags) title
(True for backend, frontend and mobile) n
showpage
%%Page: 27 27
s
( Don't delete app-facing feature flags) title
(True for mobile) n
showpage
%%Page: 28 28
s
() n
() n
() n
( Include a feature flag on the whiteboarding phase) title
showpage
%%Page: 29 29
s
() n
() n
() n
( Include deleting/retiring the feature flag at the end) title
showpage
%%Page: 30 30
s
( Avoid renaming a feature flag) title
(Use :app-version with :min-version instead) n
showpage
%%Page: 31 31
s
() n
() n
() n
( And most importantly...) title
showpage
%%Page: 32 32
s
( *Always* rely on a feature flag on the app) title
(Never do a hotfix, avoid expedited releases at all costs) n
showpage
%%Page: 33 33
s
( References) header
() n
(1. "Feature Toggles \(aka Feature Flags\)", by Pete Hodgson) n
(2. "Continuous integration vs. delivery vs. deployment", by Sten Pittet) n
(3. Accelerate, by N. Forsgren, J. Humble and G. Kim) n
(4. these slides: euandre.org/slide/) n
(5. prose version of this presentation) n
(6. view source) n

showpage

%%EOF