Live data from Hacker News

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

kotaku.com

51–60 of 210 posts

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

#51
post #50

I've loved John's code since I saw it first time when the original Quake was leaked from their FTP site through IP spoofing. I was just a kid at that time, and it was an amazing experience to hack it. Yet now, the first example that I saw in this article hurts my eyes. Compare: for ( i = 0; i numVerts ; i++ ) { dot = plane.Distance( in->verts[i] ); dists[i] = dot; if ( dot LIGHT_CLIP_EPSILON ) { sides[i] = SIDE_FRONT…

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 this latter I mean, if you change the code a little bit, you don't have to rewrite it; it looks basically the same. Imagine you want to do more than just assign one variable inside the clauses of the 'if'. In the Carmack version you just add more code there. In the proposed substitute, you have to rewrite the whole thing.)

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

#52
post #11

As someone who has worked with the Doom 3 source code for a mod, I have the opposite opinion. The code very clearly shows a programming team (or programmer) in the process of transitioning from old-school C to C++. Most functions have a huge blob of variable declarations right at the top, as was once necessary in C, even though these variables aren't used until later, or possibly even at all. Usage of const is minima…

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.

Declaring at the top of a function conflicts with the C++ convention of powerful constructors. It's perfectly normal for a C++ class to allocate a lot of memory, open a network socket, or do any other number of heavy-weight things during construction. If you declare all variables at the top of the function, you're forced to have C-style init functions for all data structures that you call separately.

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

#53
post #50

I've loved John's code since I saw it first time when the original Quake was leaked from their FTP site through IP spoofing. I was just a kid at that time, and it was an amazing experience to hack it. Yet now, the first example that I saw in this article hurts my eyes. Compare: for ( i = 0; i numVerts ; i++ ) { dot = plane.Distance( in->verts[i] ); dists[i] = dot; if ( dot LIGHT_CLIP_EPSILON ) { sides[i] = SIDE_FRONT…

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. :)

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

#54
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…

The assignment sides[i] = ... with "? :" formatted as a table (in table notation) should be red as a single statement. It is a relatively common element, you will find in easy to read, once you see it a few hundred times.

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

#55
post #35

Earlier quoted context omitted.

> Clarity can usually be addressed with longer variable or method names, but there's a strong culture against that in nearly ever programming community. It would be interesting to see a list of those that discourage long method and variable names. I haven't seen anything that suggests that Java, Ruby, Python, Haskell, Kotlin, Scala, PHP, Groovy etc. discourage long variable and method names.

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.

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

#56
post #35

Earlier quoted context omitted.

> Clarity can usually be addressed with longer variable or method names, but there's a strong culture against that in nearly ever programming community. It would be interesting to see a list of those that discourage long method and variable names. I haven't seen anything that suggests that Java, Ruby, Python, Haskell, Kotlin, Scala, PHP, Groovy etc. discourage long variable and method names.

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.

While I was writing that, I realised that it may come down to the definition of what constitutes a long method / variable / class name.

I have usually found that the IntelliJ defaults are enough to make the names meaningful. For Ruby, the inspection kicks in at 30 characters. Interestingly, it's referenced from the ruby style guide here: https://github.com/bbatsov/ruby-style-guide where I can't find a recommended maximum length.

We're somewhat sidetracked from the main discussion. I'm generally in favour of trying to write code that is as readable as possible. Ideally in such a way that it is understandable even without the comments.

That said, I do think that good comments are helpful and essential if you're building a library. The Spring Framework comes to mind as a project that has a great set of documentation built from the comments (but also has very readable code, along with long method, variable and class names).

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

#57
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…

Regarding poor_style(), I've never understood this objection (and indeed I prefer the block style you complain about there). Can't your editor fix this up for you in a few keystrokes? This is the sort of thing that an editor should make easy.

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

#58

Earlier quoted context omitted.

I don't see any advantages of declaring variables up front. Not all variables should be at the function scope. Often I have a local variable that is only used inside one branch of a conditional, why should I declare that at the top? Declaring things up front also separates the type from the usage, which makes things harder to read and takes up twice as many lines in some cases.

Maybe I miscommunicated; I'm not against declaring variables at scopes smaller than the function - I declare variables at the top of conditional branches as well. I still don't buy the 'twice as many lines' reason for mixing assignment and declaration.

You should be using const variables as much as possible (and in general preferring immutable data). In that case assignment and declaration _must_ take place at the same location.

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

#59

I've loved John's code since I saw it first time when the original Quake was leaked from their FTP site through IP spoofing. I was just a kid at that time, and it was an amazing experience to hack it. Yet now, the first example that I saw in this article hurts my eyes. Compare: for ( i = 0; i numVerts ; i++ ) { dot = plane.Distance( in->verts[i] ); dists[i] = dot; if ( dot LIGHT_CLIP_EPSILON ) { sides[i] = SIDE_FRONT…

Here's a variant of that ternary chain, used in Perl Best Practices:

  sides[i] = dot  LIGHT_CLIP_EPSILON  ? SIDE_FRONT
                                       : SIDE_ON
                                       ;
This is a little cleaner if your values are longer, and has slightly nicer diffs if you add conditionals.

Note that this won't work in many languages whose ternary operator precedence is different (PHP comes to mind).

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

#60
post #56

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.

While I was writing that, I realised that it may come down to the definition of what constitutes a long method / variable / class name. I have usually found that the IntelliJ defaults are enough to make the names meaningful. For Ruby, the inspection kicks in at 30 characters. Interestingly, it's referenced from the ruby style guide here: https://github.com/bbatsov/ruby-style-guide where I can't find a recommended max…

I can get on board with common sense decision making :-)
Post reply on HN