Fighting the Culture of 'Worse Is Better'
An anonymous reader writes: Developer Paul Chiusano thinks much of programming culture has been infected by a "worse is better" mindset, where trade-offs to preserve compatibility and interoperability cripple the functionality of vital languages and architectures. He says, "[W]e do not merely calculate in earnest to what extent tradeoffs are necessary or desirable, keeping in mind our goals and values -- there is a culture around making such compromises that actively discourages people from even considering more radical, principled approaches." Chiusano takes C++ as an example, explaining how Stroustrup's insistence that it retain full compatibility with C has led to decades of problems and hacks.
He says this isn't necessarily the wrong approach, but the culture of software development prevents us from having a reasoned discussion about it. "Developing software is a form of investment management. When a company or an individual develops a new feature, inserts a hack, hires too quickly without sufficient onboarding or training, or works on better infrastructure for software development (including new languages, tools, and the like), these are investments or the taking on of debt. ... The outcome of everyone solving their own narrow short-term problems and never really revisiting the solutions is the sea of accidental complexity we now operate in, and which we all recognize is a problem."
He says this isn't necessarily the wrong approach, but the culture of software development prevents us from having a reasoned discussion about it. "Developing software is a form of investment management. When a company or an individual develops a new feature, inserts a hack, hires too quickly without sufficient onboarding or training, or works on better infrastructure for software development (including new languages, tools, and the like), these are investments or the taking on of debt. ... The outcome of everyone solving their own narrow short-term problems and never really revisiting the solutions is the sea of accidental complexity we now operate in, and which we all recognize is a problem."
is a blogger who thinks about stuff and posts it "news"?
This sounds a lot like the mantra of the FreeDestkop.org folks and/or Redhat with the "moving Linux into the 21st century". I'm not going to call it a 'planted' article, but you know.
that values 100% employment, what else is there left to do when everything else is either automated or so productive that you only need a few people?
You make terrible systems that require tons of people day and night just to keep going.
Create a new language if you feel a radical change is necessary. I switched jobs for the "worse is better" mindset around me, but I do not agree with the post, Stroustrup is a bad example. I would not use C++ if I couldn't tie it to a C code/library. Standing on the shoulders of giants is often good. Only Einsteins should be allowed to invent new languages.
Back in the day. The clue is in the name. If it wasn't compatible but simply similar then it would have been called something else. Java perhaps.
C++'s strong compatibility with C was one of its strongest selling points relative to other object oriented languages back in the '80s.
And that compatibility still is important today. For one thing, APIs can be written in C (starting with the POSIX API) and be used by programs written in either C or C++.
Here's an idea: if you don't know shit about C++, don't post shit about C++. Save your precious insights for systemd maybe?
It's easy for a programmer to say "We should stop worrying so much about compatibility and interoperability" when they don't have to deal with customers, support, or actually selling the end product. When a customer calls up and says, "Hey, how come this new version of Windows doesn't work with any of my old Windows software?" you can't just tell them "Because our programmers thought it was better to get a fresh start."
SJW's don't eliminate discrimination. They just expropriate it for themselves.
So.. preserving backwards compatibility and interoperability across versions is a bad thing? If he's unhappy with the feature set of C++ (and I wouldn't blame him for that), then how about simply picking up a different language instead? That's what a new, non-compatible C++ version would be in any case.
Look at how great it has worked out for Python. It's been six years since the only mildly incompatible version 3 was released, and it has still not managed to become dominant over the legacy version 2. A more radical break would almost certainly have had an even tougher road ahead.
Trust the Computer. The Computer is your friend.
Seems like someone (or a consortium of someone's) should take C++, drop the C compatibility requirement, make whatever "cleanup" changes that allows, and call it C+++. Just make sure there's a module ready to go for gcc.
What was his suggestion to fix this problem? Because if it wasn't to open his own company, and 'do thigs the right way', then he's kind of a Hypocrite.
"Technical Debt is a thing, people"
I never heard the term before, had to wiki it, then realized it was a fundamental of software engineering that I was taught decades ... ago :( so old
Don't create app functionality that the user won't use. More bells and whistles mean more dev time, test time and more to maintain, it's a simple concept.
That's why apps now have functionality metrics (Firefox seems really big on it for example).
Sig. Sig. Sputnik
Worse is better is basically the KISS principle for software. C++ is not an example of that, but C is. This guy is an idiot.
This is my signature. There are many like it, but this one is mine.
.
So he thinks that compatibility and interoperability are not features which he likes. OK, I'm OK with that.
However, that is his opinion, nothing more, nothing less.
There are reasons why interoperability and compatibility are desired. It is not the easiest path to provide those characteristics, on the contrary, it is easier to just say, ~screw compatibility, screw interoperability~, and you'll probably finish your task more quickly.
So then the question becomes, why do people invest extra effort in order to assure interoperability and compatibility?
...which we all recognize is a problem....
And now he presumes to speak for everyone....
Overall it sounds like he just got out of a bad meeting in which someone told him that his opinions are not worth the air used to utter them, and now he's trying to convince the world that he is right and the world is wrong.
And that compatibility still is important today. For one thing, APIs can be written in C (starting with the POSIX API) and be used by programs written in either C or C++ or in language X, or language Y, or language Z.
FTFY. This is due to calling conventions, not due to a 'language compatibility'
Here's an idea: if you don't know shit about C++, don't post shit about C++?
Here's an idea: If you don't know shit about the basics of programming, don't post, like, at all. Especially avoid calling others idiots when you're at the same time making clear you're even less competent.
CLI paste? paste.pr0.tips!
discussion and then say your oponents have a "worse is better" mentality, well not unless you want to succeed.
Sacrificing backward compatibility and interoperability for radical changes would lead a large population of rapidly mutating code and runtime environment. You see this both in biology and software. Malware proliferates, ditches backward compatibility and interoperability and tries to adapt as quickly as possible to exploit newly discovered vulnerabilities. Giant organisms and big pieces of software change slowly, spend enormous amount of energy and effort in maintaining a thriving eco-system.
Radical changes (saltations) has its advantages but also limitations. Slow incremental changes has its limitations but also advantages.
sed -e 's/Chuck Norris/Rajnikant/g' joke > fact
Once upon a time, I wrote "clever" code. Truly beautiful, almost poetic in its elegance. Note I said "elegance", not "simplicity".
I don't know who to credit for this (probably read it on Slashdot), but a single perspective completely changed the way I view coding:
It takes substantially more effort to debug than it does to write code in the first place. If, therefore, I write code as clever as I possibly can - I can't effectively debug it (without investing far more time than I should) if something changes or goes wrong.
Now, that doesn't mean "worse is better"... I can still produce good code; I can even still write the occasional clever function when performance demands it. But for the 99.9% of code that has almost no impact whatsoever on performance, I can just say "if X then Y else Z" rather than using cool-but-cryptic bitmasking tricks to avoid executing a conditional instruction. And hey, whaddya know, I can actually read it at a glance six month later, rather than praying I didn't forget to update my comments.
On the flip side of this, a few weeks ago I helped a friend put together a spreadsheet with a few complex formulas in it. I love me some IFSUMS, arguably the best new feature of Excel in the past decade. Note that clause, "in the past decade". This weekend, she called me because her nice helpful spreadsheet wouldn't work - On Excel 2003. It seems that while 2003 has IFSUM, MS didn't add IFSUMS until 2007. The choice of one seemingly harmless backward-compatibility-breaking function made the whole thing useless in a given context. Now, in fairness, I can hear you all screaming "just upgrade already!"... But in the real world, well, we still have people using Windows 95.
Wrong.
C++ has zero problem dealing with structs as function parameters (usually pointers to structs) which have arbitrarily complex internal structure, including embedded pointers. Since C does not provide OO encapsulation, it is often useful for calling code to manipulate pointers directly.
In Perl, you've got to wait until someone provides a binding for these complex cases... or, yeah, "why don't you do it yourself? It's open source."
I think the author's original focusing on C++ as an example of "worse is better" is a sad distraction. Clearly C++ was designed with the goal of being compatible with C. There are plenty of examples of languages which attempted to solve object-oriented programming but threw away backwards compatibility as a design goal: D, Java, and C# come to mind.
That said, I think he does have an interesting point about our unwillingness to sit down and carefully consider our response to problems as they arise during development--that we are constantly chasing incremental changes without considering the technical debt that arises. I've seen it particularly inside many of the companies I've freelanced to; they consider their software an asset rather than a depreciating liability, that must be preserved at all costs--even if that cost is increased technical debt that makes maintenance nearly impossible.
But the real source of the problem, in my opinion, is not a culture which thinks "worse is better." It may appear that way, because many companies engage in tradeoffs which, to the casual observer, seems like they really consider "worse" as "better." The real problem is that many corporations and many organizations don't necessarily reward competence, because they are often run by the incompetent. The Dunning-Kruger effect extends beyond self-assessment. Thus, they treat software as an asset rather than as a depreciating liability: management is unable to properly assess their internal processes and the value of the result. All that work, and we're supposed to throw it away?
The scary part is that to many of the organizations I've freelanced to, too much competence creates organizational friction. The places where I've done work who've ranked my work the best are exactly the places where I've "phoned it in", so to speak, only going a little bit above the call of duty. Go too much above the call of duty, pause everyone to have a considered response and to carefully do what is right, and you find yourself up against very powerful forces who, thanks to their inability to self-assess, push back hard.
So Paul, is this a plug for your book or yet another argument for functional programming?
Not much useful information or examples as to why or where "Worse is better" is harming the world of computing. There is always a better tool to help solve a problem. But for many reasons they may or may not be appropriate. You the programmer should know when and where to use them.
One of my favorite quotes (the bold text at the end is the good part):
That applies to not only Unix and operating systems but any tool that is made to solve a problem. Just replace the word codebase with the tool name of choice.
I think we are seeing fresh starts. We've seen a shift away from desktop applications towards web as a common framework, that's become remarkably more useful. And now we are seeing moves towards mobility. Both web and mobility have forced a genuine separation between view systems and business logic that in the desktop world was a goal often not met. Then with the rise of devops architectures are becoming even more factory component where the parts are interchangeable and thus design mistakes can be corrected.
In terms of the languages themselves as fewer of the languages outside view languages need to be performance front ends, nor need to have a broad audience they've been able to specialize into particular domains. So if anything I see the opposite.
The author if this article is a Scala guy. Scala is architected the key compromise of free intermixing of imperative and functional code so that programmers don't have to cross the conceptual barrier switching to functional. Which means that it effectively introduces programmers to functional concepts at the line level but not the program design level. It is really an imperative language with lots of functional data manipulation structures you don't see the full power of functional. It is hard to think of a language which more directly followed in C++'s footsteps of bolting object-orientation onto C, then Scala which bolted functional onto a Java type language.
Does anyone have any idea of the hacks he's talking about?
Since C++ is intended to and has always been a superset of C, how could there be any problems and hacks caused by compatibility with C? How could it be any better by discarding part of the language itself?
A problem I've been seeing lately is that everyone seems to think software is carved in stone. In the past 3 or 4 years I've heard a LOT of excuses why some flaw in one system or another made a feature impossible. In these cases, fixing the flaw would be pretty trivial. Instead of doing THAT, people just build another layer of crap on top of the previous layer of crap and try to kind-of get something working. Code is not immutable. If it doesn't do something you need it to do, MAKE it do what you need it to do. Write a library, redesign a layer, simplify an interface, whatever. Don't just wring your hands and make the problem worse! Code is made to change. No design is ever perfect right from the start. If you try to make your design perfect from the start, you'll just end up paralyzed, afraid of doing anything because you might do it wrong. Start with a design that seems reasonable and adjust it as needed. Write small, decoupled libraries that can support that, and write unit tests to insure that each component behaves as expected. It's really not that hard, people!
I'm trying to teach myself to set people on fire with my mind... Is it hot in here?
As someone who manages several small ($2M) software development projects, and who gets developers pulled off to work on more important projects, I have a different view point than Parent, and more similar to the CS profs.
On my projects, my devs are typically assigned to my project for some fraction of their time (30-50%) and they have other projects that they also work on.
I'm willing to pay for slightly less efficiency, but in return get good code that someone can leave and someone else can pick up and run.
And I'm tired of "let's just get it working" crummy code and worse documentation. The reason *I* have to suffer through losing my 30% programmer is often because their previous project ran into a problem, and "Mr. I don't do docs" dev is the only one who can come in and make the quick fix needed, during which time I am dead in the water. And because he's a "just read the code, it's obvious" kind of person, I can't get someone else to fill in the hole. Project Gods forbid that he should be hit by a bus or take a job somewhere else, because I'll basically have to start from scratch.
Worse is better, or interoperability, is often mandated at the behest of the customer who often doesnt understand what theyre really asking for and its context. Customers dont understand that interoperability and compatibility fundamentally alters the scope and performance of a project. Often legacy features get included at the request of PHB's that become stakeholders out of fear, meaning feature X is only included because some irrational end user doesnt want change. Healthcare records are an excellent example as the driving force for their presentation and feature set are a typically a group of elderly physicians who just want what theyre used to using without the inconvenience of losing face over a technology they dont understand. Banks command interoperability and compatibility for different reasons, mainly because financial systems are predicated upon very basic yet powerful and secure mainframe systems that arent negotiable for upgrade.
the sad solution is to learn the objective of the application, ignore the customer, and focus on training after the system is developed. Work inside the maintenance cycle of the programs existence to identify flaws, but try to restrict increases in scope and vigilantly fight back against changes that are pedantic and clearly for the benefit of a single individual or flawed process.
Good people go to bed earlier.
worse is worse is the problem.
worse is better: a bunch of lisp/haskell weenies complaining that people use C
worse is worse: node.js
Copyright (c) 1990 - 2014 Dice. All rights reserved. Use of this comment is subject to certain Terms and Conditions.
How did breaking compatibility worked out for python 3?
I would assert precisely the opposite. "trade-offs to preserve compatibility and interoperability" do not cripple the functionality to users-- failures to engineer compatibility and interoperability is what cripples functionality.
The number of times that there's been a new feature and I've said "oh, excellent, it's true that my old files no longer work, but this is so wonderful I don't care" has been very close to zero. The number of times there's been a new feature and I've said "those assholes, I have twenty thousand files that don't work any more, what in the world were those idiots thinking?" is decidedly not zero.
http://www.geoffreylandis.com
People have been hating on C++ for over 20 years.
The biggest issue seems to be that it lets bad programmers blow things up.
Well...DUH.
It's a systems programming language. Always has been. C++ 2014 is starting to add some of the safety features found in higher-level languages, but it still has all the direct access stuff that freaks out people that want to hire inexperienced programmers (read: "cheap"), and set them to work on system code.
Here's a protip: If you want to hire cheap kids right out of college, don't give them C++ as they inaugural language. They probably learned on Java, which is the software development equivalent of "NerfWorld." They will almost instantly blow up C++.
If you have a project that NEEDS the power and access of C++, then, for Hastur's sake, DON'T give a n00b the job.
Otherwise, you have lots of choices with higher-level languages. Use one of them.
Stop whining about C++. If it won't fit the bill, then it will wither away, like so many other languages.
If being perfect means not having critical core features then you're confused about what is and is not perfect. Compatibility is important. In many applications it is vital. Period - end of story. Does maintaining compatibility make the project more complicated? Yep. Coding is hard.
Next issue.
I've decided to stop wasting my time responding to AC trolls/sockpuppets... so if you want a response from me... login.
Interoperability is king.
I don't care how awesome your new application is, if I can't get my data into it and out of it, it's worthless to me. I've been down this road. If I have to start a massive project just to start using your application, or plan for a massive one to stop using it, that's a cost to me... a big one. And if my people have to go to training just to be able to use it because you didn't want to bother meeting a standard... or I have to hire people strait out of college? Again, that's a huge cost. If your application is 10% slower because of interoperability, even that's inconsequential... I can order server cores off the internet, it's not that big of a deal. Got an idea for a new feature? Great! But if you can't get that feature to work inside the existing standard, you don't have a new feature. There's likely a reason it's not allowed.
Ordinarily, it doesn't. But the thing is, there are two things called GCC: the GNU C compiler (which handles C) and the GNU Compiler Collection (a set of compilers which, though they share the same backend, are still separate entities).
GCC, the C compiler, cannot handle Fortran. GCC, the set of compilers, can handle it via g77 (the old compiler) or gfortran (the new one), but the C compiler can't. This is considered the traditional way of doing things.
What makes C++ different from many languages is that its maintainers insist that C++ compilers must be able to handle C code. It's not enough to have a different compiler in the set, the way GCC does: it must be doable with the C++ compiler itself, in the same application. And so g++ can do it too, because that's what the standard requires of it.
That's what makes the difference. Ordinarily, as you say, a compiler's ability to handle multiple languages shouldn't affect any of the languages in it. But C++ was defined in a way that not only makes those effects possible: it makes them mandatory.
If you don't like the mess in C++, find a better language and use that. C++ is actually the most popular language for performance-critical code? Hm, I wonder how that happened? Because of or despite its C compatibility?
The world is full of bad technology that is popular because its version 1.0 was really popular at the time. The fact we still use all of it says something about the market for technology; apparently, backwards compatibility to a fault makes for more long-term popular systems than do-it-right-this-time. It is, unfortunately, the way of the computer industry. Or fortunately, if you need a job.
I sometimes ask revealing, often ignorant-seeming questions. Maybe they're harder to answer than you think.
It's a combination of 'Standards are never finished being implemented' combined with features never being explicitly declared.
Both C and C++ have been hobbled for years not by their backwards compatbility, but rather than features that are intentionally ambiguous or undefined because those are 'Implementation specific details', without regards to the effect of those lacking declarations effects on both cross platform compatibility as well as auditability of the resulting code. If there is no guarantee as to the functional equivalency of code produced by two compilers on the SAME arch (nevermind on different ones) how can you expect there to be the opportunity to 'start over' by dropping legacy support without a stable and documented legacy codebase for the new designs to be developed on?
Just as an example: Look at K&R, ANSI, C90, C14, etc. Many of these standards were never fully implemented in any particular compiler. K&R was supported in early gcc releases but deprecated and then dumped in gcc-2.95->early 3.x releases. Many of the later releases break features of the earlier ones piecemeal despite the original standard never having had a 'stable' release that could properly generate code for all applications (While rare, there are still many corner cases, even in perfectly 'valid' C programs that thanks to developer error, or mistake implementation of standard features resulted in code generation bugs. Some of which weren't fixed before a standard was deprecated or altered for compatibility with C++ for instance in a manner that broke a formerly 'conforming' application.)
Point being: Lots of compatibility has been thrown by the wayside in the name of forward progress, but it hasn't SOLVED anything because nobody seems willing to bother taking time out from their new features to ensure a stable and standard complete/compliant codebase from which to iterate into the next generation. The result of this is a constant churn of mostly working code with all sorts of corner cases resulting in unexpected operation, security errors, or simply some 'end user' being unable to compile an old version because the new compiler can't bootstrap the old one, the old one requires since-lost voodoo to compile the new one, and the amount of work and digital archeology to determine what changed in the standards to make the old code properly operate under the new ones may not be worth the expense in time/knowledge to do so.
Apologies if this is overly verbose, meandering, or obtuse. I figure if nothing else this might provide a basis of concepts someone more articulate can turn into an acceptable discourse on the shortcomings of the 'development culture'.
I phrase I picked up years ago seems to apply here, 'standard is better then the best solution'. It is not a culture of 'worse is better', but of competing interests where the pure joy of developing languages is not the primary metric for determining what the best course of action is.
That for every problem solved another dozen are created thanks to people needing busywork.
Some of that busywork translates into added work for the rest of us with no practical benefits.
Kind of like various changes to C and C++ standards over the years and the legacy software that has resulted in us having to maintain/repair/replace.
It's a Kernighan quote:
ÃoeEveryone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?Ã
Without worse-is-better, you make sure the job is completely done before release. So, it takes years to make progress, you end up building an extremely complex system to cover every possibility. Because of that very complexity it is difficult to extend for new requirements, which become apparent after the system is specified and before it was built.
If you want to build a nuclear power plant control system or something equally as critical and unchanging, sure, go ahead and engineer everything out the wazoo. Otherwise, get things done, even if they are "worse".
I'm with you on this. As a programmer, the thing I hate the most is "Gee, Mom, look what I can do!" code -- obtuse code written to impress rather than be simple, obvious and functional. And yes there are indeed times when something mind-bendingly complex is needed to achieve the required goal, but by and large, the KISS principle applies. As to the article's main point, I have to ask what is the purpose of breaking backward compatibility: Making it faster to produce readable, easily maintainable code, being the first one on the block to use something new and shiny, or simply to appear to be one of the Elite? Always keep in mind, however, that programing is more an art than a science, and creativity often comes from the simplest of tools, not the most expensive or the trendiest. And creativity is why we fiddle with all these bits, right?
"My country, right or wrong; if right, to be kept right; and if wrong, to be set right." --Senator Carl Schurz (1872)
IMO scala has similar problems to C++. Compared to Java, it's type system is very dense and hard to get into.
Scala is easy when you write simple things, but hard when APIs force you to use the language's more advanced features or if you want to write an API yourself.
Just look at some of the method signatures in the collection API, they look like Perl scripts instead of argument lists.
Then there is operator overloading, which is sometimes usefuly (like for BigDecimal arithmetic), but often leads to Perl syndrome as well.
Now that Java 8 has some functional support as well, I don't think that Scala will gain much ground any more.
We had FoxPro 6 and Windows 98, when XP hit our desks, FoxPro no longer worked. They made me use (ugh!) MS Access.
So I have a few dozen Access apps when they "upgraded" to Office '03, and not a single one would run. Access had become a completely different program with completely different code and was completely incompatible with Access '98. I had to rewrite every God damned program!
OTOH the NOMAD mainframe databases seldom had glitches. I'd been a PC kind of guy, but NOMAD on the mainframe and Microsoft's stupid, anti-user bullshit started changing my mind.
Free Martian Whores!
So far, I don't think I've seen a single comment here that got the point of the essay.
He's not talking about incremental "improvements" to existing languages, he's pointing out that the common attitude of "we'll make this language easy to learn by making it look like C" is a poor way to achieve any substantial progress.
This is true but everyone who's invested a substantial amount of time learning the dominant, clumsy, descended-from-microcode paradigm is reluctant to dip a toe into anything requiring them to become a true novice again.
I've long been a big fan of what are now called "functional" languages like APL and J - wait, hold on - I know that started alarm bells ringing and red lights flashing for some of you - and find it painful to have to program in the crap languages that still dominate the programming eco-system. Oh look, another loop - let me guess, I'll have to set up the same boilerplate that I've done for every other loop because this language does not have a grammar to let me apply a function across an array. You want me to continue doing math by counting on my fingers when I've got an actual notation that handles arrays at a high level, but I can't use it because it's "too weird". (end rant)
There have been any number of studies - widely ignored in the CS world - going back decades (see this http://cacm.acm.org/magazines/...) - pointing out how poorly dominant programming memes mesh with the way most people think about problems and processes. Meanwhile, the 1960s called - they want their programming languages and debugging "techniques" back - "printf", anyone?
All of my competitors should adopt the author's philosophy of software development immediately. His ivory tower FP idealism is worthy of emulation by all.
I will keep muddling through based on years of experience, leveraging existing code and know-how, maintaining backwards compatibility, planning long-term changes that sometimes take years to complete, deprecating unneeded features in as non-disruptive a manner as possible. And then, when the opportunity arises to do something radically different (like with the C++ "auto" keyword), make it happen. We're called pragmatic programmers. We are clearly losers. Do not emulate what we do.
the growth in cynicism and rebellion has not been without cause
If only we could somehow encapsulate that technical debt as bonds and sell those forward to an organization which then would use the bonds to back up some technical derivatives of sort and sell them forward, saving the middle management from ever thinking about the whole thing. The place of this trading could have a sexy name like "The Cloud", or something.
I would assert precisely the opposite. "trade-offs to preserve compatibility and interoperability" do not cripple the functionality to users-- failures to engineer compatibility and interoperability is what cripples functionality. The number of times that there's been a new feature and I've said "oh, excellent, it's true that my old files no longer work, but this is so wonderful I don't care" has been very close to zero. The number of times there's been a new feature and I've said "those assholes, I have twenty thousand files that don't work any more, what in the world were those idiots thinking?" is decidedly not zero.
And this is why there are so many programming languages with massive overlap in usage. Because once you start down a path, you can never, ever, everver change. If you want something that 42 years down the road that breaks with convention, go create a new language.
Backward compatibility. Which btw Microsoft has broken a time or three.
To accuse the C++ community of not having engaged in "reasoned discussion" about backwards compatibility is silly. Chiusano may not like the tradeoffs that C++ makes (I don't), but they are the result of a glacially slow and tedious community process and discussions. Whatever C++ is, it is by choice and reflection. Furthermore, "worse is better" refers to keeping things simple by cutting corners, and you really can't accuse C++ of keeping things simple.
(Charges about too much backwards compatibility are ironic from someone who promotes Scala, a language that makes many compromises just in order to run on top of the JVM and remain backwards compatible with Java.)
Have gnu, will travel.
So, we're obviously talking about the post-Jobs UIs on iOS and the Mac OS, right?
Well, in that case, worse is worse.
I found that I can determine how bad a programmer is by how much he hates C++. There is a direct correlation. If you hate C++ or find it difficult to learn, there are many job opening for janitors.
Clojure should solve the problem of using too much stack through recursion by properly impelementing tail-recursion. When writing recursive functions, the programmer should always write the function so that it can be "properly tail-recursive". If not, you are saying at the outset that you are creating something that will use unbounded memory to do a computation that *could* always be done in a fixed memory size. Writing a recursive function that is not properly tail-recursive is simply bad programming and an anti-pattern. Either refactor the algorithm into something iterative or make it properly tail-recursive. Then, the max stack size will never be an issue.
"Worse is better" is usually related to LEAVING OFF features which would be considered extraneous. I dare you to find any language with more features than C++. That's a hilariously bad example, if anything, he's complaining about the existence of a feature, namely reverse compatibility... Which the software would be (in his opinion) better without. So he's basically arguing FOR "worse is better" in TFA, although he doesn't seem to realize it.
Backwards compatibility is a good thing, but too much of it can be bad. There are glaring errors in languages which have not been fixed in the name of some faux backwards compatibility argument.
I'll start with one that was fixed.... thirty years after the fact, all the while arguing that it couldn't be fixed, in the name of backward compatibility. The example? ANSI C gets the right answer for sqrt(2) while the original C didn't.
An example of things that C got wrong and have yet to be fixed? the bug inducing = assignment operator, the lack of arrays bound check and the completely unnecessary and time wasting #include <stdio.h> at the beginning of every program.
Observe that those glitches were blindly copied by most C language derivatives (C++, Java, C#, Scala).
I'm not a big fan of Go, but at least if goes back to the := assignment operator.
The outcome of everyone solving their own narrow short-term problems and never really revisiting the solutions is the sea of accidental complexity we now operate in, and which we all recognize is a problem.
It strikes me that this describes our economic system as well.
"What the American public doesn't know is what makes them the American public." -Ray Zalinsky (Tommy Boy)
No need to get all twisted up over quality and function. I was just on a major health insurance provider website and it's seemingly unable to produce lists of providers nor even display the right coverage that I have or even the plans I signed up for. But luckily logon was a bitch and the whole thing is clunky slow.
I think we're going with shitty is good enough, and if it's not, then fuck you anyhow.
I can answer these, as I was there.
"Hey, how come this new version of Mac OS doesn't work with any of my old Mac OS 9 software?", said Mac users in response to Classic support being dropped with the release of Mac OS X 10.5.
Because Apple was unwilling to port the Classic 68K emulator to Intel because of the difference in processor byte order, among other things, making such a port not worthwhile in terms of performance of the Classic software. The user experience would have been crap, and so the decision was made by upper management to not support Classic going forward on Intel.
For the PPC versions of Classic, they could have been supported under Rosetta, but it would have meant an approximate doubling of the number of APIs that were dragged forward onto Intel, for the dubious benefit of "Some Classic software will run, and some won't; sorry the stuff you personally care about doesn't".
"Hey, how come this new version of OS X doesn't work with any of my old PowerPC software?", said Mac users in response to Rosetta being dropped with the release of OS X 10.7.
This one was more related to the lack of a willingness to "freeze-dry" old versions of the libraries. The Mac OS X B&I ("Build and Integration") process required building from scratch the libraries, when building them fat, even though this was a process decision, rather than a technical one.
Effectively, it's not practically possible within the Apple process to reproduce a binary build that's identical to a previous binary build. This is because Mac OS X builds are hosted on a system where the builds depend on being incrementally built into the host environment, rather than actually cross-built to the target. What this means is that the "build from scratch" process to produce the PPC portion of the fat binaries for all the system libraries couldn't be pegged at a particular Mac OS X version, while moving forward with the Intel portion of the binaries, and therefore it was not possible to maintain binary backward compatibility - which was what both Rosetta, and before it, Classic, existed to do.
Debian Linux has this same problem when you build in a chroot to avoid "polluting" the host build environment. It's one of the reasons a build chroot is used by Linaro to support ARM architecture builds on Intel, and that's the same reason that ChromeOS for x86 is built in a chroot environment on a debian variant maintained internally for desktops at Google, rather than being simply directly cross-built into a directory tree hierarchy.
Unlike FreeBSD, neither Linux nor Mac OS X is capable of targeted cross-builds, without pollution of the build/host environment, and without using build products as part of the build.
So technically, the answer for both Linux and Mac OS X is the same: poor build environment engineering - "Worse is Better", exactly what the original article talks about - infects both operating systems.
From TFA: "Other professions, like medicine, the law, and engineering, have values and a professional ethic, where certain things are valued for their own sake." Evidently the author is unfamiliar with common law, in which the law evolves over time via practical application, much as programming languages evolve and mutate. This is contrast to statutory law, which is created from whole cloth, much as one might create a new programming language which has roots in other languages but is fundamentally different from any of them.
If the analogy is apt, "warts" presumably appear in the law. Lawyers, judges, or legislators might wish to remove them. However, practical considerations such as disruption of some existing body of law might prevent that. Also, warts are, by definition, subjective. So, one man's wart might be another man's treasure.
Going back to programming, the use of pointers in C++ is both a wart inherited from C, and a useful feature that can't be removed without fundamentally changing the language. Thus, we have C++ templates for smart pointers, which seek to ameliorate the wart without actually expurgating it.
It's idiomatic in a C++ header that uses extern "C" { ... } to define an interface to be used by both programs written in C and programs written in C++. (When the properly constructed header is included in a C program, the preprocessor eliminates the extern "C" { ... } block.)
The problem is that you don't have to consider just benefits, desirability, goals and values. You have to consider the other side of the equation: cost. And for programming languages like C++, the cost of breaking compatibility can be huge. If you change C++ in a way that isn't compatible with existing behavior, you have to check every single program written in C++ for bugs, errors and just plain failure to compile anymore. The cost of that's going to outweigh just about any benefit short of "creates a literal Heaven on Earth for every single person in the world". It'd be simpler to create a new language based on C++ with the desired changes made to it, which is what tends to happen. The same applies to software frameworks and architectures.
"I wandered off or a while and when I came back they'd added the STL,which provided some badly-needed data structures and language capabilities"
Most of the common STL containers would be a few hours work to write something reasonably functional. Binary tree maps perhaps a day to get working properly but nonetheless, nothing a competetant programmer couldn't do. In fact this was done in C for years without the STL so your complaint is a bit weak.
But when you throw out backwards compatibility, you get syntax horrors like Erlang and R.
No? I rest my case.
Judging by the output of the UX crowd over the past few years, they actually seem to believe that worse is better. It's kindof funny seeing him arguing against the proposition.
Not all C++ compilers handle all C code. Visual C++ never did fully implement C99 (Herb Sutter, in charge of Visual C++, said that those looking for a C99 compiler for Windows should go elsewhere). Since C and C++ are so similar, many implementations will compile C code if presented as C code, for convenience.
This is NOT part of the standard. The standard lays out what a C++ implementation must do, and compiling C programs is not one of them. Many C programs are also valid C++ programs that do the same thing, so those must be compiled. There is a standard way to say that things should be compiled in a way compatible with a C compiler (C has a de facto ABI, unlike many languages). There is no requirement that a C++ compiler compile a C program that is not valid C++.
"When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
Almost all the hacks imposed on C++ to remain compatible with C are linear hacks that don't combine combinatorially. That's what makes these hacks ugly: bending over backwards to achieve hack containment. The C++ standardization literature contains many of the fiercest debates ever waged among pointy hats concerning hack containment. Purity wasn't an option. Impurity segregation was.
The hacks in C++ that do have combinatorial complexity pertain to features of the C++ language completely unrelated to C, such as templates and namespaces.
The bending over backward to avoid non-linear hacks due to compatibility with C got the standards committee into a wee bit of time pressure. Both the template and namespace features were added "on the fly" against the stated policy of the standardization group to only standardize after there was enough experience on the ground to avoid the worst mistakes.
If the standard isn't finished on a timely basis: market fail.
If the standard is finished without templates and namespaces: paradigm fail.
If the standard makes blunders in defining templates and namespaces: an eternal witch's brew.
The committee members rather sanely (and unhappily) chose the least of several competing evils.
There's never been a language like C++ to get otherwise smart people to say stupid things.
* C++ contains many ugly hacks due to its C legacy
* most ugly hacks are combinatorial
* C++ contains many combinatorial hacks
* therefore C++ is riven with combinatorial hacks due to its C legacy
Yes, but the ugly hacks to support C are not the combinatorial hacks, and the combinatorial hacks to support templates and namespaces before their time are not the hacks to support C.
Of course, if you don't delve deeply enough to figure this out, one might just conclude that C++ was concocted by a brigand of insane ideologues. You'd be stupid and wrong, but if your surround yourself with an echo chamber of the equally lazy, there's hardly any detectable social downside (near you).
There's remains, however, this irritating tendency of the world around you not to adopt your favourite "clean" language and put C++ out to pasture once and for allâ"due exclusively to inertia, incompetence, and mendacity. Of course.
The next rank of fierce debate during standardization concerned the elimination of all proposed features where adopting the feature imposed a performance penalty across the board even when it isn't used. A few performance points here and there on a heavy-lifting, industrial programming language quickly adds up to entire data centers. Elegance was never a sufficient argument, unless the performance tax imposed was—at most—barely measurable.
Elegance looks like such a great thing until one begins writing an application at industrial scale. The hacks inherent in making any computational system work efficiently on industrial scale (with smooth degradation around the edge cases, and no crippling instabilities) instantly dwarfs the hackishness of the C++ language itself.
scroll, scroll, "lisp", back.