John Carmack discusses the art and science of software engineering

I’m not really a hard core gamer any­more, but my fas­ci­na­tion with pro­gram­ming did begin with video games (and specif­i­cally, ren­der­ing algo­rithms). So when I saw John Carmack’s 2012 Quake­Con keynote show up in my feed, I thought I’d lis­ten to a bit of it and learn a bit about the state of game design and development.

What I heard instead was a hacker’s hacker talk about his recent real­iza­tion that soft­ware engi­neer­ing is actu­ally a social sci­ence. Across 10 min­utes, he cov­ers many human aspects of devel­oper mis­takes, pro­gram­ming lan­guage design, sta­tic analy­sis, code reviews, devel­oper train­ing, and cost/benefit analy­ses. The empha­sis through­out is mine (and I also tran­scribed this, so I apol­o­gize for any mistakes).

In try­ing to make the games faster, which has to be our pri­or­ity going for­ward, we’ve made a lot of mis­takes already with Doom 4, a lot of it is water under the bridge, but pri­or­i­tiz­ing that can help us get the games done faster, just has to be where we go. Because we just can’t do this going, you know, six more years, what­ever, between games.

On the soft­ware devel­op­ment side, you know there was an inter­est­ing thing at E3, one of the inter­views I gave, I had men­tioned some­thing about how, you I’ve been learn­ing a whole lot, and I’m a bet­ter pro­gram­mer now than I was a year ago and the inter­viewer expressed a lot of sur­prise at that, you know after 20 years and going through all of this that you’d have it all fig­ured out by now, but I actu­ally have been learn­ing quite a bit about soft­ware devel­op­ment, both on the per­sonal crafts­man level but also pay­ing more atten­tion by what it means on the team dynam­ics side of things. And this is some­thing I prob­a­bly avoided look­ing at squarely for years because, it’s nice to think of myself as a sci­en­tist engi­neer sort, deal­ing in these things that are abstract or prov­able or objec­tive on there and there.

In real­ity in com­puter sci­ence, just about the only thing that’s really sci­ence is when you’re talk­ing about algo­rithms. And opti­miza­tion is an engi­neer­ing. But those don’t actu­ally occupy that much of the total time spent pro­gram­ming. You know, we have a few pro­gram­mers that spend a lot of time on opti­miz­ing and some of the select­ing of algo­rithms on there, but 90% of the pro­gram­mers are doing pro­gram­ming work to make things hap­pen. And when I start to look at what’s really hap­pen­ing in all of these, there really is no sci­ence and engi­neer­ing and objec­tiv­ity to most of these tasks. You know, one of the pro­gram­mers actu­ally says that he does a lot of mon­key programming—you know beat­ing on things and mak­ing stuff hap­pen. And I, you know we like to think that we can be smart engi­neers about this, that there are objec­tive ways to make good soft­ware, but as I’ve been look­ing at this more and more, it’s been strik­ing to me how much that really isn’t the case.

Aside from these that we can mea­sure, that we can mea­sure and repro­duce, which is the essence of sci­ence to be able to mea­sure some­thing, repro­duce it, make an esti­ma­tion and test that, and we get that on opti­miza­tion and algo­rithms there, but every­thing else that we do, really has noth­ing to do with that. It’s about social inter­ac­tions between the pro­gram­mers or even between your­self spread over time. And it’s nice to think where, you know we talk about func­tional pro­gram­ming and lambda cal­cu­lus and mon­ads and this sounds all nice and sci­ency, but it really doesn’t affect what you do in soft­ware engi­neer­ing there, these are all best prac­tices, and these are things that have shown to be help­ful in the past, but really are only help­ful when peo­ple are mak­ing cer­tain classes of mis­takes. Any­thing that I can do in a pure func­tional lan­guage, you know you take your most restric­tive sci­en­tific ori­ented code base on there, in the end of course it all comes down to assem­bly lan­guage, but you could exactly the same thing in BASIC or any other lan­guage that you wanted to.

