Live data from Hacker News

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

kotaku.com

121–130 of 210 posts

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

#121
post #81
post #75

So he discourages Getters/Setters and instead says that declaring the variable as Public is better? I mean, isn't that like not giving a sh-- about encapsulation principles ?

We're all consenting adults. Python gets by just fine on this principle.

The argument from the Java camp is that if you always use the getters and setters, you leave the access and modification open to extension, say, by adding a callback listener for changes to a variable.

I then just say, change it when you need it, and use that fancy "find usages" thing most IDEs and vim have.

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

#122
post #49

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.

This is not JavaScript, where a variable defined inside a function always has the entire function as its scope, and so it's confusing not to have it on top. In C++, a variable is not in scope until it's declared, so you can just declare it when you're going to start using it. If your function is five pages long, and in the fifth page you can't remember what's in scope and you have to reread through the entire functio…

Even in Javascript's case I don't like putting variables on top. Declaring variables only as they are needed lets JSHint warn me if I use accidentally something outside of its intended scope.

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

#123
post #121
post #81

Earlier quoted context omitted.

We're all consenting adults. Python gets by just fine on this principle.

The argument from the Java camp is that if you always use the getters and setters, you leave the access and modification open to extension, say, by adding a callback listener for changes to a variable. I then just say, change it when you need it, and use that fancy "find usages" thing most IDEs and vim have.

Precisely. The real reason Python gets this right is that it the properties feature lets you write `obj.foo` but still call a `getFoo` method behind the scenes.

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

#124

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…

I agree that it's visually displeasing, but it's very easy to actually read and understand.

The only reason I was able to quickly understand your beautifully-aligned code was because I had read the logic in the previous block, which is stupidly-easy to parse.

I also (like many others) shun the use of nested ternary operators. Probably because I'm used to dealing with PHP's straight-up broken implementation.

Further, I'd have split the side being determined from the sides array, as it's rather mentally taxing to figure out the increment at the end:

  if (dot 

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

#125
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"!

Mercurial already has this as well:

  hg annotate --help
  ...
  -w --ignore-all-space    ignore white space when comparing lines
  -b --ignore-space-change ignore changes in the amount of white space
  -B --ignore-blank-lines  ignore changes whose lines are all blank

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

#126
post #90

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…

Well, let me state this: John's version is not to my preference 'cause it has { in the same line as if, but I can live with that. But YOUR version uses not only the ? operator, which should be burned with fire but it NESTS two of them together. Please, I want to die now. :( Conclusion: We have different preferences.

nested ternaries are the same as if-else-if continuations. You figure that out one time, and it's easy to parse forever after.

The ternary operator in general eases understanding because it extracts the common bit, i.e. "sides[i] =", meaning you don't have to carefully read the contents of each and every conditional block to verify nothing else is going on besides this one assignment.

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

#127
post #75

So he discourages Getters/Setters and instead says that declaring the variable as Public is better? I mean, isn't that like not giving a sh-- about encapsulation principles ?

I'm kind of the same opinion as Carmack re: getters/setters. My feeling is, if all you're going to do is allow clients to read and write the variable, why not just expose it? Sure, you can argue encapsulation and even justify it by saying that later down the road you may want to change the implementation, but far too often I've seen C++ classes with a setter and getter for every variable, for no good reason (eg, they…

One (maybe stupid?) reason why I really like getter/setters has nothing to do with encapsulation, but that it makes it easier to search for places where a variable is changed. Often you have lots of getFoo and little setFoo functions - so just searching for "Foo" will return lots of results while "setFoo" helps me finding those faster.

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

#128
post #106

Earlier quoted context omitted.

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

I think we have different ideas about what constitutes optimization.

Sure, putting const in parameter declarations is easy to do. It may even buy you a little bit of speed because the compiler is a little bit clearer about pointer aliasing and whatever. But it's not going to make a difference in the equivalence classes of slow code / fast code / Really Fast Code.

Serious hardcore optimization usually involves changing the way the problem is solved to something different than the way the old code thought about it: either constraining the problem space further, or attacking it from a different direction. This usually involves rewriting everything since there are so many cross-cutting concerns. Sometimes one has to do this several times to figure out which way is really fastest. Microoptimization things, like whether you used const somewhere or not, are much smaller details that have correspondingly small effects.

For code that one isn't specifically optimizing, speed probably doesn't matter. There was an exception to this, where we hit a little bit of a bump in the late-2000s on platforms with in-order CPUs like the PlayStation 3 and Xbox 360, because they have such a high penalty on cache misses; this tended to make general-purpose code slower and result in much flatter profiles. But now we are pretty much out of that era.

In general, const is more of a protection than an optimization. This is especially true heading into the massively parallel future, where const just sort of tells you whether some code is known for sure to run safely in parallel or not... and running safely in parallel matters tremendously more to overall speed than the number of instructions in that bit of code, or whatever. (Anyway, C++ is not at all a viable language in the massively parallel future... so that is going to be interesting.)

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

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

Totally agree and I was really surprised by this. One line patches can turn into 30 lines just to reformat the surrounding code.

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

#130
post #31

I am also a const nazi, and occasionally find myself trying to imitate some of its uses elegantly through run time errors or strict naming conventions in other languages. I do understand why many other languages decided not to support it though. There's definitely a few times I've coded myself into a corner and ended up with "const spaghetti", having to do a const_cast or two to free myself and make a deadline. The a…

I also care about const-correctness... but once in a while in a dark hour I wonder if I really saved or lost more time by it so far.
Post reply on HN