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
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