I found an interview of Stroustrup very compelling and this is in the same direction of my thoughts on similar topics. Hence I thought to keep his entire interview in my blog.
Technology Review: Why is most software so bad?
Bjarne Stroustrup: Some software is actually pretty good by any standards. Think of the Mars Rovers, Google, and the Human Genome Project. That's quality software! Fifteen years ago, most people, and especially most experts, would have said each of those examples was impossible. Our technological civilization depends on software, so if software had been as bad as its worst reputation, most of us would have been dead by now.
On the other hand, looking at "average" pieces of code can make me cry. The structure is appalling, and the programmers clearly didn't think deeply about correctness, algorithms, data structures, or maintainability. Most people don't actually read code; they just see Internet Explorer "freeze."
I think the real problem is that "we" (that is, we software developers) are in a permanent state of emergency, grasping at straws to get our work done. We perform many minor miracles through trial and error, excessive use of brute force, and lots and lots of testing, but--so often--it's not enough.
Software developers have become adept at the difficult art of building reasonably reliable systems out of unreliable parts. The snag is that often we do not know exactly how we did it: a system just "sort of evolved" into something minimally acceptable. Personally, I prefer to know when a system will work, and why it will.
TR: How can we fix the mess we are in?
BS: In theory, the answer is simple: educate our software developers better, use more-appropriate design methods, and design for flexibility and for the long haul. Reward correct, solid, and safe systems. Punish sloppiness.
In reality, that's impossible. People reward developers who deliver software that is cheap, buggy, and first. That's because people want fancy new gadgets now. They don't want inconvenience, don't want to learn new ways of interacting with their computers, don't want delays in delivery, and don't want to pay extra for quality (unless it's obvious up front--and often not even then). And without real changes in user behavior, software suppliers are unlikely to change.
We can't just stop the world for a decade while we reprogram everything from our coffee machines to our financial systems. On the other hand, just muddling along is expensive, dangerous, and depressing. Significant improvements are needed, and they can only come gradually. They must come on a broad front; no single change is sufficient.
One problem is that "academic smokestacks" get in the way: too many people push some area as a panacea. Better design methods can help, better specification techniques can help, better programming languages can help, better testing technologies can help, better operating systems can help, better middle-ware infrastructures can help, better understanding of application domains can help, better understanding of data structures and algorithms can help--and so on. For example, type theory, model-based development, and formal methods can undoubtedly provide significant help in some areas, but pushed as the solution to the exclusion of other approaches, each guarantees failure in large-scale projects. People push what they know and what they have seen work; how could they do otherwise? But few have the technical maturity to balance the demands and the resources.
BS: C++ wasn't designed specifically for the large switching machines, but for a huge range of applications. Bell Labs was the home of an incredible range of interesting projects spanning every scale and using essentially every kind of computer and operating system. But yes, the average Bell Labs programmer was significantly more able than most people's notion of an "average programmer," and reliability and performance (in that order) were considered significantly more important than in most other places.
Performance is still an issue in many of the applications that I'm interested in: responsiveness of interfaces, start-up and close-down time of applications. Software developers have neutralized the astounding performance of modern computer hardware by adding layer upon layer of overelaborate [software] abstractions. We seem to have hit the limits of linear speedup for hardware, but in many cases, we could win a couple of orders of magnitude back from the software.
That said, C++ has indeed become too "expert friendly" at a time where the degree of effective formal education of the average software developer has declined. However, the solution is not to dumb down the programming languages but to use a variety of programming languages and educate more experts. There has to be languages for those experts to use--and C++ is one of those languages.
TR: In retrospect, in designing C++, wasn't your decision to trade off programmer efficiency, security, and software reliability for run time performance a fundamental mistake?
BS: Well, I don't think I made such a trade-off. I want elegant and efficient code. Sometimes I get it. These dichotomies (between efficiency versus correctness, efficiency versus programmer time, efficiency versus high-level, et cetera.) are bogus.
What I did do was to design C++ as first of all a systems programming language: I wanted to be able to write device drivers, embedded systems, and other code that needed to use hardware directly. Next, I wanted C++ to be a good language for designing tools. That required flexibility and performance, but also the ability to express elegant interfaces. My view was that to do higher-level stuff, to build complete applications, you first needed to buy, build, or borrow libraries providing appropriate abstractions. Often, when people have trouble with C++, the real problem is that they don't have appropriate libraries--or that they can't find the libraries that are available.
Other languages have tried to more directly support high-level applications.
That works, but often that support comes at the cost of specialization. Personally, I wouldn't design a tool that could do only what I wanted--I aim for generality.
TR: How do you account for the fact that C++ is both widely criticized and resented by many programmers but at the same time very broadly used? Why is it so successful?
BS: The glib answer is, There are just two kinds of languages: the ones everybody complains about and the ones nobody uses.
There are more useful systems developed in languages deemed awful than in languages praised for being beautiful--many more. The purpose of a programming language is to help build good systems, where "good" can be defined in many ways. My brief definition is, correct, maintainable, and adequately fast. Aesthetics matter, but first and foremost a language must be useful; it must allow real-world programmers to express real-world ideas succinctly and affordably.
The main reason for C++'s success is simply that it meets its limited design aims: it can express a huge range of ideas directly and efficiently. C++ was not designed to do just one thing really well or to prevent people doing things considered "bad." Instead, I concentrated on generality and performance.
I'm sure that for every programmer that dislikes C++, there is one who likes it. However, a friend of mine went to a conference where the keynote speaker asked the audience to indicate by show of hands, one, how many people disliked C++, and two, how many people had written a C++ program. There were twice as many people in the first group than the second. Expressing dislike of something you don't know is usually known as prejudice. Also, complainers are always louder and more certain than proponents--reasonable people acknowledge flaws. I think I know more about the problems with C++ than just about anyone, but I also know how to avoid them and how to use C++'s strengths.
And then, of course, you don't expect proponents of languages that lost out in competition with C++ to be polite about it. Software development doesn't have that degree of professionalism--though I hope it eventually will. Science is different in this respect: when a new tool, technique, or theory wins out, people see that as progress. In software, contributions by competitors and predecessors are not widely acknowledged, appreciated, or even understood.
TR: In The Design and Evolution of C++, you claim that Kierkegaard was an influence on your conception of the language. Is this a joke?
BS: A bit pretentious, maybe, but not a joke. A lot of thinking about software development is focused on the group, the team, the company. This is often done to the point where the individual is completely submerged in corporate "culture" with no outlet for unique talents and skills. Corporate practices can be directly hostile to individuals with exceptional skills and initiative in technical matters. I consider such management of technical people cruel and wasteful. Kierkegaard was a strong proponent for the individual against "the crowd" and has some serious discussion of the importance of aesthetics and ethical behavior. I couldn't point to a specific language feature and say, "See, there's the influence of the nineteenth-century philosopher," but he is one of the roots of my reluctance to eliminate "expert level" features, to abolish "misuses," and to limit features to support only uses that I know to be useful. I'm not particularly fond of Kierkegaard's religious philosophy, though.
TR: What do you regret the most?
BS: No regrets! Well, of course I dream of what I might have done differently and better, but seriously, who am I to second-guess, say, 1984 vintage Bjarne? He may have been less experienced than I, but he was no less smart, probably smarter, and he had a better understanding of the word of 1984 than I have. C++ has been used to build many systems that enhance our lives, and it has been a significant positive influence on later languages and systems. That's something to be proud of.
Technology Review: Name the coolest and lamest programs ever written in C++, and say what worked and didn't work.
Bjarne Stroustrup: Google! Can you even remember the world before Google? (It was only five years ago, after all.) What I like about Google is its performance under severe resource constraints. It possesses some really neat parallel and distributed algorithms. Also, the first Web browsers. Can you imagine the world without the Web? (It was only about 10 years ago.) Other programs that I find cool are examples of embedded-systems code: the scene-analysis and autonomous driving systems of the Mars Rovers, a fuel-injection control for a huge marine engine. There is also some really cool code in Photoshop's image processing and user interfaces. What I like about these programs is how they are structured to be reliable and responsive under pretty harsh resource constraints. Some of Photoshop's ways of managing internal complexity (for instance, the graphical user interface [GUI] layout and access from image-processing algorithms to the pixel data) are just beautiful.
If you look at code itself, rather than considering the resulting program, we could look at something like Shape [an abstract class that defines an interface by which shapes like circles and rectangles can be manipulated in C++], which I borrowed from Simula. It's still the language-technical base of most GUIs, such as the one on your computer or your iPod, or whatever. A more modern example would be the find or the sort algorithm in the Standard Template Library [STL] in C++. That's the language technical basis for much modern high-performance C++ code, especially of programs that need to do simple operations on lots of data. What is common to these examples of code is that they cleanly separate concerns in a program, allowing separate developments of parts. That simplifies understanding and eases maintenance. These basic language techniques allow separate "things" to be separately represented in code and combined only when needed. However, code is something appreciated by programmers, rather than most people. I have always been a bit envious of graphics people, robotics people, etc. What they do is so concrete and visible; what I do is invariably invisible and incomprehensible to most people. I know many mathematicians feel the same way.
Sorry, I'm not going to shame anyone by naming their work "the lamest C++ program ever." It's oh so tempting . . . but no, it wouldn't be fair.
TR: Following structured programming (of which the best known example is Pascal) and object-oriented programming (your own C++), what will be the next big conceptual shift in the design of programming languages? Some years ago, Technology Review put its money on aspect-oriented programming. Does AO represent a conceptual shift of the same kind that OO did?
BS: I hope you didn't put too much money on it! I don't see aspect-oriented programming escaping the "academic ghetto" any day soon, and if it does, it will be less pervasive than OO. When it works, aspect-oriented programming is elegant, but it's not clear how many applications significantly benefit from its use. Also, with AO, it appears difficult to integrate the necessary tools into an industrial-scale programming environment.
One reason I am cautious is that I saw an earlier language built on similar ideas, called R++, struggle to gain acceptance some 15 years ago. It did well for a major application, but repeatedly, enthusiastic people discovered [that] introducing major changes into their tool chains and processes was complicated and expensive, and that educating new developers was difficult and time-consuming. Naturally, aspect-oriented programming may avoid some of these problems, but to succeed it needs to dodge all, and more. In computer science, a major new idea will succeed only if it is sufficiently capable in every relevant area. To succeed on a large scale, a new language must be good enough in all areas (even some the language designer has never heard of), rather than just superb at one or two things (however important). This is a variant of the simple rule that to function, all essential parts of a machine must work; remove one, and the machine stops. The trick is to know which parts are essential. Please note that I'm not saying, "Aspect-oriented programming doesn't work," but to be "the next big thing," you have to provide major gains in an enormously broad range of application areas.
All that said, I don't know what the next major conceptual shift will be, but I bet that it will somehow be related to the management of concurrency. As programmers, we have been notoriously bad at thinking about lots of things happening simultaneously, and soon our everyday computers will have 32 cores.
You didn't mention generic programming. It is definitely worth thinking about in this context. Over the last decade, it has made a major change to the way C++ libraries are designed and has already led to the addition of language features in Java and C#. I don't think of generic programming as the "next paradigm," because C++ has directly supported it since about 1990, and the C++ standard library crucially depends on it. What if the next big thing has already arrived and nobody (except programmers) noticed?
It's worth noting, perhaps, that I don't actually believe in a popular [use] of the word "paradigm" (that derives from Thomas Kuhn's ideas in The Structure of Scientific Revolutions) when it is applied to programming. I do not believe that a paradigm completely replaces previous paradigms in one revolutionary moment (or "shift"). Instead, each programming paradigm adds to what worked previously, and as a paradigm matures, it is increasingly integrated with previous paradigms. Kristen Nygaard was fond of saying that multiplication didn't completely replace addition, and, by analogy, whatever would come after object-oriented programming would include object-oriented programming as a subset. I tend to agree. The evolution of C++ was guided by this view, and the evolution of Java and C# provides further examples.
TR: Computer languages remain generally difficult to learn. One might argue that for computers to become more than "helper" tools that enable mass computations and widespread communications, they must evolve again--and one key may be in simplifying the process of coding so that more individuals are able to participate in development.
BS: I think that would be misguided. The idea of programming as a semiskilled task, practiced by people with a few months' training, is dangerous. We wouldn't tolerate plumbers or accountants that poorly educated. We don't have as an aim that architecture (of buildings) and engineering (of bridges and trains) should become more accessible to people with progressively less training. Indeed, one serious problem is that currently, too many software developers are undereducated and undertrained.
Obviously, we don't want our tools--including our programming languages--to be more complex than necessary. But one aim should be to make tools that will serve skilled professionals--not to lower the level of expressiveness to serve people who can hardly understand the problems, let alone express solutions. We can and do build tools that make simple tasks simple for more people, but let's not let most people loose on the infrastructure of our technical civilization or force the professionals to use only tools designed for amateurs.
In any case, I don't think it is true that the programming languages are so difficult to learn. For example, every first-year university biology textbook contains more details and deeper theory than even an expert-level programming-language book. Most applications involve standards, operating systems, libraries, and tools that far exceed modern programming languages in complexity. What is difficult is the appreciation of the underlying techniques and their application to real-world problems. Obviously, most current languages have many parts that are unnecessarily complex, but the degree of those complexities compared to some ideal minimum is often exaggerated.
We need relatively complex language to deal with absolutely complex problems. I note that English is arguably the largest and most complex language in the world (measured in number of words and idioms), but also one of the most successful.
TR: Please talk about the pros and cons of maintaining backward compatibility with the existing knowledge base (for example, consider your determination to maintain high compatibility to C when you developed C++). It might seem that a clean break would produce leaps of progress; but is this really a realistic proposition?
BS: Java shows that a (partial) break from the past--supported by massive corporate backing--can produce something new. C++ shows that a deliberately evolutionary approach can produce something new--even without significant corporate support. To give an idea of scale: I don't know what the marketing budget for Java has been so far, but I have seen individual newspaper advertisements that cost more than the total of AT&T's C++ marketing budget for all time. "Leaps" can be extremely costly. Is such money well spent? Maybe from the point of view of corporate budgets and corporate survival, but given a choice (which of course I'll never have), I'd spend that money on research and development of evolutionary changes. Note that almost by definition, research money is used to fund attempted leaps that tend to fail while competing with evolutionary changes.
However, evolution shouldn't be an excuse for doing things the way we've always done them. I would like for evolutionary changes to occur at a faster pace than they do in C++, and I think that's feasible in theory. However, that would require funding of "advanced development," "applied research," and "research into application" on a scale that I don't see today. It would be essential to support the evolution of languages and libraries with tools to ease upgrades of real systems and tools that allowed older applications to survive in environments designed for newer systems. Users must be encouraged to follow the evolutionary path of their languages and systems. Arrogantly damning older code as "legacy" and recommending "just rewrite it" as a strategy simply isn't good enough. "Evolutionary languages" tend to be very conservative in their changes because there is no concept of supporting upgrades. For example, I could imagine accepting radical changes in source code if the change was universally supported by a solid tool for converting from old style to new style. In the absence of such tools, language developers must be conservative with the introduction of new features, and application developers must be conservative with the use of language features.
One problem with an evolutionary approach is that there are few academic outlets for incremental change--especially not when that incremental change directly relates to real-word systems. This is a sign that computer science and software engineering haven't yet emerged as the theoretically and empirically well-founded foundation of real-world software development. Theory and practice seem rarely to meet, and researchers are pushed away from real-world software towards less messy academic topics. Conversely, many developers completely ignore research results.
A major issue in language evolution is control of its direction. For a new language, users have a choice: they can adopt it or not (though this becomes less clear-cut if the new language is heavily pushed by their platform supplier). But once they use a language, it is harder to ignore new features (e.g., one user might not like a feature, but a colleague or a library supplier may think it great and use it). And it is impossible to ignore incompatible changes. The ISO C++ standards process relies on volunteers, who can devote only part of their time to the standards work. This implies that it is slow moving. It also seems to imply that end users are consistently underrepresented compared to suppliers of compilers and tools. Fortunately, the C++ committee has always been able to attract many dozens of active members for its meetings and many more online, so it avoided the parochialism of a small group. Until very recently, academics have been completely absent.
C++ provides a nice, extended case study in the evolutionary approach. C compatibility has been far harder to maintain than I or anyone else expected. Part of the reason is that C has kept evolving, partially guided by people who insist that C++ compatibility is neither necessary nor good for C. Another reason-- probably even more important--is that organizations prefer interfaces that are in the C/C++ subset so that they can support both languages with a single effort. This leads to a constant pressure on users not to use the most powerful C++ features and to myths about why they should be used "carefully," "infrequently," or "by experts only." That, combined with backwards-looking teaching of C++, has led to many failures to reap the potential benefits of C++ as a high-level language with powerful abstraction mechanisms.
Friday, April 15, 2011
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment