Hacker News new | ask | show | jobs
by TheDong 1513 days ago
The lesson that I take is that all non-essential packages should instead be in an official, separately versioned, stdlib.

Go moved "image/draw" into "golang.org/x/image/draw". This was a good solution because it meant you could update the compiler without having to worry about also updating your image drawing stuff and that possibly breaking.

I wish they did that with http, tls, and all the other stuff that isn't really part of the language itself.

As is, I usually have to wait months to get compiler benefits (like being able to use generics, or smaller binary sizes, or fixes to bugs) because the compiler update also comes with breaking changes to the http package (like the http2 change) or tls or whatever.

My lessons is that there should be 3 tiers of libraries:

1. Compiler-versioned libraries. Things like io, syscalls, reflection, and things who's implementation depends heavily on the compiler internals. Breaking changes are never made without extreme circumstances.

2. Official, separately versioned, standard libraries. Things like golang.org/x/ or the idea behind the rust-lang-nursery. This is for stuff like http, logging, tls, crypto algorithms, image manipulation, high-level filesystem APIs, other protocols and abstractions. It is supported to use an old version of these libraries with a new compiler forever, and the compiler will never change libraries in 1 in such a way that they could break any old version of 2. You should update these whenever you can, but they may make breaking changes, and may be versioned as such.

3. The rest of the packages, stuff the community writes. These should prefer to use semver, and should prefer to use libraries from 1 and 2, but no promises are made.

I think having these 3 tiers is ideal, especially because it makes it easier to update the compiler (it will never break you), ensures perpetual support for older versions of official non-stdlib-but-still-core libraries (may make major releases that break, but the old one builds and works forever).

This is already pretty close to how C works actually, and it's great. Tier 1 is the actual language spec itself, linking libraries, etc. Tier 2 is libc. Tier 3 is the rest of the world. I really don't have to worry about how my pthread_create call in glibc will break when I update gcc because that separation is well maintained, and backwards compatibility is assured.

Python and go are both a clear step back, where I update the compiler to get some feature, and then my http server stops working even though I had no intention of updating it.

1 comments

> The lesson that I take is that all non-essential packages should instead be in an official, separately versioned, stdlib.

Hmm, honestly, this is a really great take. A thin OS base, with the "batteries" being optional. Or at least being to use specific versions, bits and pieces from various points in time as needed.

Of course, this could turn into an Eldritch mess, but then again, it might also lead to working software over not being able to update the stuff you want to update because the rest would break otherwise.

Overall, there's probably a lot of consideration to be made about the details, but that seems workable. Stability might still sometimes be an issue (e.g. should the language internals change, a la Python 2 to 3), though i'm not sure whether that can even be addressed all that well, at least in the higher abstraction level languages (with separate runtimes like CLR, JVM etc.).