5 ms·
C++ is 35 years old. The problem is that it has 35 years of backwards compatibility. Go will not avoid this problem by taking time to make changes, it can only
by mantap 7y ago
C++ is 35 years old. The problem is that it has 35 years of backwards compatibility. Go will not avoid this problem by taking time to make changes, it can only be resolved by being prepared to break backwards compatibility.
- sammorrowdrums 7y agoIt's quite an amazing feat that C++ has maintained backwards compatibility. Watching the ~11 years of Python 2 to 3 adoption has been somewhat painful, and many libraries have had to offer support for both across much of that time. (And I believe at time of writing Google isn't even 100% ported to 3 yet - please correct this if I'm wrong). I couldn't be happier that Python 3 is finally king though, and major projects like Django are able to go entirely to 3 now. Breaking changes in languages can be important and good, but they really can affect adoption of the new version by existing users, which is tough as often major users hold some sway in the ecosystem. JavaScript has the no breaking changes problem even worse, because you have to support (within reason) all major interpreters existing in the wild, and cannot easily change the code, so "transpiling" has become the normal. Microsofts support lifetime for IE11 also means this isn't changing soon. Lots of old browsers in the wild (even though it has improved dramatically over last few years).
- mantap 7y agoIt is much easier to do breaking changes in a compiled and statically typed language, as long as it doesn't use a preprocessor. Because you can do automatic upgrades. Some Python 3 changes were not fixable by 2to3 which meant all source needed to be checked manually line by line, vastly increasing the cost of upgrading. Worse, Python 2 wasn't forward compatible with Python 3 in many cases, which required libraries like six to get a transition period through the back door. The whole process was managed horrifically.
- IshKebab 7y agoC++ has not maintained backwards compatibility by doing automatic upgrades. I don't think that would even count. Backwards compatibility for a language means that old source code still works without having to update it, even if you can do so automatically. Also worth pointing out that C++ has broken backwards compatibility in a very small number of cases, e.g. the `auto` keyword has changed meaning. Nobody ever used it before so it wasn't a problem in practice.
- pjmlp 7y agoclang-tidy has support for doing code upgrades, but doing that in a ISO standard language with several implementations, including compiler specific language extensions, is an almost impossible task anyway.
- mantap 7y agoI wasn't giving C++ as an example of a language that maintains backwards compatibility through breaking changes using source upgrades, I was actually thinking of Go when I said that. Obviously C++ does have a preprocessor, which means upgrades cannot be done automatically in general because e.g. how do you know which macros in an #ifdef are "supposed" to be defined and which are "supposed" to be undefined etc? Instead they have to maintain backwards compatibility in the spec.
- deleted 7y ago[deleted]
- zojirushibottle 7y ago> Watching the ~11 years of Python 2 to 3 adoption has been somewhat painful this portrayal of the python 2 to 3 migration does not represent the majority of the community! and yet we keep hearing it over and over because "large" codebases were not migrated on time. this migration was a software engineering problem. i hope by now, people have learned to write dumb code and avoid clever tricks whenever they can. performance and clever tricks get tied to languages, OSes, & hardware versions. python is no exception! not saying don't do them. just saying know what you are getting into. again, the issue is not entirely due to breaking changes. but python made it too easy. c++ for example would have given people such a hard time that they wouldn't have even bothered. python's was too permissive. i have seen the python 2.7 codebase that shipped with the original appengine. it always felt like traveling to a different world whenever the debugger gets into their code...
- nine_k 7y agoProblems of Python 2 to 3 migration were mostly not about clever tricks. They were largely about making Unicode strings and byte strings incompatible (as they should have been from get go). Much of Python 2 code mixed them up, and that was a source of actual bugs. Hence the need to fix manually.
- kortex 7y agoIt's hard to overstate how big of a breaking change that was. Python is basically scriptable C. In c, strings aren't really a thing, but they are first class in Python (since everything is effectively a dict). And char's are your typical string-like data structure. So in py2, it made (some) sense at the time to let str and byte[] types intermingle. I don't agree with that choice, but it wasn't unreasonable (much like the null pointer). This led to all manner of playing fast and loose with str as byte[] usage. I've seen inline asm and even machine code in python. Now it's the new millenium and oh look, ascii-char won't cut it as your language implementation of strings.
- nicoburns 7y agoJavaScript has made breaking changes though. Strict mode was introduced for ES5, and includes breaking changes, and now all engines in use implement it (it was in at least IE9). The difference between that and the python situation is that JavaScript allowed both versions to coexist in the same codebase.
- sammorrowdrums 7y agoStrict mode was opt in though, and code would still evaluate without it. There's also a lot of new syntax though, which does have high costs in cases like generators, and shipping the regenerator runtime because you need your code to run everywhere. To my knowledge they have extended syntax and added modes, but not actually made any breaking changes. A mode was a way to avoid making breaking changes. What I missed from my comment is not just about the engines in use, but also that all old spec confirming JavaScript should still run, in all new environments. That is backwards compatibility.
- matthewbauer 7y agoI suppose if you happened to previously have code with the string 'use strict'; at the top, and did non-strict things below, it would break. In a very small scale, that does break backwards compatibility.
- sammorrowdrums 7y agoI'd love to find out if there was anyone affected in reality. It seems improbable, as random string statements with no assignment is a pretty niche way to comment code, or surely it would have been mistake. But there's so much poorly written JS on the web that there is a chance!
- kybernetikos 7y ago> parseInt("012") Modern browsers will say 12, old browsers (IE 8 and down) will say 10.
- wtetzner 7y agoC++ has introduced breaking changes, though: https://stackoverflow.com/questions/6399615/what-breaking-changes-are-introduced-in-c11 https://stackoverflow.com/questions/6399615/what-breaking-ch... They've just been careful to try to minimize the impact.
- deleted 7y ago[deleted]
- pron 7y agoBackward compatibility (although there's a spectrum here -- not every breaking change breaks a lot of codebases) is virtually always more important than any feature you can think of. Breaking it might cost a lot of work, and you have to be fairly certain that the cost is more than offset by the benefits from the change, and over a relatively short time period. Given that the cost of breaking changes is easy to perceive, and it's been years if not decades since we've seen programming language features with substantial, tangible benefits, breaking compatibility is almost always the wrong decision.
- ATsch 7y agoThe important thing when breaking backwards compatability is that it can be: - automatically done - isolated within a module As long as these are true, the issues caused by breaking compatability are minimal. It's really the Python model where it's all-or-nothing and you de-facto need to remain compatible with two releases as everyone transitions that's the problem.
- htfy96 7y ago> - isolated within a module This only exists in fairy land. In practice, mixing code from different versions is always the root of subtle bugs and ABI/API mess. For me in front of a big chunk of legacy code, I'd rather wrap them in a separate process and communicate with the remaining part through RPCs if possible.
- lgessler 7y agoIt doesn't have to be like this. Clojure is over 10 years old and has more or less achieved its vision of never having a breaking change in the core language. This comes at a cost (many rejected proposals, very very slow acceptance of them) but it's still proof that you can avoid breaking changes if you are sufficiently cautious. (It probably also helps that Clojure has a full-fledged macro system that lets users write libraries that would have had to be compiler plugins or language proposals in other languages.)
- Sean1708 7y agoThat sounds like an example of it being exactly like this (since neither Go nor C++ have had any breaking changes either AFAIA), or am I not understanding something?
- lgessler 7y agoSorry, I didn't make the point I wanted to, which is that GP (on my reading) seems to think that breaking changes are necessary and unavoidable for the long-term health for a PL. I'm saying Clojure seems to be perfectly fine even without any breaking changes in over 10 years, and that it seems like it'll continue like this indefinitely.
- pjmlp 7y agoIts market adoption also seems to be stagnant, so.
- agumonkey 7y agoAlso practices and paradigms were different. Go leverage some form of historical experience in how to evolve the language.
- tomp 7y agoWhat does "backwards compatibility" even mean? That you can combine new code with old code (a.k.a. ABI compatibility)? That you can compile old code with a new compiler (modular compiler, old frontend + new backend, should work)? That you can mix old code and new code in the same file (why would you want to do that, presumably new code is also better, otherwise what's the point of changes in the first place)?
- mantap 7y agoIn the context of C++ it means that you don't have to make changes to your code when a new language version comes out. Because old broken features are preserved for eternity even if severely dysfunctional. Most of the hard work of learning C++ is learning all the "gotchas" that will sneak in and cause undefined behaviour or worse. That's why people have a love/hate relationship with it. The language is full of BS but the path of least resistance is to learn the ins and outs of the BS rather than to do a full rewrite of your huge codebase in a sane language. Learning the ins and outs of C++ is a one time hit, after that you can use it quite happily. So new projects get started in C++ and the cycle repeats.
- loopz 7y agoBackwards compatibility is not the goalpost: https://golang.org/cmd/fix/ https://golang.org/cmd/fix/ https://blog.golang.org/introducing-gofix https://blog.golang.org/introducing-gofix