Slide 1

Slide 1 text

Chris Krycho – LambdaConf 2024 Semantic Versioning, library & framework evolution, programming language design, type systems, and you. The Cutting Edge of Versioning

Slide 2

Slide 2 text

A little bit about me Hello! • 15 years in software engineering • Avionics, energy industry & physics, Bib l es, restaurant ordering, LinkedIn • Now writing new materia l s for The Rust Programming Language book • Recent work at LinkedIn on versions, ecosystem evo l ution, PLs, and more

Slide 3

Slide 3 text

What should you know when we’re done? What is versioning? What does it l ook l ike to take versioning serious l y as a kind of programming? What shou l d you be doing as a programmer who is using versioning? Key goals 3

Slide 4

Slide 4 text

What is versioning?

Slide 5

Slide 5 text

Versioning is a communication tool. What is versioning?

Slide 6

Slide 6 text

Versioning is a communication tool. What is versioning? Something changed: • New features? • Add support for my operating system version? • Fix that annoying bug? 6

Slide 7

Slide 7 text

Does the upgrade get me something I want? 7

Slide 8

Slide 8 text

Am I willing to pay for it? 8

Slide 9

Slide 9 text

Versioning Strategies 9

Slide 10

Slide 10 text

The de facto standard for the past decade. SemVer (Semantic Versioning) ..(-)?(+)? 10

Slide 11

Slide 11 text

The de facto standard for the past decade. SemVer Given the version 5.2.3: • Major: 5 • Minor: 2 • Patch: 3 • Pre-re l ease: N / A • Bui l d or other metadata: N / A 11

Slide 12

Slide 12 text

The de facto standard for the past decade. SemVer Given the version 5.2.3-beta.1+fun: • Major: 5 • Minor: 2 • Patch: 3 • Pre-re l ease: beta.1 • Bui l d or other metadata: fun 12

Slide 13

Slide 13 text

The de facto standard for the past decade. SemVer ..(-)?(+)? • Patch: backwards-compatib l e bug fi xes on l y • Minor: features or deprecations (and possib l y backwards-compatib l e bug fi xes) • Major: breaking changes (and possib l y features and/or backwards-compatib l e bug fi xes) Extras: • Pre-re l ease: optiona l pre-re l ease number • Metadata: optiona l bui l d or other metadata 13

Slide 14

Slide 14 text

…is not without its issues. SemVer • What is a bug? • What is a breaking change? • Observab l e behavior • Performance characteristics • Private API (…but used by l itera l l y everyone) → “SemVer l awyering” 14

Slide 15

Slide 15 text

—SoloVer v2 ∞ “We intentionally do not try to communicate “backward compatibility” as there is no objective and satisfying de fi nition anyways. As a provider, you should document changes properly. As a user, you should test anyways. SoloVer &c. Skip the arguing: just increment a number! 15

Slide 16

Slide 16 text

Dates always go up. (Or close enough!) CalVer &c. Common variations: • YYYY.MM, e.g. 2024.05 • Ubuntu-sty l e: YY.MM, e.g. 24.05 • Patches a l l owed/supported: YY.MM., e.g.: • 24.05.1 • 24.05.2 16

Slide 17

Slide 17 text

Just count to 9. TypeScriptVer! • 1.0.0, 1.0.1, …, 1.0.999, … • 1.1.0, 1.1.1, … • … • 1.9.0, 1.9.1, … • 2.0.0, 2.0.1, … 17

Slide 18

Slide 18 text

But why?!? TypeScriptVer! • Marketing: Microsoft muckety-mucks said so. • Phi l osophy: “A l l changes to a compi l er are breaking.” 18

Slide 19

Slide 19 text

—Hyrum Wright ∞ Hyrum’s Law “With a su ffi cient number of users of an A P I , it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody. 19

Slide 20

Slide 20 text

“…a su ffi cient number of users…” Hyrum’s Law How many? Tens. Maybe dozens. 20

Slide 21

Slide 21 text

Versioning is a communication tool.

Slide 22

Slide 22 text

Each versioning scheme communicates something. Versioning is a communication tool. • SemVer: What kinds of changes happened? • Ca l Ver: When did this version happen? • So l oVer etc.: …things happened! • TypeScript: the decima l system!

Slide 23

Slide 23 text

Versioning as Contract 23

Slide 24

Slide 24 text

