Live data from Hacker News

John Carmack's comment on Doom 3's code style

kotaku.com

71–80 of 210 posts

Re: John Carmack's comment on Doom 3's code style

#71
post #45

A lot of the practices here are enshrined in the Google C++ styleguide: http://google-styleguide.googlecode.com/svn/trunk/cppguide.x... The author's first point about establishing conventions so that you can re-use the code that works with those conventions is very important. At Google, nobody writes code to serialize/deserialize bytes, because the default answer is just "use protobufs". Nobody writes low-level commu…

> A lot of the practices here are enshrined in the Google C++ styleguide: with the notable exception of lining up things horizontally, which tends to be frowned on.

I'm guessing that Carmack did a lot of assembly language programming and that the vertical alignment comes from that. I've done a ton of assembly programming and I find myself aligning code in C because I find it easier to scan.

Re: John Carmack's comment on Doom 3's code style

#72
post #25

Earlier quoted context omitted.

What do you find so disagreeable about collecting variables at the top of a function? For the most part, I like having all the variable declarations at the top, so it's easy to see what names are in what scope.

void up_front_decls() { float some_var; int another_var; some_var = get_some_var(); do_some_calculations(some_var); maybe_something_else(&some_var); some_var = get_another_var(); do_some_other_calculations(another_var); blah_blah_already_broken(); } void as_needed_decls() { float some_var = get_some_var(); do_some_calculations(some_var); maybe_something_else(&some_var); int some_var = get_another_var(); // compile-ti…

Finally got the silly regex. To align poor_style in vim with the tabularize plugin:

:Tab /\S\s\zs[ ]\S*

Explanation: \S\s* finds a non whitespace character followed by as many whitespace characters as possible. This brings us to the beginning of the variable name. We then use \zs which says that the "found" area should only begin here.

Since we want the * in block_style to be attached to the indented word but not before the variable name, we match either * or space followed by a non-whitespace character to symbolize the beginning of the word. End result:

  void poor_style()
  {
    up_front                declarations;
    also                    encourage;
    this_ridiculous        *block_style;
    that_is                 a_royal_pain;
    to                      maintain;
    because_some_long_type  inevitably;
    screws_it               up;
  }

Re: John Carmack's comment on Doom 3's code style

#73
post #69
post #45

Earlier quoted context omitted.

> A lot of the practices here are enshrined in the Google C++ styleguide: with the notable exception of lining up things horizontally, which tends to be frowned on.

I really do not understand why they chose to do so. In my opinion, it does not improve readability at all, even worse, when the spacing between type and name gets big , your eyes need more work to figure out the correct line relations. Furthermore, this can generate horrible commits, for example: int x; int y; becomes: int x; int y; float z; after adding ONE single variable. But your commit will contain changes for t…

I do that, and I don't find it to be that much of an issue, myself. In my experience, it's rare that I add a new variable to a funtion, so I guess your mileage may vary.

Re: John Carmack's comment on Doom 3's code style

#74
post #50

Earlier quoted context omitted.

Bravo. That comparison makes worrying about vertical space seem ludicrous.

Space is important. Think that you are not writing code, but painting a picture. And you are using space to convey meaning. You literally want to paint code, not write it. :)

