Hacker News new | ask | show | jobs
by badsectoracula 2343 days ago
> I'm not sure what the right way is

The right way is to make sure that stuff that used to work in the previous version still works in the current version. Breaking people's work, especially work that spans multiple years, projects, knowledge, etc and expecting them to be happy about it is naive. Being condescending when they turn out to not be happy and try to avoid the unnecessary busywork forced on them does not help either.

This isn't just about Python, many libraries and languages (and some OSes - see iOS, macOS and to a slightly less extent Android) are terrible about this. The proliferation of semver with its normalization of breaking stuff (the fact that a dependency - be it a library or language or whatever - uses semver communicates that they have already decided that they will break backwards compatibility at some point) shows that most people are fine with breaking others' code.

2 comments

The most painful breaking change was the string treatment. Breakage was necessary if you wanted to make it possible to have more confidence in the basic building blocks of python.

If you make a mistake when making a tool, you can either leave it forever, permanently causing pain for users forever, or you can try to find a path to fix it.

That being said, a Python 3.0 which was _just_ “can’t call encode in string, decode on bytes” then subsequent releases fixing up other stuff over time would have been much nicer.

Like the “everything is iterators now” release could have happened later.

The constant stream of breaking changes in Python - that is, in the "standard library" which may as well be part of the language - is the most frustrating thing about Python. There are perfectly good projects that can no longer be run without major work, just because they were left unmaintained for a few years. This is a silly state of affairs, and depressingly common when the fix is really simple: version declarations. Feel free to move fast and break things, but always provide the old behaviour if the user puts a "version=3.2" flag in their code. There's no reason this mechanism couldn't have extended to every change in Python since its release.

If POV-Ray can do it, Python could have done it.

Free Pascal changed the string type some time ago to make it encoding aware (i'm not really a fan of the idea, but it was done for Delphi compatibility which is considered important by the FPC developers). I only had to change a handful of lines in my 10+ year old code (at the time, now it is older) to make things work (all were about treating the string as a byte array and manipulating the memory directly - i just changed the type to RawByteString which provides exactly that functionality).

AFAIK that was the biggest "breaking" change they introduced by far. In general have code from 2007 that compiles out of the box and this sort of stability is why i stick with FPC (and C) despite it being messy sometimes.

If you make a mistake when making a language or API you should make sure whatever fix you come up with will keep the existing code working, most common way being that the old API is implemented in terms of the new (even if slower, things will keep working) or in the case of languages, new stuff that can conflict with existing code can be opt-in (Free Pascal often uses compiler submodes for this).

Yes, this makes implementing the library/language harder but it is going to be a bit of extra work for the implementors in exchange for avoid A LOT of work for the users (especially when you consider all the combined time wasted in porting Python 2 to Python 3).

The language we use at work (Delphi) changed its string type from ANSI to Unicode, and it took us less than a day to fix our ~500kloc code base, which does a _lot_ of string manipulations all over.

This was due to the hard work the people behind Delphi had put down to make the transition as smooth as possible.

Python 2s issues went beyond the string encoding.

Some functions would return either bytes our text (in python 2 parlance, strings or Unicode) depending on the input. People would call decode on text (despite it only making sense on bytes).

Ultimately Python 2 encouraged a programming model where if you just tested with ASCII everything worked but the instant one of your library users put in an accented character or a kanji everything would blow up.

Just to make things clear: many python 2 programs operated on bytes thinking they were text. There isn’t really a way of resolving this API without user intervention on declaration of intent (not saying 3.0 was perfectly right but not every change can be made backwards compatible if you still have existing code)

> The right way is to make sure that stuff that used to work in the previous version still works in the current version.

But that too brings considerable downsides.

For all its merits, C++ is an extremely bloated language, getting even more complex every release, due in no small part to its commitment to backward compatibility.

There's no perfect answer. Python3's decision wasn't stupid, they just chose one downside over another.

C++ bloated largely because they decided to make it bloated - they didn't had to, they just decided to shove in whatever new idea sounded good without much concern about the language's size.

But despite that i 100% guarantee you that people who actually use the language and have large codebases are really glad that C++ is backwards compatible and they do not have to waste time refactoring code that works.

> they just decided to shove in whatever new idea sounded good without much concern about the language's size.

Compared to most languages, C++ is very slow moving, but also very old.

> despite that i 100% guarantee you that people who actually use the language and have large codebases are really glad that C++ is backwards compatible

Of course.