As I noted previously, I recently gave a Tech Talk at Google on DTrace. When I gave the talk, I was in the middle of reading Scott Rosenberg’s Dreaming in Code, and (for whatever poorly thought-out reason) I elected to use my dissatisfaction with the book as an entree into DTrace. I think that my thinking here was to use what I view to be Rosenberg’s limited understanding of software as a segue into the more general difficulty of understanding running software — with that of course being the problem that DTrace was designed to solve.
However tortured that path of reasoning may sound now, it was much worse in the actual presentation — and in terms of Dreaming in Code, my introduction comes across as a kind of gangland slaying of Rosenberg’s work. When I saw the video, I just cringed, noted with relief that at least the butchery was finished by five minutes in, and hoped that viewers would remember the meat of the presentation rather than the sloppy hors d’oeuvres.
I was stupidly naive, of course — for as soon as so much as one blogging observer noted the connection between my presentation and the book, Google-alerted egosurfing would no doubt take over and I’d be completely busted. And that is more or less exactly what happened, with Rosenberg himself calling me out on my introduction, complaining (rightly) that I had slagged his book without providing much substance. Rosenberg was particularly perplexed because he felt that he and I are concluding essentially the same thing. But this is not quite the case: the conclusion (if not mantra) of his book is that “software is hard”, while the point I was making in the Google talk is not so much that developing software is hard, but rather that software itself is wholly different — that it is (uniquely) a confluence between information and machine. (And, in particular, that software poses unique observability challenges.)
This sounds like a really pedantic difference — especially given that Rosenberg (in both book and blog entry) does make some attempt to show the uniqueness of software — but the difference is significant: instead of beginning with software’s information/machine duality, and from there exploring the difficulty of developing it, Rosenberg’s work has at its core the difficulty itself. That is, Rosenberg uses the difficulty of developing software as the lens to understand all of software. And amazingly enough, if you insist on looking at the world through a bucket of shit, the world starts to look an awful lot like a bucket of shit: by the end of the book, Rosenberg has left the lay reader with the sense that we are careering towards some sort of software heat-death, after which meetings-about-meetings and stickies-on-whiteboards will prevent all future progress.
It’s not clear if this is the course that Rosenberg intended to set at the outset; in his Author’s Note, he gives us his initial bearings:
Why is good software so hard to make? Since no one seems to have a definitive answer even now, at the start of the twenty-first century, fifty years deep into the computer era, I offer by way of exploration the tale of the making of one piece of software.
The problem is that the “tale” that he tells is that of the OSAF’s Chandler, a project plagued by metastasized confusion. In fact, the project is such a wreck that it gives rise to a natural question: did Rosenberg pick a doomed project because he was convinced at the outset that developing software was impossible, and he wanted to be sure to write about a project that wouldn’t hang the jury? Or did his views of the impossibility of developing software come about as a result of his being trapped on such a reeking vessel? On the one hand, it seems unimaginable that Rosenberg would deliberately book his passage on the Mobro 4000, but on the other, it’s hard to imagine how a careful search would have yielded a better candidate to show just how bad software development can get: PC-era zillionaire with too many ideas funds on-the-beach programmers to change the world with software that has no revenue model. Yikes — call me when you ship something…
By the middle of the book it is clear that the Chandler garbage barge is adrift and listing, and Rosenberg, who badly wants the fate of Chandler to be a natural consequence of software and not merely a tale of bad ideas and poor execution, begins to mark time by trying to find the most general possible reasons for this failure. And it is this quest that led to my claim in the Google video that he was “hoodwinked by every long-known crank” in software, a claim that Rosenberg objects to, noting that in the video I provided just one example (Alan Kay). But this claim I stand by as made — and I further claim that the most important contribution of Dreaming in Code may be its unparalleled Tour de Crank, including not just the Crank Holy Trinity of Minsky/Kurzweil/Joy, but many of the lesser known crazy relations that we in computer science have carefully kept locked in the cellar. Now, to be fair, Rosenberg often dismisses them (and Kapor put himself squarely in the anti-Kurzweil camp with his 2029 bet), but he dismisses them not nearly often enough or swiftly enough — and by just presenting them, he grants many of them more than their due in terms of legitimacy.
So how would a change in Rosenberg’s perspective have yielded a different work? For one, Rosenberg misses what is perhaps the most profound ramification of the information/machine duality: that software — unlike everything else that we build — can achieve a timeless and absolute perfection. To be fair, Rosenberg comes within sight of this truth — but only for a moment: on page 336 he opens a section with “When software is, one way or another, done, it can have astonishing longevity.” But just as quickly as hopes are raised, they are dashed to the ground again; he follows up that promising sentence with “Though it may take forever to build a good program, a good program will sometimes last almost as long.” Damn — so close, yet so far away. If “almost as long” were replaced with “in perpetuity”, he might have been struck by the larger fallacies in his own reasoning around the intractable fallibility of software.
And software’s ability to achieve perfection is indeed striking, for it makes software more like math than like traditional engineering domains — after all, long after the Lighthouse at Alexandria crumbled, Euclid’s greatest common divisor algorithm is showing no signs of wearing out. Why is this important? Because once software achieves something approximating perfection (and a surprising amount of it does), it sediments into the information infrastructure: the abstractions defined by the software become the bedrock that future generations may build upon. In this way, each generation of software engineer operates at a higher level of abstraction than the one that came before it, exerting less effort to do more. These sedimenting abstractions also (perhaps paradoxically) allow new dimensions of innovation deeper in the stack: with the abstractions defined and the constraints established, one can innovate underneath them — provided one can do so in a way that is absolutely reliable (after all, this is to be bedrock), and with a sufficient improvement in terms of economics to merit the risk. Innovating in such a way poses hard problems that demand a much more disciplined and creative engineer than the software sludge that typified the PC revolution, so if Rosenberg had wanted to find software engineers who know how to deliver rock-solid highly-innovative software, he should have gone to those software engineers who provide the software bedrock: the databases, the operating systems, the virtual machines — and increasingly the software that is made available as a service. There he still would have found problems to be sure (software still is, after all, hard), but he would have come away with a much more nuanced (and more accurate) view of both the state-of-the-art of software development — and of the future of software itself.