Speci fi cally: a socio-technical contract. Versioning as Contract At the intersection of peop l e and computers: • Not pure l y socia l . • Not pure l y technica l . • Often imp l icit. Contracts can be enforced!

Slide 25

Slide 25 text

Versioning as Programming 25

Slide 26

Slide 26 text

What are the basic rules for making this work? Versioning as Programming 1. De fi ne your versioning system in a machine-readab l e way. 2. Give semantics to that machine-readab l e format. 3. Map changes in your code to those semantics.

Slide 27

Slide 27 text

—Postel’s Law “Be conservative in what you do, be liberal in what you accept from others. Versioning as Programming De fi ning breaking changes: a shorthand.

Slide 28

Slide 28 text

De fi ning breaking changes: a mental model. Versioning as Programming Non-brea k ing Brea k ing Accept “looser” input Require “stricter” input Provide “stricter” output Provide “looser” output Add a new API Remove an existing API

Slide 29

Slide 29 text

—semver-ts.org ∞ “Note that this summary elides many important details, and those details may surprise you! Versioning as Programming De fi ning breaking changes.

Slide 30

Slide 30 text

Versioning as Programming Checking the contract.

Slide 31

Slide 31 text

Checking the contract: vibes. Versioning as Programming If we on l y cared about communicating with humans… Does it fee l l ike a breaking change? Then it is.

Slide 32

Slide 32 text

Checking the contract: tests. Versioning as Programming • Pioneers: Ruby and Node.js • Changing tests te l l s you something: • Fai l ing tests ⟹ bug or breaking change • New tests ⟹ bug fi x or feature • Removed tests ⟹ removed (deprecated) code • Performance and end-to-end re l ationships

Slide 33

Slide 33 text

Checking the contract: types. Versioning as Programming Types communicate the contract for a piece of code— to both humans and computers!

Slide 34

Slide 34 text

Checking the contract: types in Elm. Versioning as Programming • Run the compi l er when pub l ishing! • On l y at the type l eve l . → Necessary but insu ffi cient.

Slide 35

Slide 35 text

Checking the contract: types in Rust. Versioning as Programming • Uses SemVer for version reso l ution in Cargo. • Documents breaking changes in great detai l .

Slide 36

Slide 36 text

Checking the contract: types in Rust. Versioning as Programming

Slide 37

Slide 37 text

Checking the contract: types in Rust. Versioning as Programming • Uses SemVer for version reso l ution in Cargo. • Documents breaking changes in great detai l . • Growing support for automation: cargo-semver-checks • This is hard!

Slide 38

Slide 38 text

Checking the contract: types in Rust. Versioning as Programming mod example { pub struct Person { pub age: u8, pub name: String, } } let me = example :: Person { name: String :: from("Chris"), age: 36, };

Slide 39

Slide 39 text

