How not to rewrite your library
Tips on stable APIs
by Loren Segal / @lsegal
I’ve worked on libraries,
all shapes and sizes.
I’ve worked on libraries,
all shapes and sizes.
and with^
I’ve worked on libraries,
all shapes and sizes.
and with^
I’ve worked on libraries,
all shapes and sizes.
and with^
I’ve worked on libraries,
all shapes and sizes.
and with^
we’re getting older!
(and that’s a good thing)
what does it mean to be a grownup?
there is a lot of Ruby out there.
much more to break.
idealism ⟼ pragmatism
Backwards Compatibility Matters
Dependency GraphLibrary Maintainer
parser
ast
library maintainers have a distorted view
of dependency management.
Library Maintainer
“It’s just onebreaking change!”
Dependency GraphApplication Maintainer
Dependency GraphApplication Maintainer
parser gem
“It’s just onebreaking change!”
“It’s just onebreaking change!”
“It’s just onebreaking change!”
“It’s just onebreaking change!”
“It’s just onebreaking change!”
“It’s just onebreaking change!”
Application Maintainer
breaking changes hurt.
I’m Application Maintainer.
what can I do?
hold library maintainers
accountable.
even for major version bumps.
I’m a Library Maintainer
avoidance > mitigation
change
but mitigation will do.
C H A N G E MITIGATION STRATEGIES
Compatibility Adapters
Strategy #1
Adapter Pros:
- Minimal change for user. - Write once, minimal maintenance.
RedcarpetCompat
Only 74 lines. Rarely changes.
“but it’s a maintenance burden!”
“but it’s a maintenance burden!”
Gem::SourceIndex
RubyGems 1.3 API. Literally 0 changes.
Ethical DeprecationStrategy #2
this is super important…
Deprecate ≠ Delete!
NOT EQUAL
dislike, don’t delete.
TOLERANCE!
We must live in harmony with our deprecated
brothers and sisters!
Good Deprecation Example
Java 1.3: Thread.stop()
Java 1.3: Thread.stop()
Java 1.8: Still there.
Java 1.8: Thread.stop()
1. always have a good technical
reason to deprecate.
2. always have a
replacement API.
be like: Thread.stop()
be like: Thread.stop()Good Reason
be like: strcpy()
be like: strcpy()
Alternative API
don’t be like: fs.exists()
don’t be like: fs.exists()
don’t be like: fs.exists()
Not technical.
don’t be like: fs.exists()
Not technical.
No reason provided.No replacement provided.
3. you don’t have to
maintain deprecated code.
4. you don’t have to
delete deprecated code.
even in major version updates.
Semantic VersioningStrategy #3?
v{MAJOR}.{MINOR}.{PATCH}
MAJOR = breaking change MINOR = non-breaking change PATCH = no APIs should change
v{MAJOR}.{MINOR}.{PATCH}
v1.0.0 v3.5.3 etc.
SemVer is a great tool!
you can use SemVer.
you should use SemVer!
just don’t use SemVer as an excuse to break users.
just don’t use SemVer as an excuse to break users.
that’s not cool.
major version bumps are still last resorts.
only use SemVer to communicate
breaking changes.
(the rare times they happen)
recall: avoidance > mitigation
C H A N G E AVOIDANCE STRATEGIES
avoid breaking changes.
avoid breaking changes. easy right?
Tips to Avoid Changing Your API
1. up-front design work always yields a more
stable API.*
1. up-front design work always yields a more
stable API.** in my experience.
- domain model - class diagram - ER diagram
make a:
YARD, circa Feb. 2007
https://raw.githubusercontent.com/lsegal/yard/v0.1a/doc/domain_model.jpg
8 years later, that entire architecture
still exists.
2. README Driven
Development
sketch out your API in README form.
start from user experience,
work backwards.
start from user experience,
work backwards.
less formal. equally helpful.
less formal. equally helpful.
for small libraries.
3. Everything as a
Contract
Think of each API decision as a contract
you cannot break.
Ask:
“Will I be comfortable with this API being public in 5 years?”
If not, don’t make it public.
“But 5 years is a long time!”
Things That WereDesigned More Than5 Years Ago andStill Work Today
cron (last change in 1999)
(GNU/BSD) make.
10+ year old Makefiles still work.
(note: he probably didn’t vendor gcc/make/X11 in his repository)
will you be able to say this about your
non-trivial Ruby program
in 20 years?
1. design for the future.
2. think about your users.
users > code.
3. own your mistakes.
“Way too many projects seem to think that the code is more
important than the user, and they break things left and right, and they don’t apologize for it, because they feel that they are ‘fixing’ the code
and doing the right thing.”
“Way too many projects seem to think that the code is more
important than the user, and they break things left and right, and they don’t apologize for it, because they feel that they are ‘fixing’ the code
and doing the right thing.”- Linus Torvalds, creator of the Linux Kernel
@lsegal
@lsegal
gnuu.org!
thank you.