One of the things that’s also fed into that is my older son’s start­ing to learn how to pro­gram now. I actu­ally tossed around the thought of should I maybe have him try to learn Haskell as a 7 year old or some­thing and I decided not to, that I, you know, I don’t think that I’m a good enough Haskell pro­gram­mer to want to instruct any­body in any­thing, but as I start think­ing about how some­body learns pro­gram­ming from really ground zero, it was open­ing my eyes a lit­tle bit to how much we take for granted in the soft­ware engi­neer­ing com­mu­nity, really is just lay­ers of arti­fice upon top a core fun­da­men­tal thing. Even when you go back to struc­tured pro­gram­ming, whether it’s while loops and for loops and stuff, at the bot­tom when I’m sit­ting think­ing how do you explain pro­gram­ming, what does a com­puter do, it’s really all the way back to flow charts. You do this, if this you do that, if not you do that. And, even try­ing to explain why do you do a for loop or what’s this while loop on here, these are all con­ven­tions that help soft­ware engi­neer­ing in the large when you’re deal­ing with mis­takes that peo­ple make. But they’re not fun­da­men­tal about what the computer’s doing. All of these are things that are just try­ing to help peo­ple not make mis­takes that they’re com­monly making.

One of the things that’s been dri­ven home extremely hard is that pro­gram­mers are mak­ing mis­takes all the time and con­stantly. I talked a lot last year about the work that we’ve done with sta­tic analy­sis and try­ing to run all of our code through sta­tic analy­sis and get it to run squeaky clean through all of these things and it turns up hun­dreds and hun­dreds, even thou­sands of issues. Now its great when you wind up with some­thing that says, now clearly this is a bug, you made a mis­take here, this is a bug, and you can point that out to every­one. And every­one will agree, okay, I won’t do that next time. But the prob­lem is that the best of inten­tions really don’t mat­ter. If some­thing can syn­tac­ti­cally be entered incor­rectly, it even­tu­ally will be. And that’s one of the rea­sons why I’ve got­ten very big on the sta­tic analy­sis, I would like to be able to enable even more restric­tive sub­sets of lan­guages and restrict pro­gram­mers even more because we make mis­takes con­stantly.

One of the things that I started doing rel­a­tively recently is actu­ally doing a daily code review where I look through the check­ins and just try to find some­thing edu­ca­tional to talk about to the team. And I anno­tate a lit­tle bit of code and say, well actu­ally this is a bug dis­cov­ered from code review, but a lot of it is just, favor doing it this way because it’s going to be clearer, it will cause less prob­lems in other cases, and it ruf­fled, there were a few peo­ple that got ruf­fled feath­ers early on about that with the kind of broad­cast nature of it, but I think that every­body is appre­ci­at­ing the process on that now. That’s one of those scal­a­bil­ity issues where there’s clearly no way I can do indi­vid­ual code reviews with every­one all the time, it takes a lot of time to even just scan through what every­one is doing. Being able to point out some­thing that some­body else did and say well, every­body should pay atten­tion to this, that has some real value in it. And as long as the team is agree­able to that, I think that’s been a very pos­i­tive thing.

But what hap­pens in some cases, where you’re argu­ing a point where let’s say we should put const on your func­tion para­me­ters or some­thing, that’s hard to make an objec­tive call on, where lots of stuff we can say, this indi­rec­tion is a cache miss, that’s going to cost us, it’s objec­tive, you can mea­sure it, there’s really no argu­ing with it, but so many of these other things are sort of style issues, where I can say, you know, over the years, I’ve seen this cause a lot prob­lems, but a lot of peo­ple will just say, I’ve never seen that prob­lem. That’s not a prob­lem for me, or I don’t make those mis­takes. So it has been really good to be able to point out com­monly on here, this is the mis­take caused by this.

But as I’ve been doing this more and more and think­ing about it, that sense that this isn’t sci­ence, this is just try­ing to deal with all of our human frail­ties on it, and I wish there were bet­ter ways to do this. You know we all want to become bet­ter devel­op­ers and it will help us make bet­ter prod­ucts, do a bet­ter job with what­ever we’re doing, but the fact that it’s com­ing down to train­ing dozens of peo­ple to do things in a con­sis­tent way, know­ing that we have pro­gram­mer turnover as peo­ple come and go, new peo­ple com­ing and look­ing at the code base and not under­stand­ing the con­ven­tions, and there are clearly bet­ter and worse ways of doing things but it’s frus­trat­ingly dif­fi­cult to quan­tify.

