Live data from Hacker News

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

kotaku.com

111–120 of 210 posts

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

#111
post #84
post #79

Earlier quoted context omitted.

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 rela…

Sounds like someone should implement a blame option for "ignore whitespace - show latest author with non-whitespace changes"!

git blame -w already does this: http://www.kernel.org/pub/software/scm/git/docs/git-blame.ht...

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

#112

Earlier quoted context omitted.

It's funny you mention that, as I'm using the companion program ( http://google-styleguide.googlecode.com/svn/trunk/cpplint/cp... ) on the code for my current project right now. My only complaints is that much of the cpplint program checks for arbitrary style choice versus possible issues. Sure, most of the style I agree with, but I've actually hacked on that program a bit because the style guidelines are hardcoded i…

That's my pet peeve about many linters as well - I don't use jslint because it has many of Crockford's personal style tastes embedded in it, several of which I disagree with. In cpplint's (and perhaps jslint's) defense, it was written for one specific organization with broadly-accepted style guidelines, and open-sourced "in the hopes that it'll be useful, but without any warranty of any kind".

jshint was started in part to separate out the actual warnings from Crockford's style in jslint (it is also supposed to be more configurable with regards to style-type comments). It might be worth a look if that is the only reason you disliked jslint.

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

#113
post #7

Earlier quoted context omitted.

John Carmack wrote a nice article about experiences writing functional code in C++ here: http://www.altdevblogaday.com/2012/04/26/functional-programm...

"a function can still be pure even if it calls impure functions, as long as the side effects don’t escape the outer function" This is a very good point that probably could be systematically exploited. Does anyone know examples of this?

In Haskell there is the ST monad can be used to write stateful implementations for pure functions. The type system guarantees that side effects can't escape their scope.

http://www.haskell.org/haskellwiki/Monad/ST

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

#114
post #96

Earlier quoted context omitted.

No, you clearly didn't understand my point. I am talking about maximizing the rate of successful features implemented. Programming things in assembly language is obviously not going to do that. I don't know, man. I have 31 years of programming experience. I am not detecting from your argument that you have anywhere near this level of experience, so I am inclined not to get into this discussion. But I will say that yo…

I'm not even clear that it's clear I didn't understand your point. I guess I have trouble communicating effectively. I thought your point was that flexible control flow structures like if-else allow you to change code quickly and more easily in the future. Wasn't that the point? Assuming I have understood your preference for flexible code, I am simply stating my belief that it is useful to balance this with rigid cod…

Sometimes rigid code is simpler, sure. But what I am arguing is that it is almost never more debuggable / maintainable.

What I am saying is not specific to test and branch, though test and branch is great because it gives you these big code blocks into which you can insert more code and it's clear where that code lives and under what circumstances it runs. Which is something you don't get in assembly language, which is part of why the assembly language reply is a goofy straw-man argument.

Yes, my reply was a bit irritable; I would definitely prefer to have a reasonable discussion, but the assembly-language thing was the first volley in being unreasonable. Putting up a straw man like that is an attempt to win the argument, not an attempt to understand the other person's position. I detected this and decided, well, if that's the position, then it is useless trying to make further / deeper rational arguments, so I am just going to say, this comes from a lot of experience, so take it or leave it.

As fatbird replied, "This is shitty." (I can't reply to his reply yet because of the timed reply thing, so I am including it here.) Maybe it is shitty, I don't know, but it's true and sometimes you just have to say the true thing to be expedient and get on with life.

I don't have time to teach people on the internet how to program. I work my ass off for 4 years at a time to build and ship games that are critically acclaimed and played by millions of people. These are the kinds of things most programmers wish they had the opportunity to work on, and wish that they knew how to build. (Often programmers think they know how to build these things, and then they go try, and they fail. It is a lot harder than one thinks). I am not saying this to brag, because I honestly don't feel braggy about it right now. It's just fact. I am pretty good at programming (probably not as good as Carmack) and I have worked really hard for a long time to be as good as I am. Meanwhile I am also trying to be pretty good at game design, and oh yeah, running a software company.

So when I give advice like this, and someone retorts, and it seems to be coming from a place of lesser experience, it is not really worth my time to get into a serious argument. I am not going to learn anything. I have been in the place where I had that kind of opinion, many years ago, and then I learned more. Fine. I can either be polite and quiet about it, or say something a little bit blunt and rude, in the hope that the other person (and maybe any bystanders to the conversation) will seriously re-consider what was said in light of the new information that it comes from someone who is maybe not a joker. I can't spend a lot more time than that teaching everyone in the internet how to program, because it takes almost all the energy I can muster just to build software. (Though occasionally I do write up stuff about how to program, and give lectures bearing on that subject, like this one: http://the-witness.net/news/2011/06/how-to-program-independe...).

Of course this don't-get-into-the-argument strategy of mine has at least partially failed, since here I am typing out this really long reply. I don't know.

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

#115
post #84
post #79

Earlier quoted context omitted.

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 rela…

Sounds like someone should implement a blame option for "ignore whitespace - show latest author with non-whitespace changes"!

git blame -w

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

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

I would argue that if declaring up-front versus declaring as-needed makes a significant difference in readability, then your functions are too long.

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

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

I agree with jblow. I consider ternary a "sharp knife" in that even though it saves space, I never want to see it used more than one level deep. I don't want sharp knives in my code, I want Lego bricks. If that means the source code is a little bigger or the runtime is a little slower, that's OK, the vast majority of the time.

The most egregious example of I can think of in this kind of thing is JS "gurus" who try to use the fewest semicolons possible in their unminified source. It doesn't add readability, and the semicolon rules are complicated enough that one could easily write a bug while trying to stick to the style.

Sometimes languages have "tricks" that aren't sharp, and those are OK to use when you know them, but one has to distinguish.

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

#118
post #20

My heart grew a little warm with the last paragraph of John Carmack's comment: "The major evolution that is still going on for me is towards a more functional programming style, which involves unlearning a lot of old habits, and backing away from some OOP directions."

He's mentioned before that he's toyed with the idea of switching to Haskell. That wasn't for functional programming though. It was instead for the built-in static code analysis the Haskell type system and compiler provides.

Do you have a link to the source for that? I'm curious to read.

If your description is accurate, Rust[1] is exactly what he wants. I've been learning Rust recently (with a little help from [2]) and it does a ton of static code analysis, is safe by default (no dangling or null pointers, no shared mutable state), uses Hindley-Milner type interface just like Haskell, and generally is what you would expect if Haskell and C++ had a baby.

[1] http://www.rust-lang.org/

[2] http://www.rustforrubyists.com/

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

#119

> C++ code can quickly get unruly and ugly without diligence on the part of the programmers. To see how bad things can get, check out the STL source code. Microsoft's and GCC's[5] STL implementations are probably the ugliest source code I've ever seen. Even when programmers take extreme care to make their template code as readable as possible it's still a complete mess. Take a look at Andrei Alexandrescu's Loki libra…

Any style of programming can look like a mistake if you take it to crazy extremes. I find header/template C++ programming works very well provided you do it in moderation and keep things simple. Remember the STL is complicated because it tries to be super generic, and it tries to be super generic because it's a library so it tries to cater for all possible uses. If you're writing a program instead of a library, you c…

For other examples of crazy extremes, see :

Java Swing using anonymous classes to 10 or more depths to represent callbacks because OOP and inheritance > all.

Haskell having one file IO operation a thousand feet below the surface of a program "un-purifying" the entire call stack with side effects because pure functional is king.

Trying to implement any generic anything in C, because in procedural having template or inheritance based polymorphic behavior is crazy, so you end up with 5 million ways to write readNumber() for every numeric type ever.

So go figure, procedural, meta, functional and OOP all go completely deep end when you try to kitchen sink them as the be all end all solution to all problems and woes.

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

#120
post #106

Earlier quoted context omitted.

It depends. But in this particular case, some trivial extra code inserted inside that if statement may break things. Like breaking vectorization of that 'for' (note, that we are going over vertices). When you are writing the code, some times you may want to put additional constraints on the allowed operations, modifications, etc. A trivial example in C++ would be using 'const &' instead of '&'.

This is true (especially: breaking vectorization). But premature optimization is not a good idea, and if you are doing real optimization, you are going to rewrite that piece of code 10 times anyway, so it is in a different class of problem and the putty stuff I was saying before does not apply (i.e. this code is in the 1% or so of the codebase that is highly performance-sensitive). Optimized code is just a different…

And again it depends. I would return to a simple example of passing a parameter by a const reference.

When you are writing this const in the "const std::string &name" you are 1) constraining developers from breaking things 2) making the code more efficient 3) providing clues to other developers 4) providing clues to optimizer.

All of these points are important to some degree. And it is just the same, when you are writing this assignment.

And writing efficient code that provides all these clues in every way possible (including consistently and meaningfully arranging the white spaces) is certainly a good idea. Funny thing, that with experience it doesn't take extra time to do that. You just write it, and it comes out in the right way: readable, efficient and optimal down to CPU microcode and aligned memory accesses.

Post reply on HN