17 ms·
The Linux 2.5, Ruby 1.9 and Python 3 release management anti-pattern
- hyperpape 10y agoAre there examples of widely used, mature projects that have gone the opposite way?
- progval 10y agoweb browsers? I'm thinking particularly of Firefox, with all these extensions that do not work with the latest versions.
- Animats 10y agoThat's been coming for years. XUL addons have never worked on mobile Firefox.
- rockdoe 10y agoFirefox used to do the infrequent large change thing, then moved to frequent small breakage. Specific to add-ons: every release has broken some and the XUL depreciation is to some extent to deal with that problem better. Note that users hate both options proposed in the article passionately, it just seems that break early break often results in fewer users voting with their feet.
- mbroncano 10y agoSwift ?
- hyperpape 10y agoI think they aren't a reasonable comparison because they're very young and warned up front that they'd break compatibility several times in the early years.
- tedunangst 10y agoOpenBSD, llvm, and go all have six month cadences.
- hyperpape 10y agoAnd do the same sorts of breaking changes get made, just distributed in smaller chunks through those six month releases?
- tedunangst 10y agoExactly.
- mixedCase 10y agoI don't know about OpenBSD and LLVM, but Go has made good on the Go 1 compatibility promise, with only a few minor changes being disputed as wether they break it or not. Go 2.0 will probably be a different story, assuming it ever comes out, but I have a hard time believing the devs will release anything that won't be fixable using the "go fix" tool.
- tbrock 10y agoAnd ubuntu and gnome and fedora and...
- hp 10y agoYep. it works well. https://wiki.gnome.org/ReleasePlanning/TimeBased https://wiki.gnome.org/ReleasePlanning/TimeBased
- usernam 10y agoI can only comment on the specific llvm case, but I cannot say "it works" without listing the fact that I have to keep ~5-6 versions of llvm around _exactly_ for that reason. You cannot compare an OS, or in general any product which is "complete by itself" (browsers), with a compiler which is then used to _make_ the end product. Your source depends on it, and as it grows it just becomes increasingly hard to keep up. Rolling releases are /also/ a tradeoff. I'm not particularly pleased with llvm in this case. I genuinely prefer semantic releases, and yes, even the python2->3 strategy in this context.
- SatvikBeri 10y agoNot sure if Scala counts (it's 12 years old) but it continues to have (usually minor) breaking changes on each release.
- premium-concern 10y agoDo you have an example of what broke between 2.11.7 and 2.11.8?
- SatvikBeri 10y agoSorry, by release I meant e.g. 2.11 -> 2.12 . I don't recall any breakages in recent memory on smaller versions.
- gbrown_ 10y agoHere's a presentation from Theo de Raadt on how OpenBSD does its releases, https://www.youtube.com/watch?v=i7pkyDUX5uM https://www.youtube.com/watch?v=i7pkyDUX5uM.
- fpgaminer 10y agoArguably one of the most successful companies in the world is Microsoft. The reasons for their success are many, but at least one is the focus on backwards compatibility. Hook users, and never give them a reason to leave. As developers we know it is painful to maintain backwards compatibility, but it's incredibly valuable. It builds user confidence in your products, and most importantly it builds user trust that upgrading is safe and thus encourages adoption of newer versions of your software/libraries. The only mistake Microsoft made was not doing rolling releases. Major updates are slow and scary, so even though upgrading to a new version of Windows didn't mean loss of compatibility, it was never "easy" and always jarring. Backwards compatibility, automated testing, rolling releases. That's the magic bullet to keeping everyone happy and on the latest updates. If your users have to think about version numbers, you're doing it wrong. * Yes, there are instances of Microsoft breaking compatibility, more-so post Windows 7. The point is that they tend to focus on it, and they get it right 97% of the time which is a technological feat. See the Rust programming language for a great example of this recipe.
- Longhanks 10y agoAnd now we're stuck with decades old software and API stacks while Metro/Modern UI/UWP struggles to take off since about 5 years.
- fygdttysf 10y agoThe day MS depracates WinAPI, they're control of the desktop is over, as every company which develops huge codebases will switch to an environment where their programs doesn't have to be rewritten at MS's discretion.
- derefr 10y agoIs there any platform an enterprise could switch to that would guarantee a slower rate-of-change than Windows? "One major rewrite-requiring breaking change in 20 years" sounds like—if not a good deal—the best one I could foresee getting anywhere.
- filereaper 10y agoI hazard that there's no easy answer to this. If you 'fork' and start off on a new development trail, its hard to retain compatibility. If you keep with the legacy branch, you can end up with a frankenstein monstrosity. Most of the examples used are of very highly coupled pieces of monolithic code ie. kernels, language runtimes, and probably also extends to databases. Its hard to take these apart without losing performance in some aspect or another... I suspect most 'user-land' developers have moved to the microservices/SOA type development methodology where API's dominate so this is less of a concern.
- zzzcpan 10y agoI think it's a lot more subtle than that. Users are always ready to jump ship, even if you don't break compatibility. Merely introducing new functionality that competes with the old ways and shifting dev focus to it forces users to put an effort into the new ways, which irritates them, so some might not do that and might start looking around instead, depending on how deeply invested they are and how fed up they are. Others have not tried even the old ways yet and are ok with the focus on the new ways. And only few are those benefiting from the new ways. Simple strategy just can't work for everyone. There has to be a separate strategy for separate kinds of users and things that introduce competition and fragmentation must be carefully weighted. Given all that, breaking compatibility early and often as a proposed solution seems like even worse strategy as it not just demands effort, but demands it immediately and irritates users even more, which means more users are probably going to get fed up a lot sooner.
- epx 10y agoFrom this point of view, Swift language is doing right. It is irritating to have to fix a project every few months because Swift language is changing under our feet, but it is still better than having multiple active flavors of Swift. (I still don't love Swift, though.)
- EuAndreh 10y agoWell, Apple can do whatever they want, with any language they want, better or worse, and they can still force developers to change to the latest thing. If they say that you can develop for iOS 11 only with Swift 4, not Swift 3< or Objective-C, everybody will have to switch to Swift 4, or else they won't be able to develop to iOS 11. Even though I also think that Swift is better than Objective-C, and getting better in each version, is not really comparable with Ruby/Python/etc.
- tonyedgecombe 10y agoAlthough I haven't had to use it the go solution looks really good to me, just run gofix update your code.
- mjevans 10y agoWith respect to Python 3, I think it /is/ in fact a similar but different language. Primarily my focus is not on small annoying easily covered things (a print() function is better than a print keyword), but on more systemic changes like it's decision to make a unicode str the default type of string for the language. I would like to see a new version of Python (maybe 4?) that centers around basic, commonly atomic, types and arrays of those types. This would prevent the issue of Python 3 either mangling input strings or choking as it tries to digest legacy input that isn't in the anticipated encoding (at the cost of not making the mess larger). It would not-modify data that is being passed through the language UNLESS requested as an operation or as an output filter (implicit operation). Traditional UNIX like 8 bit clean handling is why UTF-8 is a super set of ASCII (code-points above 0x7f undefined/locally specific); UTF-8 was able to define an in-situ character sync method and was still compatible with existing files, and programs that did not enforce a specific encoding on the data stream.
- est 10y agoPy3k's problem is lack of incentives. If Py3k is 30% faster in execution speed ppl will migrate in no time. But currently everything is do-able in py2.7 and maybe even faster. A successful example is PHP7.
- ubernostrum 10y agoIf you think Python 3 doesn't offer anything compelling, you haven't read about what's in Python 3.
- jsmeaton 10y agoI suspect for a lot of people the carrots aren't really that relevant compared to the cost of migrating. Async is one of the bigger ones and for us folks doing Django it's not on the menu. There are certainly quality of life improvements but nothing too ground breaking apart from async.
- mjevans 10y agoI suspect a reason Python 3 might 'be slower' would be precisely how expensive everything being a /validated/ (is it UTF-16 internal? Some other crazy Windows Native format IIRC) string, including internal object elements like names and dictionary (map) keys.
- captaincrowbar 10y agoThe "Third Way" is to avoid both problems (diverging stable and unstable forks vs. a single line with frequent minor breakage) by making heroic efforts to maintain backwards compatibility even in the face of major changes. Someone already mentioned Windows as an example of this. I'd point to C++ as another example: the C++ committee's longstanding commitment to maintaining backward compatibility at all costs has always been one of C++'s greatest strengths, and is certainly one of the main reasons why it's still in widespread use despite its age and many flaws.
- TylerE 10y agoThe biggest mistake Python 3 made was the print statement change. There was really no compelling reason to do it, it broke basically 2.x script ever for 0 practical gain.
- smcl 10y agoI'm not so sure. On one hand yeh sure, print vs print() may not have been something users were clamoring for, or worth adding an additional layer of confusion/weirdness over. However it's relatively straight-forward to port such code or instruct someone "ah you don't do print x you do print(x)". From what I've seen the unicode/string bytes/chars is a much bigger factor. Ironically this change made my largest Python app easier in Python 3 (easier to embed unicode literals from various languages), so perhaps my opinion isn't so valid here...
- TylerE 10y agoThe unicode change was more impactful, but the print was more like a little fuck you to maintenance devs everywhere. If they wanted print-as-function, fine, but they didn't have to eliminate the print statement at the same time. Some warts you're better off not scratching at.
- guitarbill 10y ago>> There was really no compelling reason to do it > the print was more like a little fuck you to maintenance devs everywhere > If they wanted print-as-function, fine, but they didn't have to eliminate the print statement at the same time. Complete and utter hyperbole. You could read PEP-3105 [0] and easily see it isn't true. In addition to this, quoting from both the PEP and the docs [0][1]: > "Luckily, as it is a statement in Python 2, print can be detected and replaced reliably and non-ambiguously by an automated tool, so there should be no major porting problems (provided someone writes the mentioned tool)." > "When using the 2to3 source-to-source conversion tool, all print statements are automatically converted to print() function calls, so this is mostly a non-issue for larger projects." Enough with the bullshit. [0] https://www.python.org/dev/peps/pep-3105/ https://www.python.org/dev/peps/pep-3105/ [1] https://docs.python.org/3/whatsnew/3.0.html https://docs.python.org/3/whatsnew/3.0.html
- stefantalpalaru 10y agoThe author is mistaken in adding Linux to this list. There was no "big, disruptive change" in the Linux userspace-facing API (stable syscalls, basically). The Linux developers are quite serious about not breaking that and what Linus said back in 2005 still stands - http://yarchive.net/comp/linux/gcc_vs_kernel_stability.html http://yarchive.net/comp/linux/gcc_vs_kernel_stability.html : > We care about user-space interfaces to an insane degree. We go to extreme lengths to maintain even badly designed or unintentional interfaces. Breaking user programs simply isn't acceptable. We're _not_ like the gcc developers. We know that people use old binaries for years and years, and that making a new release doesn't mean that you can just throw that out. You can trust us.
- maxlybbert 10y agoThe article seems to believe that Debian packaging practices can be used to illustrate how the users responded to a project's actions. I find that funny, but it makes it hard to accept the article's conclusions. (I'm not saying anything about Debian, really; I would have the same complaint if the article pointed to Fedora, Slackware, Ubuntu, etc. as proof about whether a change confused users).
- lnussbaum 10y ago(I'm the author) Well my main free software affiliation is with Debian -- that's why I used it to illustrate. Still, I think it's relevant. One of the difficult choices that distributions have to make, is to decide which branch of projects should be shipped to users (of if multiple branches need to be shipped, which one should be the default). Of course Debian is often on the conservative side of things, and also made those decisions based on its own ability to introduce patches to fix breakages. It would be more interesting to have data about which python version is supported by how many modules, over time (and which ruby version is supported by how many ruby gems, over time). But I don't think that this data is available?
- Sanddancer 10y agoI think as a counterexample, one could look to projects like FreeBSD, which have had a long-running development branch and branches for release for a very long time. Breaking changes happen in -CURRENT, but within a stable branch -- 10.x, 11.x, etc, you even get things like ABI compatibility, so a module written for kernel 10.1 will work for kernel 10.2. The example projects show more a lack of development discipline than a problem with the big break model. A version number change from 1.8.7 to 1.9.0 doesn't suggest big changes that one should be cautious of, causing problems. Linux Kernel 2.5 had the problem of a lack of developers willing to write more inclusive tests and a lack of a pre-determined roadmap. Python had the problem of a lack of a transition version where deprecation warnings were on by default. Successful breaks can be made when they are declared in advance so people can have reasonable feedback. The projects in question show communication problems, not problems with the idea.
- IanCal 10y ago> Python had the problem of a lack of a transition version where deprecation warnings were on by default. I'm really not sure this is necessary, though perhaps I'm wrong. I expect that fewer people would have upgraded to 2.6 or 2.7 if they were full of warning printouts. > Successful breaks can be made when they are declared in advance so people can have reasonable feedback Python has an enormous amount of advance warning. Python3 was released at the same time as 2.6, which came with a warnings mode for breaking changes in python 3, then 2.7 allowed people to backport many of the newer features. There is an automated tool to do many of the conversions and you've been able to test your changes for the last seven years against a fully supported alternative, and 2.7 will be supported until 2020. That's a total of about 11 years from the launch of a working upgrade, it was being discussed a lot for at least a couple of years before the 3.0 launch and Guido says he first brought up the idea of py3k in 2000. I'm also sure you can write code that works in both 2 and 3, so there's even a fairly clear migration path. If developers aren't going to change things given such a runway, would adding default deprecation warnings really make such a difference? I'm sure I recall at the time that the transition was intended to take 10 years, and so is the problem simply that people are using a different measure of success than python did themselves?
- tehwalrus 10y agoThis article talks about problem porting patches back to Linux 2.4, and then makes the comparison with python 2. Conceptually, the "breaking backwards compatibility" argument works, especially for the dependent ecosystem. But, it is worth noting that python 2 and 3 build out of the same branch of the same tree. Indeed, you can build the 2.5, 2.6, 2.7, 3.X grammars all off the same code. Sure, there will be some python 3 specific stuff that won't be included when you build 2.X, but any patches are by definition already backported.
- deleted 10y ago[deleted]
- echelon 10y agoUgh, looking at the comments it seems that the Rust "nightly vs stable" article a few days ago [1] has sparked a lot of confusion. Either that, or people are trying to spread FUD about Rust. The original author ought to write a retraction. [1] https://news.ycombinator.com/item?id=13251729 https://news.ycombinator.com/item?id=13251729
- Annatar 10y agoIn retrospect, and looking at what those projects have been doing in recent years, it is probably a better idea to break early, break often, and fix a constant stream of breakages, on a regular basis, even if that means temporarily exposing breakage to users, and spending more time seeking strategies to limit the damage caused by introducing breakage. It amazes me how the author managed to conclude completely the opposite from what he described. Make the users experience the breakage. On purpose. To me as an engineer, that's utterly unacceptable. Empathy is still a core engineering value https://www.listbox.com/member/archive/182179/2013/05/sort/time_rev/page/1/entry/1:75/20130508172342:8CF96552-B825-11E2-98EE-8CBB5940B2DC/ https://www.listbox.com/member/archive/182179/2013/05/sort/t... the solution isn't to expose breakage to users in order to make the developers' lives easier; we are developers precisely because we are to tackle the difficult problems, so that users could get work done. As engineers, we convert the science and the theory into working products and tackle difficult problems so that useful work could get done. If we are disrupting the users so that our work and lives would be easier, we don't respect our users. We should never make our work easier for us at the expense of our users. The solution is to design for backwards compatibility from the onset; version interfaces if you can't predict for the future, but always remain backward compatible. This way, new consumers of the interfaces benefit from the new features transparently, and existing consumers continue to function without disruption. Plan ahead; don't just code: planning is 50% (or more) of the work.
- lnussbaum 10y ago(I'm the author) I did not mean that developers should break things on purpose. Of course, seeking strategies to limit the damage caused by introducing breaking changes, by providing some amount of backward compatibility where possible, is always a good idea. But I think that what those examples show is that strategies where disruptive changes are introduced on a regular basis (what I call "break early, break often"), requiring some fixes from time to time, work better than strategies where a different branch is used to break the world, and then require a huge transition for users. Maybe what I failed to articulate in the article is that most compilers, interpreters, libraries introduce minor breaking changes on a regular basis, with most major or semi-major releases. When that amount stays manageable, it's usually not a big problem for users (= developers that use those compilers, interpreters, libraries), that just deal with that. Also note that real end users are usually protected from this kind of breakage because they use software coming from distributions (that do the work of trying to make sure that everything they ship can work together), or package managers that allow for strict versioned dependencies.
- je42 10y agomerge early. push automated tests to the limit. use feature flags to disable unstable features.
- upofadown 10y agoPython 3 was to some extent a reaction to the constant breakage that people were complaining about at the time. It was decreed that backwards incompatible stuff would go into 3 and 2 would remain relatively static. Eventually it was announced that 2 would remain entirely static. That created an odd situation where the version that people were expected to transition from became a much better place to do new development in that it was a stable target. Heck, in a sense it is still better to target Python 2.7 for new development as the people running the reference implementation (cpython) have promised to stop changing things as a matter of policy. Your 2.7 based app could run basically forever with no changes. So you are dammed if you do and dammed if you don't. There is no definite answer here.