That’s some­thing that I’m spend­ing more and more time look­ing at. I read NASA’s soft­ware engi­neer­ing lab­o­ra­tory reports and I can’t seem to get any real value out of a lot of those things. The things that have been valu­able have been auto­mated things, things that don’t require a human to have some analy­sis, have some eval­u­a­tion of it, but just say, enforced or not enforced. And I think that that’s where really where things need to go as larger and larger soft­ware gets devel­oped. And it is strik­ing the scale of what we’re doing now. If you look back at the NASA reports and the scale of things and they con­sid­ered large code bases to be things with three or four hun­dred thou­sand lines of code. And we have far more than that in our game engines now. It’s kind of fun to think that the game engines, things that we’re play­ing games on, have more sophis­ti­cated soft­ware than cer­tainly the things that launch peo­ple to the moon and back and flew the shut­tle, ran Sky­lab, run the space sta­tion, all of these mas­sive projects on there are really out­done in com­plex­ity by any num­ber of major game engine projects.

And the answer is as far as I can tell really isn’t out there. With the NASA style devel­op­ment process, they can deliver very very low bug rates, but it’s at a very very low pro­duc­tiv­ity rate. And one of the things that you wind up doing in so many cases is cost ben­e­fit analy­ses, where you have to say, well we could be per­fect, but then we’ll have the wrong prod­uct and it will be too late. Or we can be really fast and loose, we can go ahead and just be sloppy but we’ll get some­thing really cool hap­pen­ing soon. And this is one of those areas where there’s clearly right tools for the right job, but what hap­pens is you make some­thing really cool really fast and then you live with it for years and you suf­fer over and over with that. And that’s some­thing that I still don’t think that we do the best job at.

We know our code is liv­ing for, real­is­ti­cally, we’re look­ing at a decade. I tell peo­ple that there’s a good chance that what­ever you’re writ­ing here, if it’s not extremely game spe­cific, may well exist a decade from now and it will have hun­dreds of pro­gram­mers, look­ing at the code, using it, inter­act­ing with it in some way, and that’s quite a bur­den. I do think that it’s just and right to impose pretty severe restric­tions on what we’ll let past analy­sis and what we’ll let into it, but there are large scale issues at the soft­ware API design lev­els and fig­ur­ing out things there, that are artis­tic, that are crafts­man like on there. And I wish that there were more quan­tifi­able things to say about that. And I am spend­ing a lot of time on this as we go forward.