Checking the contract: types in Rust. Versioning as Programming mod example { pub struct Person { pub age: u8, pub name: String, id: Uuid, } } let me = example :: Person { name: String :: from("Chris"), age: 36, }; error: cannot construct `Person` with struct literal syntax due to private fields --> src/main.rs:1:14 | 1 | let me = example :: Person { | ^^^^^^^^^^^^^^^ | = note: ... and other private field `id` that was not provided

Slide 40

Slide 40 text

Checking the contract: types in TypeScript. Versioning as Programming • More comp l icated type system ⟹ SemVer checking is harder

Slide 41

Slide 41 text

Checking the contract: types in TypeScript. Versioning as Programming

Slide 42

Slide 42 text

Checking the contract: types in TypeScript. Versioning as Programming • More comp l icated type system ⟹ SemVer checking is harder • Examp l e: • JS co ll ection types are mutab l e • TS has l oca l type inference • TS has untagged union types: string | number

Slide 43

Slide 43 text

Checking the contract: types in TypeScript. Versioning as Programming function example(): string | number; let myArray = [example()]; // Array myArray.push(123); // ✅ myArray.push("hello"); // ✅

Slide 44

Slide 44 text

Checking the contract: types in TypeScript. Versioning as Programming function example(): number;

Slide 45

Slide 45 text

De fi ning breaking changes: a mental model. Versioning as Programming Non-brea k ing Brea k ing Accept “looser” input Require “stricter” input Provide “stricter” output Provide “looser” output Add a new API Remove an existing API

Slide 46

Slide 46 text

Checking the contract: types in TypeScript. Versioning as Programming function example(): number; let myArray = [example()]; // Array myArray.push(123); // ✅ myArray.push("hello"); // ❌ string not assignable to number

Slide 47

Slide 47 text

Checking the contract: types in TypeScript. Versioning as Programming function example(): number; let myArray: Array = [example()]; myArray.push(123); // ✅ myArray.push("hello"); // ✅

Slide 48

Slide 48 text

Checking the contract: types in Unison. Versioning as Programming • Generate an AST • Norma l ize the AST into a canonica l form • Hash the norma l ized AST • Save the hash, norma l ized AST, and name to SQLite

Slide 49

Slide 49 text

Checking the contract: versions as types. Versioning as Programming version init class Expr extends Object { @init Expr() { super() } @init int eval() { return 0 ; }; } class Num extends Expr { @init int n; @init Num(int n) { super(); this.n = n; } @init int eval() { return this.n; } } class Example { @init Expr expr() { return new Num(4); } } @init((new Example().expr())

Slide 50

Slide 50 text

Checking the contract: versions as types. Versioning as Programming version v1 upgrades init class Add extends Expr { @v1 Expr a, Expr b; @v1 Add(Expr a, Expr b) { super(); this.a = a; this.b = b; } @v1 int eval() { return this.a.eval() + this.b.eval(); } } @v1(new Add((new Example).expr(), (new Example).expr()))

Slide 51

Slide 51 text

Checking the contract: versions as types. Versioning as Programming version v2 upgrades init class Expr extends Object { @v2 string print() { return ""; } } class Num extends Expr { @v2 string print() { return "" + this.n; } } @v1(new Add((new Example).expr(), (new Example).expr())) ✅ @v1((new Example).expr().print()) ❌

Slide 52

Slide 52 text

Checking the contract: versions as types. Versioning as Programming version v3 upgrades v1, v2 replaces init class Add extends Expr { @v3 string print() { return this.a.print() + " + " this.b.print(); } } @v1((new Example).expr().print()) ✅

Slide 53

Slide 53 text

What should you do? 53

Slide 54

Slide 54 text

…as an application developer? What should you do? • Use something SemVer-ish for your user facing versions. • Think about l ibraries and too l s: What are their versioning po l icies? • Imp l icit? Look at history! • Exp l icit? Look at history!

Slide 55

Slide 55 text

…as a library author? What should you do? • Think about—and communicate about—versioning! • Use the too l s: • elm bump, cargo semver-checks, etc. • Bui l d them if they don’t exist! • Keep upgrades l ow-coup l ing. → Support mu l tip l e majors of your own core dependencies

Slide 56

Slide 56 text

…as a framework author? What should you do? Your choices imp l icit l y constrain the who l e ecosystem. So: • Be extra exp l icit about your versioning po l icies. • Design your po l icies according l y: → A l l ow l ibraries to support more than one major version at once. → Make breaking changes infrequent and predictab l e. → Incorporate migration strategies and too l ing. (Codemods!) • Advise l ibraries to treat you as a “peer dependency”.

Slide 57

Slide 57 text

Aside: peer dependency semantics What should you do? • Frameworks are peer dependencies of l ibraries. • Libraries shou l d on l y require the l owest version they support • …and test against the who l e range they support in CI • (This can be comp l icated in many ecosystems!) • In Node, use pnpm or yarn, or use va l idate-peer-dependencies

Slide 58

Slide 58 text

…as a programming language author? What should you do? • Consider versioning in your l anguage design. • Bui l d version-aware-too l ing as soon as possib l e. • Bake “peer dependency” hand l ing into package too l ing. → Make it easy for l ibrary authors to check compatibi l ity. → Make it easy for app l ication authors to get compatib l e versions. → Enab l e automation, for CI, upgrades, etc.

Slide 59

Slide 59 text

What did we learn? Versioning is a form of communication. Versioning is a socio-technica l contract. So: Summing up 59 • Pick a po l icy (preferab l y SemVer!), and state it c l ear l y. • Enforce your po l icy with whatever too l s you can. • Keep upgrade coup l ing l ow! • Bui l d new things to push this forward: peer deps, l anguage features, etc.

Slide 60

Slide 60 text

I appreciate your attention. Thank you! • Fo l l ow me: chriskrycho.com • Emai l me: he l l [email protected] • Hire me! • front-end technica l strategy • TS adoption & conversion • Rust workshops • hard prob l em ana l ysis • bui l ding “ratchets” to improve software qua l ity 60