From bcd1d0be109aae75ed7d34545f893208a671e316 Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Sat, 15 Apr 2023 16:21:40 -0300 Subject: v2: WIP support for slides --- v2/src/bin/makemake | 17 +- v2/src/content/en/slide/local-first.ps | 522 +++++++++++++++++++++++++++++ v2/src/content/en/slide/local-first.slides | 204 +++++++++++ v2/src/content/en/slide/rollouts.ps | 500 +++++++++++++++++++++++++++ v2/src/content/en/slide/rollouts.slides | 208 ++++++++++++ v2/src/lib/base.en.conf | 11 + v2/src/lib/base.pt.conf | 11 + v2/src/lib/commencement.en.conf | 2 + v2/src/lib/commencement.pt.conf | 2 + 9 files changed, 1475 insertions(+), 2 deletions(-) create mode 100644 v2/src/content/en/slide/local-first.ps create mode 100644 v2/src/content/en/slide/local-first.slides create mode 100644 v2/src/content/en/slide/rollouts.ps create mode 100644 v2/src/content/en/slide/rollouts.slides (limited to 'v2/src') diff --git a/v2/src/bin/makemake b/v2/src/bin/makemake index c6e3407..3956844 100755 --- a/v2/src/bin/makemake +++ b/v2/src/bin/makemake @@ -144,6 +144,17 @@ for lang in $(langs); do printf '\n\n' done + coll_path="$(coll2path "$lang" slide)" + git ls-files "$CONTENT_PREFIX/$lang/$coll_path"*.slides | + varlist "slide.$lang.slides" + git ls-files "$CONTENT_PREFIX/$lang/$coll_path"*.slides | + sed 's/^\(.*\)\.slides$/\1.pdf: \1.ps/' + printf '\n\n' + + echo "slide.$lang.pdf = \$(slide.$lang.slides:.slides=.pdf)" + echo "all-generated.$lang.slides = \$(slide.$lang.slides)" + echo "all-generated.$lang.pdf = \$(slide.$lang.pdf)" + for e in $(extensions); do { if ! printf '%s\n' "$e" | grep -qE "$page_ext_filter"; then @@ -185,7 +196,7 @@ for lang in $(langs); do sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1feed.xml|" | varlist "all-generated.$lang.xml" - extensions '.series' '.categories' '.extrahtml' '.extrafeeds' '.index' '.xml' | + extensions '.series' '.categories' '.extrahtml' '.extrafeeds' '.index' '.xml' '.pdf' | sed "s|^\(.*\)\$|\$(all-generated.$lang\1)|" | varlist "all-generated.$lang" @@ -212,7 +223,7 @@ printf 'svgs = $(svgs.uncolored:.uncolored=)\n\n' } > "$CONTENT_PREFIX"/.gitignore -for e in $(extensions '.series' '.categories' '.extrahtml' '.extrafeeds' '.index' '.xml'); do +for e in $(extensions '.series' '.categories' '.extrahtml' '.extrafeeds' '.index' '.xml' '.pdf'); do langs | sed "s|^\(.*\)\$|\$(all-generated.\1$e)|" | varlist "all-generated$e" @@ -237,4 +248,6 @@ git ls-files "$CONTENT_PREFIX"/ | grep -v '\.md$' | grep -v '\.page$' | grep -v '\.uncolored$' | + grep -v '\.slides$' | + grep -v '\.ps$' | varlist 'static-content' diff --git a/v2/src/content/en/slide/local-first.ps b/v2/src/content/en/slide/local-first.ps new file mode 100644 index 0000000..44c5858 --- /dev/null +++ b/v2/src/content/en/slide/local-first.ps @@ -0,0 +1,522 @@ +%!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 +/Courier /Courier reencode +/Helvetica /Helvetica reencode +/Times /Times reencode +/Times-Italic /Times-Italic reencode + + +/headerheight 77 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 +( On "local-first") title +(Beyond the CRDT silver bullet) authortwo +showpage +%%Page: 1 1 +s +( Part 1) header +( Exposition) title +showpage +%%Page: 2 2 +s +( Target) header +() n +() n +() n +(- documents) n +(- files) n +(- personal data repositories) n +() n +() n +(Not: banking services, e-commerce, social networking, ride-sharing, etc.) n +showpage +%%Page: 3 3 +s +() n +() n +() n +( 7 ideals for local-first software) title +showpage +%%Page: 4 4 +s +() n +() n +() n +( 1 - no spinners: your work at your fingertips) title +showpage +%%Page: 5 5 +s +() n +() n +() n +( 2 - your work is not trapped on one device) title +showpage +%%Page: 6 6 +s +() n +() n +() n +( 3 - the network is optional) title +showpage +%%Page: 7 7 +s +() n +() n +() n +( 4 - seamless collaboration with your colleagues) title +showpage +%%Page: 8 8 +s +() n +() n +() n +( 5 - the long now) title +showpage +%%Page: 9 9 +s +() n +() n +() n +( 6 - security and privacy by default ) title +showpage +%%Page: 10 10 +s +() n +() n +() n +( 7 - you retain ultimate ownership and control) title +showpage +%%Page: 11 11 +s +( Towards a better future) header +() n +() n +() n +() n +( CRDTs \(Conflict-free Replicated Data Types\) as a Foundational Technology) authortwo +showpage +%%Page: 12 12 +s +( Use case) header +() n +bs +(# in node A and node B) cn +(s = "Hello, World") cn +() cn +(# in node A) cn +(s = "Hello, Alice") cn +() cn +(# in node B) cn +(s = "Hello, Bob") cn +be +(How to reconcile those?) n +(- Hello, ABloibce) n +(- Hello, AliceBob) n +(- Hello, BobAlice) n +(- Hello, Alice) n +(...) n +showpage +%%Page: 13 13 +s +( Existing CRDTs differ) title +(- performance) n +(- storage) n +(- compression) n +(- metadata overhead) n +showpage +%%Page: 14 14 +s +() n +() n +() n +( Hint towards the "automerge" CRDT) title +showpage +%%Page: 15 15 +s +() n +() n +() n +() n +() n +() n +(show comparison table, page 9) author +showpage +%%Page: 16 16 +s +( Part 2) header +( Critique) title +showpage +%%Page: 17 17 +s +( Software license) header +() n +() n +() n +("In our opinion, maintaining control and ownership of data does not mean that the software must necessarily be open source.") author +showpage +%%Page: 18 18 +s +( Example 1 - intentional restriction) header +() n +bs +(#!/bin/sh) cn +(TODAY="$\(date +%s\)") cn +(LICENSE_EXPIRATION="$\(date -d 2020-10-27 +%s\)") cn +(if [ "$TODAY" -ge "$LICENSE_EXPIRATION" ]; then) cn +( echo 'License expired!') cn +( exit 1) cn +(fi) cn +(echo $\(\(2 + 2\)\)) cn +be +() n +bs +(# today) cn +($ ./useful-adder.sh) cn +(4) cn +(# tomorrow) cn +($ ./useful-adder.sh) cn +(License expired!) cn +be +showpage +%%Page: 19 19 +s +( Example 2 - unintentional restriction) header +() n +bs +(# today) cn +($ useful-program) cn +(# ... useful output ...) cn +() cn +(# tomorrow, with more data) cn +($ useful-program) cn +(ERROR: Panic! Stack overflow!) cn +be +showpage +%%Page: 20 20 +s +() n +() n +( local-first *requires* free software ) title +(Otherwise "The Long Now" \(ideal nº5\) is lost) n +showpage +%%Page: 21 21 +s +( Denial of existing solutions) header +() n +() n +("In principle it is possible to collaborate without a repository service, e.g. by sending patch files by email, but the majority of Git users rely on GitHub." ) author +() n +(Solution: either GitHub+CRDTs or git send-email ) n +showpage +%%Page: 22 22 +s +( Plain-text formats) header +() n +("Git is highly optimized for code and similar line-based text file") author +() n +(It even pulls software to the plain text directtion, e.g.:) n +(- delivery-templates) n +(- common-core.protocols.config) n +() n +(Why not exploit that more?) n +showpage +%%Page: 23 23 +s +( Ditching of web applications) header +() n +() n +("The architecture of web apps remains fundamentally server-centric) author +() n +(Disagree. Contrast PouchDB with Android Instant Apps) n +showpage +%%Page: 24 24 +s +( Costs are underrated) header +() n +(- storage) n +(- backups) n +(- maintenance) n +() n +(Example: blog vs vlog) n +showpage +%%Page: 25 25 +s +( Real-time collaboration a bit overrated) header +() n +(It is only possible on the presence of reliable, medium-quality network connection) n +() n +() n +("X also works when inside an elevator, subway or plane!") author +showpage +%%Page: 26 26 +s +( On CRDTs and developer experience) header +() n +("For an app developer, how does the use of a CRDT-based data layer compare to existing storage layers like a SQL database, a filesystem, or CoreData? Is a distributed system harder to write software for?) author +() n +(YES.) authortwo +() n +(See "A Note on Distributed Computing") n +showpage +%%Page: 27 27 +s +( Conclusion) header +() n +(Why this is a "paper I love": it took offline-first and ran with it.) n +() n +(But a pinch of CRDT won't make the world local-first. ) n +() n +(The tricky part is the end of the sentence: "in spite of the Cloud".) n +showpage +%%Page: 28 28 +s +( References) header +() n +(1. "Local-First Software: You Own Your Data, in spite of the Cloud", by M. Kleppmann, A. Wiggins, P. Van Hardenberg and M. F. McGranaghan) n +(2. The Morning Paper article) n +(3. "A Note on Distributed Compiting", by J. Waldo, G. Wyant, A. Wollrath and S. Kendall) n +(4. these slides: euandre.org/slide/) n +(5. prose version of this presentation) n +(6. view source) n + +showpage + +%%EOF diff --git a/v2/src/content/en/slide/local-first.slides b/v2/src/content/en/slide/local-first.slides new file mode 100644 index 0000000..fd83115 --- /dev/null +++ b/v2/src/content/en/slide/local-first.slides @@ -0,0 +1,204 @@ +# On "local-first" + +@Beyond the CRDT silver bullet + +--- +## Part 1 +# Exposition + +--- +## Target +... +- documents +- files +- personal data repositories +.. +Not: banking services, e-commerce, social networking, ride-sharing, etc. + +--- +... +# 7 ideals for local-first software + +--- +... +# 1 - no spinners: your work at your fingertips + +--- +... +# 2 - your work is not trapped on one device + +--- +... +# 3 - the network is optional + +--- +... +# 4 - seamless collaboration with your colleagues + +--- +... +# 5 - the long now + +--- +... +# 6 - security and privacy by default + +--- +... +# 7 - you retain ultimate ownership and control + +--- +## Towards a better future +.... +@ CRDTs (Conflict-free Replicated Data Types) as a Foundational Technology + +--- +## Use case +. + # in node A and node B + s = "Hello, World" + + # in node A + s = "Hello, Alice" + + # in node B + s = "Hello, Bob" + +How to reconcile those? +- Hello, ABloibce +- Hello, AliceBob +- Hello, BobAlice +- Hello, Alice +\... + +--- +# Existing CRDTs differ +- performance +- storage +- compression +- metadata overhead + +--- +... +# Hint towards the "automerge" CRDT + +--- +...... +@@show comparison table, page 9 + +--- +## Part 2 +# Critique + +--- +## Software license +... +@@"In our opinion, maintaining control and ownership of data does not mean that the software must necessarily be open source." + +--- +## Example 1 - intentional restriction +. + #!/bin/sh + TODAY="$(date +%s)" + LICENSE_EXPIRATION="$(date -d 2020-10-27 +%s)" + if [ "$TODAY" -ge "$LICENSE_EXPIRATION" ]; then + echo 'License expired!' + exit 1 + fi + echo $((2 + 2)) +. + # today + $ ./useful-adder.sh + 4 + + # tomorrow + $ ./useful-adder.sh + License expired! +--- +## Example 2 - unintentional restriction +. + # today + $ useful-program + # ... useful output ... + + # tomorrow, with more data + $ useful-program + ERROR: Panic! Stack overflow! + +--- +.. +# local-first *requires* free software + +Otherwise "The Long Now" (ideal nº5) is lost + +--- +## Denial of existing solutions +.. +@@"In principle it is possible to collaborate without a repository service, e.g. by sending patch files by email, but the majority of Git users rely on GitHub." +. +Solution: either GitHub+CRDTs or git send-email + +--- +## Plain-text formats +. +@@"Git is highly optimized for code and similar line-based text file" +. +It even pulls software to the plain text directtion, e.g.: +- delivery-templates +- common-core.protocols.config +. +Why not exploit that more? + +--- +## Ditching of web applications +.. +@@"The architecture of web apps remains fundamentally server-centric +. +% FIXME: links +Disagree. Contrast PouchDB with Android Instant Apps + +--- +## Costs are underrated +. +- storage +- backups +- maintenance +. +Example: blog vs vlog + +--- +## Real-time collaboration a bit overrated +. +It is only possible on the presence of reliable, medium-quality network connection +.. +@@"X also works when inside an elevator, subway or plane!" + +--- +## On CRDTs and developer experience +. +@@"For an app developer, how does the use of a CRDT-based data layer compare to existing storage layers like a SQL database, a filesystem, or CoreData? Is a distributed system harder to write software for? +. +@YES. +. +% FIXME: link +See "A Note on Distributed Computing" + +--- +## Conclusion +. +Why this is a "paper I love": it took offline-first and ran with it. +. +But a pinch of CRDT won't make the world local-first. +. +The tricky part is the end of the sentence: "in spite of the Cloud". + +--- +## References +. +% FIXME: links +1. "Local-First Software: You Own Your Data, in spite of the Cloud", by M. Kleppmann, A. Wiggins, P. Van Hardenberg and M. F. McGranaghan +2. The Morning Paper article +3. "A Note on Distributed Compiting", by J. Waldo, G. Wyant, A. Wollrath and S. Kendall +4. these slides: euandre.org/slide/ +5. prose version of this presentation +6. view source diff --git a/v2/src/content/en/slide/rollouts.ps b/v2/src/content/en/slide/rollouts.ps new file mode 100644 index 0000000..0a8b39f --- /dev/null +++ b/v2/src/content/en/slide/rollouts.ps @@ -0,0 +1,500 @@ +%!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 diff --git a/v2/src/content/en/slide/rollouts.slides b/v2/src/content/en/slide/rollouts.slides new file mode 100644 index 0000000..aed745e --- /dev/null +++ b/v2/src/content/en/slide/rollouts.slides @@ -0,0 +1,208 @@ +--- +# Rollout, feature flag, experiment, operational toggle + +@Different use cases for backend, frontend and mobile + +--- +... +# "Feature flags" tend to come up when talking about continuous deployment + +--- +.... +@CI: continuous integration +. +@CD: continuous delivery +. +@CD: continuous deployment + +--- +## Types +... +1. rollout +2. feature flag +3. experiment +4. operational toggle + +% {favicon.svg} +--- +## Rollout + +# For *rolling out* a new version of software + +Short-lived using percentages + +% FIXME: links +- a new deployment of kubernetes +- new APK released to the Play Store + +--- +## Feature flag + +# For turning a feature *on* or *off* + +Medium-lived using allow list, A/B test, percentage, app version, etc. + +- :new-chargeback-flow +- :new-debit-card-activation-screen + +--- +## Experiment + +# For analysing behaviour + +Medium-lived using allow list and A/B test + +- :debit-withdrawal-test + +--- +## Operational toggle + +# For disabling features in #crash-like situations + +Long-lived using percentage + +- :bank-barcode-payment +- :savings-bank-barcode-query-provider + +--- +.. +@We know know about the types +# But they have different relevance for backend, frontend and mobile + +--- +## backend +.. +1. rollout: k8s blue/green, canary and ~common-rollout~ common-xp +2. feature flag: ~common-rollout~ common-xp and datasets +3. experiment: common-xp +4. operational toggle: ~common-rollout~ common-xp + +--- +## frontend +.. +1. rollout: CDN and page refreshes +2. feature flag: percentages and maybe IPs (no :customer/id on the website) +3. experiment: via dynamic backend control +4. operational toggle: via dynamic backend control + +--- +## backend +.. +1. rollout: app stores +2. feature flag: via dynamic backend control +3. experiment: via dynamic backend control +4. operational toggle: via dynamic backend control + +--- +.. +@Key differentiator is +# how much *control* we have over the environment + +--- +## backend +# full control +% FIXME: emoji +% 🎉 + +--- +## frontend +# partial control +We choose when to make a new version available + +--- +## mobile +# very limited control +- app stores can restrict updates (worse for iOS) +- customers still have to download new versions + +--- +# Costs +- more complex code +- compatibility with old app versions +- nesting is exponential + +--- +# Benefits +- dynamicity + +--- +## weighting costs × benefits +# The less control we have, the more we value dynamicity + +--- +## weighting costs × benefits +... +- backend: sometimes worth the cost +- frontend: almost always worth the cost +- mobile: *always* worth the cost + +--- +... +# Best practices + +--- +# dynamic content > feature flag +Always true for mobile, almost always for frontend + +--- +# Use :include-list for named groups +Always true for backend, frontend and mobile + + {:rules + #{{:types :include-list + :content {:filename "debit-team-members.txt"}}}} + +--- +# Always use :app-version +Only for mobile + + {:rules + #{{:types :app-version + :content {:min-version #{{:platform :android + :code 1000000} + {:platform :ios + :code 2000000}}}}}} + +--- +# Extend ~common-rollout~ common-xp if required + +That's how :include-list, :app-version, etc. were born + +--- +# Beware of many nested feature flags +True for backend, frontend and mobile + +--- +# Don't delete app-facing feature flags +True for mobile + +--- +... +# Include a feature flag on the whiteboarding phase + +--- +... +# Include deleting/retiring the feature flag at the end + +--- +# Avoid renaming a feature flag +Use :app-version with :min-version instead + +--- +... +# And most importantly... + +--- +# *Always* rely on a feature flag on the app +Never do a hotfix, avoid expedited releases at all costs + +--- +## References +. +% FIXME: links +1. "Feature Toggles (aka Feature Flags)", by Pete Hodgson +2. "Continuous integration vs. delivery vs. deployment", by Sten Pittet +3. Accelerate, by N. Forsgren, J. Humble and G. Kim +4. these slides: euandre.org/slide/ +5. prose version of this presentation +6. view source diff --git a/v2/src/lib/base.en.conf b/v2/src/lib/base.en.conf index ba0200b..144f0a0 100644 --- a/v2/src/lib/base.en.conf +++ b/v2/src/lib/base.en.conf @@ -48,3 +48,14 @@ export index_category_til_title='TIL by category' export index_til_url="$(url-for "$lang/$(coll2path "$lang" til)")" export feed_til_title="EuAndreh's TIL" + + +export index_slide_title='Slides' + +export index_recent_slide_title='Slides listing' + +export index_category_slide_title='Slides by category' + +export index_slide_url="$(url-for "$lang/$(coll2path "$lang" slide)")" + +export feed_slide_title="EuAndreh's slides" diff --git a/v2/src/lib/base.pt.conf b/v2/src/lib/base.pt.conf index 502aa1d..cb071c8 100644 --- a/v2/src/lib/base.pt.conf +++ b/v2/src/lib/base.pt.conf @@ -48,3 +48,14 @@ export index_category_til_title='HEA por categoria' export index_til_url="$(url-for "$lang/$(coll2path "$lang" til)")" export feed_til_title="HEA do EuAndreh" + + +export index_slide_title='Slides' + +export index_recent_slide_title='Slides listing' + +export index_category_slide_title='Slides by category' + +export index_slide_url="$(url-for "$lang/$(coll2path "$lang" slide)")" + +export feed_slide_title="EuAndreh's slides" diff --git a/v2/src/lib/commencement.en.conf b/v2/src/lib/commencement.en.conf index 9b19b18..70978a2 100644 --- a/v2/src/lib/commencement.en.conf +++ b/v2/src/lib/commencement.en.conf @@ -5,3 +5,5 @@ export article_collection_name='' export pastebin_collection_name='pastebin' export til_collection_name='til' + +export slide_collection_name='slide' diff --git a/v2/src/lib/commencement.pt.conf b/v2/src/lib/commencement.pt.conf index e3b9544..ba6693c 100644 --- a/v2/src/lib/commencement.pt.conf +++ b/v2/src/lib/commencement.pt.conf @@ -5,3 +5,5 @@ export article_collection_name='' export pastebin_collection_name='pastebin' export til_collection_name='hea' + +export slide_collection_name='slide' -- cgit v1.2.3