27 thoughts on “John Carmack discusses the art and science of software engineering

  1. Wow — the ref­er­enced video is over 3.5 hours long. I would have liked to have watched the 10 min­utes you were ref­er­enc­ing, per­haps you could list which point to watch (for exam­ple 1:23:45 — 1:33:00).

  2. I recently had the same feel­ing about the last three para­graphs. we have some good engi­neers and design­ers con­stantly fight­ing for a good “design”, every­one has their own ideas and method­olo­gies, but no one has a way of mea­sur­ing it’s “cor­rect­ness” or whether it’s future proven. Even though this post won’t help us to solve these “social con­flicts” in soft­ware devel­op­ment, i think you made a valid point of view and pointed out some direc­tions. Could be a nice piece of research project.

    • While there aren’t great ways of mea­sur­ing the ben­e­fits of a method­ol­ogy yet, this is an active area of soft­ware engi­neer­ing research. In fact, there are prob­a­bly over 50 stud­ies done that eval­u­ate dif­fer­ent method­olo­gies pub­lished every year, largely funded by the National Sci­ence Foun­da­tion in the U.S. Some of my col­leagues have a nice blog that sum­ma­rizes some of their find­ings.

  3. What about goal-directed pro­gram­ming?
    I really like Uni­con, which is (sadly) so under­rated!
    Uni­con, how­ever, sup­ports other par­a­digms too.

  4. I’d really enjoy observ­ing the process that he’s try­ing to man­age and read­ing through some of the code. Part of what makes the process dif­fer­ent, of course, is that they pro­duce enter­tain­ment, which means the end result is only con­strained by the per­cep­tual and con­cep­tual adapt­abil­ity of the play­ers. That gives them the free­dom to “try things” in a way that would cause unac­cept­able risk of major eco­nomic dis­rup­tions if attempted at Amex or GE.
    His coach­ing process is inter­est­ing. I won­der if he main­tains an orga­nized defect wiki.

  5. I’m really sur­prised that he doesn’t see func­tional pro­gram­ming as a solu­tion to all of this. I mean, yes, when it comes down to it, it really is just assem­bly, how­ever, what’s really impor­tant is all of the higher level abstrac­tions you can cre­ate and mod­ify with ease. I think that func­tional pro­gram­ming allows you to explain the solu­tion in the terms of it’s con­text. And I’m not say­ing that it’s some­thing that declar­a­tive pro­gram­ming can’t do. I’m sim­ply say­ing that declar­a­tive pro­gram­ming causes you to repeat your­self more often, thus caus­ing more bugs.

    • By “declar­a­tive” pro­gram­ming do you mean, “imperative”?

      Func­tional pro­gram­ming can make it quite dif­fi­cult to describe oper­a­tional seman­tics. Yet, con­trol­ling oper­a­tional seman­tics is really a big deal in writ­ing games.

      • Agreed. And I agree with the sen­ti­ments in your keynote more gen­er­ally: the pur­pose of most pro­gram­ming lan­guage fea­tures are to pre­vent mis­takes while try­ing to pre­serve other qual­i­ties such as expres­sive­ness, read­abil­ity, learn­abil­ity, etc. Func­tional lan­guages are excel­lent at pre­vent­ing mis­takes, but in trade, they can increase the dif­fi­culty of both read­ing and author­ing many types of behav­ior. Defects aren’t the only pri­or­ity in engi­neer­ing com­plex software.

    • Agreed, I mean with all due respect, cos he’s JC, and I’m just some peon, but couldn’t you dis­miss the whole of soft­ware engi­neer­ing prac­tice by say­ing “it’s all just assem­bly, evrn­rually”. The point is not what it becomes, but how we get it there. It’d like he does a talk about the mys­te­ri­ous social fac­tors while they are star­ing him in the face.

      Pre­sums­bly this is really evi­dence of how my world­view is messed up. Because his wv seems to be work­ing out ok. But what if he’s actu­ally wrong on stuff like lan­guage choice, but he’s just so damn smart that it hasn’t held him back enough for him to realise it?

      I won­der, some­times, if the very bright­est aren’t attracted to things that are slightly masochis­tic, just because they can, and then the rest if us are lead down the gar­den path by their highly intel­li­gent jus­ti­fi­ca­tions. Which are, ulti­mately, actuelly wrong. Or at least not remotely as widely applic­a­ble as supposed.

      But what do I know? Plus, I’m drunk. You don’t wanna lis­ten to me. Go fol­low the shiny.

  6. I can’t help but think that a good ‘programmer’s helper’ AI will solve a lot of these prob­lems, but this would require an expert sys­tem that can develop a syn­tac­tic bridge between ‘what I want the code to do’ and ‘what the code needs to look like to accom­plish my goals’. Maybe not a sys­tem that takes input in plain eng­lish, but some­thing like a drag-and-drop UI, or a visu­ally abstract rep­re­sen­ta­tion of a program’s flow.

    If you can write sta­tic tests that ana­lyze code and detect bugs, you could the­o­ret­i­cally write code that ‘fixes’ those bugs — you just need to know what you want the code to do, and what the ‘cor­rect’ fix is.

    I think this is essen­tially what Mr. Car­mack is talk­ing about when he says he wants more ‘restric­tive’ lan­guages. Imag­ine an IDE where you lit­er­ally can’t write a bug — per­haps all of NASA’s strict bug check­ing is auto­mat­i­cally imple­mented as you write code, or per­haps you don’t actu­ally ‘code’ in the tra­di­tional sense, you just sym­bol­i­cally link ‘pro­gram flow con­trol’ blocks together like in the Unreal Engine SDK.

    • There are a lot of pos­si­bil­i­ties in this space. Although, as a researcher who’s well aware of the past 40 years of research on this topic, I’m not opti­mistic. Most of these approaches only work well in a small num­ber of sit­u­a­tions and are com­pletely use­less in other sit­u­a­tions. The rea­son for this is that the intended, spec­i­fied behav­ior is never really known by a com­puter, even after an imple­men­ta­tion is laid down to achieve it, and the task of spec­i­fy­ing the intended behav­ior is almost always more work then just imple­ment­ing the behav­ior itself. And even then, spec­i­fi­ca­tions change and code doesn’t always reflect these changes.

        • I wrote one a few years ago that cov­ers some of these tech­niques for small programs.

          Ko, A.J., Abra­ham, R., Beck­with, L., Black­well, A., Bur­nett, M.M., Erwig, M., Scaf­fidi, C., Lawrance, J., Lieber­man, H., Myers, B.A., Rosson, M.B., Rother­mel, G., Shaw, M., and Wieden­beck, S. (2011). The State of the Art in End-User Soft­ware Engi­neer­ing. ACM Com­put­ing Sur­veys 43, 3, Arti­cle 21 (April 2011), 44 pages.

          Most of the sys­tems cov­ered in that paper are inter­ac­tive tools to help devel­op­ers find and fix defects.

    • It’s not pos­si­ble to have a gen­eral pur­pose lan­guage in which it’s not pos­si­ble to write a bug.

      Turing’s halt­ing prob­lem says that you can’t have a pro­gram that can deter­mine (in all cases) even whether the pro­gram will halt or not.

      So, pro­gram­ming tools can­not cal­cu­late all prop­er­ties of pro­gram­ming prob­lems that require exit­ing for correctness.

      But it is pos­si­ble to have restricted lan­guages that are poten­tially bug free, with respect to a spec­i­fi­ca­tion; but it’s also not nec­es­sar­ily pos­si­ble to prove the spec­i­fi­ca­tion bug-free either!

  7. Thanks for doing this, it’s nice to read again after watch­ing the talk a while ago.

    One small edit — it has been a while since I heard the talk but I’m fairly sure “cache list” should be “cache miss”. It seems to work in con­text as well.

  8. That’s the voice of an older pro­gram­mer, some­one who’s been through a lot of work and whose clas­sic younger-programmer self assur­ance has gone. It’s com­fort­ing to know that it hap­pens even to Carmack.

    • Doing pro­gram­ming for ten years, i am start­ing to lose self assur­ance. i am ever more putting “soft­ware engi­neer­ing” and defenses and all of these “crap”, that is slow­ing me down, or just is the age (i am 25). In the end, code is to be deliv­ered, and only on real world it has value.
      Per­haps we need only to embrace that bugs is nor­mal, as long as we are human. Now i am think­ing i need to make some­thing just for fun, just cod­ing, for­get­ing all these forty years “soft­ware engi­neer­ing” stuff, but i am los­ing inter­est on pro­gram­ming.
      Per­haps its some sort of con­fort to know that this can hap­pen to “gods” like Car­mack, or not, that even he cant escape from des­tiny.
      Its all sad.
      ps: sorry my poor writ­ing skills.

      • Errors, mis­takes, and unex­pected side-effects have noth­ing to do with being “human”. Ada Lovelace wrote the first pro­gram only about 170 years ago, and the first “bug” was found by Grace Hop­per about 70 years ago. Nature’s been doing it for over 2 bil­lion years, and there are still plenty of genetic bugs, which can have unex­pected *ben­e­fits*. If “flaw­less” AIs wrote pro­grams with­out bugs, they would have no value. Bugs aren’t some­thing to be avoided, but embraced. Sep­a­rat­ing what’s a bug and what’s a fea­ture is what’s impor­tant, if you try so hard to pre­vent the for­mer you also inhabit the latter.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>