Well then you should work in Piet (http://www.dangermouse.net/esoteric/piet.html) :P

Re: John Carmack's comment on Doom 3's code style

#76
post #69
post #45

Earlier quoted context omitted.

> A lot of the practices here are enshrined in the Google C++ styleguide: with the notable exception of lining up things horizontally, which tends to be frowned on.

I really do not understand why they chose to do so. In my opinion, it does not improve readability at all, even worse, when the spacing between type and name gets big , your eyes need more work to figure out the correct line relations. Furthermore, this can generate horrible commits, for example: int x; int y; becomes: int x; int y; float z; after adding ONE single variable. But your commit will contain changes for t…

If trivial whitespace difference causes wrath fill conflicts then I think you have a deeper issue. I can't think of a situation where this would be even a minor issue.

Re: John Carmack's comment on Doom 3's code style

#77
post #51
post #50

Earlier quoted context omitted.

Bravo. That comparison makes worrying about vertical space seem ludicrous.

Ugh. I prefer the Carmack version. This example turns the code into something that appears more airy but in fact is much harder to understand due to extensive use of ? :. I find that one of my own major steps toward programming maturity happened when I stopped doing goofy things like this and started writing code that was as simple as possible to logically follow, and that was as un-special-cased as possible. (By thi…

Basically it's a concise way to do a hard-coded table lookup. Tables are better for structurally regular code than if-else precisely because they restrict what that code can do.

Re: John Carmack's comment on Doom 3's code style

#78

Earlier quoted context omitted.

IntelliJ has inspections for long class and method names. A lot of Java devs run that. Long names are frequently derided in the Ruby community as being Java-like. I can't speak to Haskell at all. But generally whenever something needs to be typed frequently, it tends to be shortened. My favorite is when vowels are deemed too onerous.

Haskell is a special beast, in the sense that it uses single letters a lot for generic types in signatures. Eg: doFoo :: a -> a where doFoo will take any type a and return something of the same type. Due to the density of the language, you'll often find plenty of small, commented functions.

Compare

doubleCompose binary_func transformation first_arg second_arg = binary_func (transformation first_arg) (transformation second_arg)

vs doubleCompose (b -> b -> c) -> (a -> b) -> a -> a -> c doubleCompose (+) f x y = (f x) + (f y)

(also known as the `on` function). There's hardly any good names for x and y, since they can be anything at all.

Re: John Carmack's comment on Doom 3's code style

#79
post #69

Earlier quoted context omitted.

I really do not understand why they chose to do so. In my opinion, it does not improve readability at all, even worse, when the spacing between type and name gets big , your eyes need more work to figure out the correct line relations. Furthermore, this can generate horrible commits, for example: int x; int y; becomes: int x; int y; float z; after adding ONE single variable. But your commit will contain changes for t…

If trivial whitespace difference causes wrath fill conflicts then I think you have a deeper issue. I can't think of a situation where this would be even a minor issue.

Not a huge deal, but it hides the actual author of that line when you're doing a blame. I try to only change the precise lines I need to in a commit, and all of them are relevant to the commit message. That way it's usually a very quick check to see what commit added a certain line.

If I absolutely need to do some tidying in a file, I do it in a fully separate commit so that the change can not be construed to be related to the other feature.

Re: John Carmack's comment on Doom 3's code style

#80
post #63
post #51

Earlier quoted context omitted.

Ugh. I prefer the Carmack version. This example turns the code into something that appears more airy but in fact is much harder to understand due to extensive use of ? :. I find that one of my own major steps toward programming maturity happened when I stopped doing goofy things like this and started writing code that was as simple as possible to logically follow, and that was as un-special-cased as possible. (By thi…

I like the last one better. I think it reads more like "assign one of these values to sides[i]" and less like "do one of these three things". "By this latter I mean, if you change the code a little bit, you don't have to rewrite it; it looks basically the same." I'd say that's kind of the point though. The first one would look "basically the same" if in the last else it assigned to sides[j] instead of sides[i]. In th…

My point is that when you are writing complicated production code, and you are a good programmer such that your rate of features successfully implemented is high, then you will often be going to old code and changing that code to behave somewhat differently than it was before.

When you do this, you want that old code to be like putty. You want to bend it into a new shape without having to break it and start over. Sometimes it really is better to break it, if bending would be too messy or cause problems later or otherwise sets off a red flag in your head. But if you have to break and re-make everything all the time, you won't be a very fast programmer. So you learn how to bend things, elegantly.

And after a while of this, you learn how to write code that is more amenable to elegant bending in the first place. When you type code, you are not just implementing a specific piece of functionality; you are implementing that functionality plus provision for unknown future times when you will need to come back and make the code different.

(To link this more thoroughly to the previous comment: it happens all the time that you write code that is not really about doing stuff, but then you later need to make that code be about doing stuff. Sometimes this is for shipping functionality reasons, sometimes it is just to temporarily insert hooks for debugging. Declaring in advance that this code shall never be about doing stuff is usually a mistake.)

Post reply on HN