SemVer Falsehoods


Programmers have a lot of beliefs that are mismatched with reality. You’d think that we wouldn’t do it to ourselves, and generally build a solid foundation for each other, but no: even SemVer suffers from this.

So let’s talk about SemVer falsehoods:


  1. This can happen if “be secure” is an expectation of your tool, and fixing a vulnerability requires breaking compatibility. Ex: removing an insecure primitive, or changing cryptography requirements. Like attempting to version TLS, or upgrade a hashing algorithm.

    But we have cryptographic agility.

    You say.

    TLS downgrade attack.

    I say. 

  2. This is why the spec says you MUST declare a public API, because it’s so easy to misunderstand what the public API of a particular piece of software covers when it’s not explicitly communicated. Is it everything that’s publicly available, or some subset? Declare it.

    Folks depending on Python’s cryptography got a rude awakening when they disagreed with the maintainers about the build chain being part of the API. That’s not the end of it, because Hyrum’s law says that any change that you make to observable behaviour will break someone! XKCD 1172 

  3. Who is right when tools automatically add extra functionality that you don’t want to promise as part of your API? Like when Rust automatically derives Send and Sync for your public types? 

  4. Not always… There’s a plethora of ways to make an incompatible change that seem inocuous. Including ones that strictly add new functionality: oh no, you broke people’s tests because their test mock didn’t implement your new functionality properly. But wait, is that covered by their API2

  5. Tooling is getting better here, so it may be possible to notice incompatible API definitions. But Hyrum says that everything is in scope, even list sorting and the other things your tools don’t yet automatically detect. 

  6. No, of course it isn’t. There’s a long list of incompatible changes that developers want to make that has grown month by month since the last major version bump. And of course releasing them all at once is the best strategy that SemVer gives you, technically and culturally. For example: there were lots of changes between Python2 and Python3, and some were much more difficult to manage than others (str/bytes). Had they all been spread out over many more version changes (python 3, 4, 5, maybe even 6) it would have been much easier to manage each successive set of breaking changes.

    We don’t deploy software all at once, so why would we version it that way? 

  7. Unless you’re paying for support, who knows if the maintainers have time to back-port fixes at all. XKCD 2347  2 3

  8. There’s two major versions of SemVer and the spec provides no way to differentiate between them. Who knows if you’re getting version 1.0.0 or version 2.0.0, or another later major version? 


Thanks to Lenny Morayniss for comments/corrections/discussion.


Previously: RSS