This is a story about Doom 3’s source code and how
beautiful it is. Yes, beautiful. Allow me to explain.
After releasing my video game Dyad I took a little
break. I read some books and watched some movies I’d put off for too long. I
was working on the European version of Dyad, but that time was mostly waiting
for feedback from Sony quality assurance, so I had a lot of free time. After
loafing around for a month or so I started to seriously consider what I was
going to do next. I wanted to extract the reusable/engine-y parts of Dyad for a
new project.
When I originally started working on Dyad there was a
very clean, pretty functional game engine I created from an accumulation of
years of working on other projects. By the end of Dyad I had a hideous mess.
In the final six weeks of Dyad development I added
over 13k lines of code. MainMenu.cc ballooned to 24,501 lines. The
once-beautiful source code was a mess riddled with #ifdefs, gratuitous function
pointers, ugly inline SIMD and asm code—I learned a new term: “code entropy.” I
searched the internet for other projects that I could use to learn how to
organize hundreds of thousands of lines of code. After looking through several
large game engines I was pretty discouraged; the Dyad source code wasn’t
actually that bad compared to everything else out there!
Unsatisfied, I continued looking, and found a very
nice analysis of id Software’s Doom 3 source code by the computer expert Fabien
Sanglard.
I spent a few days going through the Doom 3 source
code and reading Fabien’s excellent article when I tweeted:
It was the truth. I’ve never
really cared about source code before. I don’t really consider myself a “programmer.”
I’m good at it, but for me it’s just a means to an end. Going through the Doom
3 source code made me really appreciate good programmers.
To put things into perspective: Dyad has 193k lines of code, all C++.
Doom 3 has 601k, Quake III has 229k and Quake II has 136k. That puts Dyad
somewhere in between Quake II and Quake III. These are large projects.
When I was asked to write this article, I used it as
an excuse to read more source code from other games, and to read about
programming standards. After days of research I was confused by my own tweet
that started this whole thing: what would “nice looking”—or “beautiful”, for
that matter—actually mean when referring to source code? I asked some
programmer friends what they thought that meant. Their answers were obvious,
but still worth stating:
Code should be locally coherent and
single-functioned: One function should do exactly one thing. It should be clear
about what it’s doing.
Local code should explain, or at least hint at the
overall system design.
Code should be self-documenting. Comments should be
avoided whenever possible. Comments duplicate work when both writing and
reading code. If you need to comment something to make it understandable it
should probably be rewritten.
There’s an idTech 4 coding standard (.doc) that I
think is worth reading. I follow most of these standards and I’ll try to explain
why they’re good and why specifically they make the Doom 3 code so beautiful.
Unified Parsing and
Lexical Analysis
One of the smartest things I’ve seen from Doom is the
generic use of their lexical analyzer[1] and parser [2]. All resource files are
ascii files with a unified syntax including: scripts, animation files, config
files, etc; everything is the same. This allows all files to be read and
processed by a single chunk of code. The parser is particularly robust,
supporting a major subset of C++. By sticking to a unified parser and lexer all
other components of the engine needn’t worry about serializing data as there’s
already code for that. This makes all other aspect of the code cleaner.
Const and Rigid
Parameters
Doom’s code is fairly rigid, although not rigid
enough in my opinion with respect to const[3]. Const serves several purposes
which I believe too many programmers ignore. My rule is “everything should
always be const unless it can’t be”. I wish all variables in C++ were const by
default. Doom almost always sticks to a “no in-out” parameter policy; meaning
all parameters to a function are either input or output never both. This makes
it much easier to understand what’s happening with a variable when you pass it
to a function. For example:
(image01)
This function definition this makes me happy!
Just from a few consts I know many things:
The idPlane that gets passed as an argument will not
be modified by this function. I can safely use the plane after this function
executes without checking for modifications of the idPlane.
I know the epsilon won’t be changed within the
function, (although it could easily be copied to another value and scaled for
instance, but that would be counter productive)
front, back, frontOnPlaneEdges and backOnPlaceEdges
are OUT variables. These will be written to.
the final const after the parameter list is my
favourite. It indicates idSurface::Split() won’t modify the surface itself.
This is one of my favourite C++ features missing from other languages. It
allows me to do something like this:
void f(const idSurface &s) {
s.Split(....);
}
if Split wasn’t defined as Split(...) const; this
code would not compile. Now I know that whatever is called f() won’t modify the
surface, even if f() passes the surface to another function or calls some
Surface::method(). Const tells me a lot about the function and also hints to a
larger system design. Simply by reading this function declaration I know
surfaces can be split by a plane dynamically. Instead of modifying the surface,
it returns new surfaces, front and back, and optionally frontOnPlaneEdges and
backOnPlaneEdges.
The const rule, and no input/output parameters is
probably the single most important thing, in my eyes, that separate good code
from beautiful code. It makes the whole system easier to understand and easier
to edit or refactor.
Minimal Comments
This is a stylistic issue, but one beautiful thing
that Doom usually does is not over-comment. I’ve seen way too much code that
looks like:
(image02)
I find this extremely irritating. I can tell what
this method does by its name. If its function can’t be inferred from its name,
its name should be changed. If it does too much to describe it in its name,
make it do less. If it really can’t be refactored and renamed to describe its
single purpose then it’s okay to comment. I think programmers are taught in
school that comments are good; they aren’t. Comments are bad unless they’re
totally necessary and they’re rarely necessary. Doom does a reasonable job at
keeping comments to a minimum. Using the idSurface::Split() example, lets look
at how it’s commented:
// splits the surface into a front and back surface,
the surface itself stays unchanged
// frontOnPlaneEdges and backOnPlaneEdges optionally
store the indexes to the edges that lay on the split plane
// returns a SIDE_?
The first line is completely unnecessary. We learned
all that information from the the function definition. The second and third
lines are valuable. We could infer the second line’s properties, but the
comment removes potential ambiguity.
Doom’s code is, for the most part, judicial with its
comments, which it makes it much easier to read. I know this may be a style
issue for some people, but I definitely think there is a clear “right” way to
do it. For example, what would happen if someone changed the function and
removed the const at the end? Then the surface *COULD* be changed from within
the function and now the comment is out of sync with the code. Extraneous
comments hurt the readability and accuracy of code thus making the code uglier.
Spacing
Doom does not waste vertical space:
Here’s an example from
t_stencilShadow::R_ChopWinding():
(image03)
I can read that entire algorithm on 1/4 of my screen,
leaving the other 3/4s to understand where that block of code fits relative to
its surrounding code. I’ve seen too much code like this:
(image04)
This is going to be another point that falls under “style.”
I programmed for more than 10 years with the latter style, forcing myself to
convert to the tighter way while working on a project about six years ago. I’m
glad I switched.
The latter takes 18 lines compared to 11 in the
first. That’s nearly double the number of lines of code for the *EXACT* same
functionality. It means that the next chunk of code doesn’t fit on the screen
for me. What’s the next chunk?
(image05)
That code makes no sense without the previous for
loop chunk. If id didn’t respect vertical space, their code would be much
harder to read, harder to write, harder to maintain and be less beautiful.
Another thing that id does that I believe is “right”
and not a style issue is they *ALWAYS* use { } even when optional. I think it’s
a crime to skip the brace brackets. I’ve seen so much code like:
That is ugly code, it’s worse than than putting { }
on their own line. I couldn’t find a single example in id’s code where they
skipped the { }. Omitting the optional { } makes parsing this while() block
more time consuming than it needs to be. It also makes editing it a pain, what
if I wanted to insert an if-statement branch within the else if (c > d)
path?
Minimal Templates
id did a huge no-no in the C++ world. They re-wrote
all required STL[4] functions. I personally have a love-hate relationship with
the STL. In Dyad I used it in debug builds to manage dynamic resources. In
release I baked all the resources so they could be loaded as quickly as
possible and don’t use any STL functionality. The STL is nice because it
provides fast generic data structures; it’s bad because using it can often be
ugly and error prone. For example, let’s look at the std::vector<T>
class. Let’s say I want to iterate over each element:
(image06)
That does get simplified with C++11:
(image07)
I personally don’t like the use of auto, I think it
makes the code easier to write but harder to read. I might come around to the
usage of auto in the coming years, but for now I think it’s bad. I’m not even
going to mention the ridiculousness of some STL algorithms like std:for_each or
std::remove_if.
Removing a value from an std::vector is dumb too:
(image08)
Gee, that’s going to be typed correctly by every
programmer every time!
id removes all ambiguity: they rolled their own
generic containers, string class, etc. They wrote them much less generic than
the STL classes, presumably to make them easier to understand. They’re
minimally templated and use id-specific memory allocators. STL code is so
littered with template nonsense that it’s impossible to read.
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 library, or the boost
libraries—these are written by some of the best C++ programmers in the world
and great care was taken to make them as beautiful as possible, and they’re
still ugly and basically unreadable.
id solves this problem by simply not making things
overly generic. They have a HashTable<V> and a HashIndex class. HashTable
forces key type to be const char *, and HashIndex is an int->int pair. This
is considered poor C++ practice. They “should” have had a single HashTable
class, and written partial specialization for KeyType = const char *, and fully
specialized <int, int>. What id does is completely correct and makes
their code much more beautiful.
This can be further examined by contrasting ‘good C++
practice’ for Hash generation and how id does it.
It would be considered by many to be good practice to
create a specific computation class as a parameter to the HashTable like so:
(image09)
this could then be specialized for a particular type:
(image10)
Then you could pass the ComputeHashForType as a
HashComputer for the HashTable:
(image11)
This is similar to how I did it. It seems smart, but
boy is it ugly! What if there were more optional template parameters? Maybe a
memory allocator? Maybe a debug tracer? You’d have a definition like:
(image12)
Function definitions would be brutal!
(image13)
What does that even mean? I can’t even find the
method name without some aggressive syntax highlighting. It’s conceivable that
there’d be more definition code than body code. This is clearly not easy to
read and thus not beautiful.
I’ve seen other engines manage this mess by
offloading the template argument specification to a myriad of typedefs. This is
even worse! It might make local code easier to understand, but it creates
another layer of disconnect between local code and the overarching system
logic, making the local code not hint towards system design, which is not
beautiful. For example, lets say there was code:
(image14)
and
(image15)
and you used both and did something like:
(image16)
It’s possible that the StringHashTable’s memory
allocator, StringAllocator, won’t contribute to the global memory, which would
cause you confusion. You’d have to backtrack through the code, find out that
StringHashTable is actually a typedef of a mess of templates, parse through the
template code, find out that it’s using a different allocator, find that
allocator... blah blah, ugly.
Doom does the complete “wrong” thing according to
common C++ logic: it writes things as non-generic as possible, using generics
only when it makes sense. What does Doom’s HashTable do when it needs to
generate a hash of something? It calls idStr::GetHash(), because the only type
of key it accepts is a const char *. What would happen if it needs a different
key? My guess is they’d template the key, and force just call key.getHash(),
and have the compiler enforce that all key types have an int getHash() method.
Remnants of C
I don’t know how much of id’s original programming
team is with the company anymore, but John Carmack at least comes from a C
background. All id games before Quake III were written in C. I find many C++
programmers without a strong C background over-C++ize their code. The previous
template example was just one case. Three other examples that I find often are:
over-use set/get methods
use stringstreams
excessive operator overloading.
id is very judicial in all these cases.
Often one may create a class:
(image17)
This is a waste of lines of code and reading time. It
takes longer to write it, and read it compared to:
(image18)
What if you’re often increasing var by some number n?
(image19)
vs
(image20)
The first example is much easier to read and write.
id doesn’t use stringstreams. A stringstream contains
probably the most extreme bastardization of operator overloads I’ve ever seen:
<<.
For example:
(image21)
That’s ugly. It does have strong advantages: you can
define the equivalent of Java’s toString() method per class w/o touching a
class’ vtables, but the syntax is offensive, and id chose to not use. Choosing
to use printf() instead of stringstreams makes their code easier to read, and
thus I think it’s the correct decision.
Much nicer!
The syntax for SomeClass’ operator << would be
ridiculous too:
[Side note: John Carmack has stated that static
analysis tools revealed that their common bug was incorrect parameter matching
in printf(). I wonder if they’ve changed to stringstreams in Rage because of
this. GCC and clang both find printf() parameter matching errors with -Wall, so
you don’t need expensive static analysis tools to find these errors.]
Another thing that makes the Doom code beautiful is
the minimal use of operator overloads. Operator overloading is a very nice
feature of C++. It allows you to do things like:
(image22)
Without overloading these operations would be more
time consuming to write and parse. Doom stops here. I’ve seen code that doesn’t.
I’ve seen code that will overload operator ‘%’ to mean dot product or operator
Vector * Vector to do piece-wise vector multiplication. It doesn’t make sense
to make the * operator for cross product because that only exists in 3D, what
if you wanted to do:
some_2d_vec * some_2d_vec, what should it do? What
about 4d or higher? id’s minimal operator overloading leaves no ambiguity to
the reader of the code.
Horizontal Spacing
One of the biggest things I learned from the Doom
code was a simple style change. I used to have classes that looked like:
(image23)
According to id’s Doom 3 coding standard, they use
real tabs that are 4 spaces. Having a consistent tab setting for all
programmers allows them horizontally align their class definitions:
(image24)
They rarely put the inline functions inside the class
definition. The only time I’ve seen it is when the code is written on the same
line as the function declaration. It seems this practice is not the norm and is
probably frowned upon. This method of organizing class definitions makes it
extremely easy to parse. It might take a little more time to write, since you’d
have re-type a bunch of information when defining the methods:
(image25)
I’m against all extra typing. I need to get stuff
done as fast as possible, but this is one situation where I think a little
extra typing when defining the class more than pays for itself each time the
class definition needs to be parsed by a programmer. There are several other
stylistic examples provided in the Doom 3 Coding Standards (.doc) that
contribute to the beauty of Doom’s source code.
Method Names
I think Doom’s method naming rules are lacking. I
personally enforce the rule that all method names should begin with a verb
unless they can’t.
For example:
(image26)
is much better than:
(image27)
Yes, it’s Beautiful.
I was really excited to write this article, because
it gave me an excuse to really think about what beautiful code is. I still don’t
think I know, and maybe it’s entirely subjective. I do think the two biggest things,
for me at least, are stylistic indenting and maximum const-ness.
A lot of the stylistic choices are definitely my
personal preferences, and I’m sure other programmers will have different
opinions. I think the choice of what style to use is up to whoever has to read
and write the code, but I certainly think it’s something worth thinking about.
I would suggest everyone look at the Doom 3 source
code because I think it exemplifies beautiful code, as a complete package: from
system design down to how to tab space the characters.
Shawn McGrath is a Toronto-based game developer and
the creator of the acclaimed PlayStation 3 psychedelic puzzle-racing game Dyad.
Find out more about his game. Follow him on Twitter.
Footnotes
[1] A lexical analyzer converts the characters of
source code, (in the relevent context), into a series of tokens with semantic
significance. Source code may look like:
x = y + 5;
A lexical analyzer (or “lexer” for short), might
tokenize that source as such:
x => variable
= => assignment operator
y => variable
+ => additional operator
5 => literal integer
; => end statement
This string of tokens is the first of many steps in
converting source code to a running program. following lexical analysis the
tokens are fed into a parser, then a compiler, then a linker, and finally a
virtual machine, (in the case of compiled languages a CPU). There can be
intermediate steps inserted between those main steps, but the ones listed are
generally considered to be the most fundamental.
[2] A parser is (usually) the next logical step
following lexical analysis in machine understanding of language, (computer
language/source code in this context, but the same would apply for natural
language). A parser’s input is a list of tokens generated by a lexical analyzer,
and outputs a syntactic tree: a “parse tree.”
In the example: x = y + 5, the parse tree would look
like:
(image28)
[3] “const” is a C++ keyword that ensures that a
variable cannot be changed, or that a method will not change the contents of
its class. “const” is shortform for “constant.” It’s worth noting that C++
includes a workaround, either via const_cast[T] or a C-style cast: (T *). Using
these completely breaks const, and for the sake of argument I prefer to ignore
their existence and never use them in practice.
[4] STL stands for “standard template library” It’s a
set of containers, algorithms, and functions commonly used by C++ programmers.
It’s supported by every major compiler vendor with varying levels of
optimization and error reporting facilities.
[5] GCC - GNU Compiler Collection: a set of compiler
supporting multiple programming languages. For the case of this article it
refers to the GNU C/C++ compiler. GCC is a free compiler, with full source code
available for free and works on a wide array of computers and operating
systems. Other commonly used compilers include: clang, Microsoft Visual C++,
IBM XL C/C++, Intel C++ Compiler.
The following replies are
approved. To see additional replies that are pending approval, click Show
Pending. Warning: These may contain graphic material.
Show pending
JohnCarmackby Shawn McGrath
1/14/13 1:18pm
Thanks!
A few comments:
In some ways, I still think the Quake 3 code is
cleaner, as a final evolution of my C style, rather than the first iteration of
my C++ style, but it may be more of a factor of the smaller total line count,
or the fact that I haven’t really looked at it in a decade. I do think “good
C++” is better than “good C” from a readability standpoint, all other things
being equal.
I sort of meandered into C++ with Doom 3 – I was an
experienced C programmer with OOP background from NeXT’s Objective-C, so I just
started writing C++ without any proper study of usage and idiom. In retrospect,
I very much wish I had read Effective C++ and some other material. A couple of
the other programmers had prior C++ experience, but they mostly followed the
stylistic choices I set.
I mistrusted templates for many years, and still use
them with restraint, but I eventually decided I liked strong typing more than I
disliked weird code in headers. The debate on STL is still ongoing here at Id,
and gets a little spirited. Back when Doom 3 was started, using STL was almost
certainly not a good call, but reasonable arguments can be made for it today,
even in games.
I am a full const nazi nowadays, and I chide any
programmer that doesn’t const every variable and parameter that can be.
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.
John Carmack
Darth StewieJohnCarmack
1/14/13 1:37pm
I’m not involved in any way with programming but
reading things like this always makes me wonder one thing: are most programmers
sharing their duties with other programmers or do they tend to work on their ‘own’
material? What I mean is, if one programmer is very clean and precise and
another is let’s say, messy and unorganized, does the entire project suffer for
it? Are multiple people essentially “dirtying” up the code for the rest of the
team?
Either way, thanks for contributing to the story and
your view. I found your linked article interesting even though it was WAY over
my head. :)
Demo-graficDarth Stewie
1/14/13 1:49pm
I liken exchanges like this to exchanges between
comedians.
Programming has a big sub-culture to it. It makes
sense too because there’s some aspects of coding culture that only other coders
will understand and relate to. A lot of comedians are friends and hang out and
even observe each other’s material for analysis and opinion, but a part of the
process seems to be a lot of comraderie and peer review.
Pirate HeartsDarth Stewie
1/14/13 1:53pm
In my experience, coding style tends to be propagated
as part of the studio culture. When in doubt, though, a good rule of thumb is
to match the style of the surrounding code.
SnapeyJohnCarmack
1/14/13 2:00pm
Nice article... I’ve been meaning to have a dig in
the doom3 code myself :)
btw the section minimal templates, to iterate over
all elements in a vector is even more concise in C++11:
for (auto elem : vec) {
...
}
KellerWVUDarth Stewie
1/14/13 2:12pm
Bunch of different ways to go about teamwork when
multiple coders work on a single project. I know some who just copy/paste stuff
together (no no no). I prefer a more functional approach, quite literally. I
would ask a teammate to write me a function named X and passes in parameters Y
and Z and returns whatever you need. That way all I need to know is the name of
the function and which parameters it uses. There are apps out there for
professionals also that create a pipeline for teams to submit code to, then
someone QCs it before it all gets put together. In the end, it just comes down
to whatever the team is comfortable with. Code is an ugly ugly thing more often
than not.
babousarcasmrules
1/14/13 2:29pm
The big differences are pointers and memory
allocation (no garbage collector).
The use of pointers (memory adress) have a LOT of
implications and is very different from the Java where everything is a
reference.
SGTalonrazikain
1/14/13 2:41pm
I am sure it is. I really enjoy following him on
twitter. Even his non-technical posts are cool. Plus the dude build frickin
rockets!!! If that doesn’t make him the coolest, i am not sure what does.
RuudPoutsmaJohnCarmack
1/14/13 2:59pm
What OOP directions are you backing away from, and
why?
MentatYPJohnCarmack
1/14/13 3:13pm
It’s a good day when the man himself weighs in.
Thanks for being the programmer that you are, but even more significantly for
sharing your knowledge with the world. It’s hard to imagine what the past 20+
years would be like without your contribution.
LaynJohnCarmack
1/14/13 3:21pm
I really loved the part about vertical spacing. I
just showed a friend and it’s the first thing that jumped out at him. I think
most, if not all, programming teachers i’ve had insist brackets should get
their own line, but i still don’t do that because i consider it ugly, wasteful
and unreadable.
It’s interesting to see how a veteran programs, since
when learning you rarely get a consistent style taught which is actually
designed specifically for AAA games.
sarcasmrulesbabou
1/14/13 3:22pm
Yeah, memory allocation sounds pretty scary to me!
But I’ll learn how to reference memory etc. and I’ll have a go with UDK or
something. Baby steps! I guess when you peel away the subtle nuances in each
OOP language, they are really similar. Cheers for replying dude!
b33g33JohnCarmack
1/14/13 3:25pm
If you are the real Carmack, please accept my
sincerest thanks for months (maybe years) of lost sleep since I was 12, a
permanent sense of disorientation and nausea whenever I run carrying a massive
firearm, a personal conviction that I DO KNOW what Hell on Earth would look
like, a belief that ‘spear of destiny’ is a much cooler nickname than ‘mr.happy’
and confidence in my ability to shoot things in the dark using a flashlight and
finally, providing me with the skills to handle a vicious German Shepard with
nothing but a K-Bar.
So, thanks.
dchichkovJohnCarmack
1/14/13 3:28pm
John,
Compare this:
for ( i = 0; i < in->numVerts ; i++ ) {
dot = plane.Distance( in->verts[i] );
dists[i] = dot;
if ( dot < -LIGHT_CLIP_EPSILON ) {
sides[i] = SIDE_BACK;
} else if ( dot > LIGHT_CLIP_EPSILON ) {
sides[i] = SIDE_FRONT;
} else {
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
Versus this:
for(i = 0; i < in->numVerts; i++)
{
dot = plane.Distance(in->verts[i]);
dists[i] = dot;
sides[i] = dot < -LIGHT_CLIP_EPSILON ? SIDE_BACK :
dot > LIGHT_CLIP_EPSILON ? SIDE_FRONT :
SIDE_ON;
counts[sides[i]]++;
}
DanCopelandJohnCarmack
1/14/13 3:30pm
I didn’t have something that would reliably run Doom
3 until I was just recently able to build a new computer, so I’m playing it now
for the first time, and I have to say that I’ve been impressed at how
non-repetitive it is for a FPS game, in terms of level design and encounters.
Each area feels fresh, and even the most frustrating wave of enemies feels like
a challenge rather than a chore; my quick-save reflex has been resharpened. The
textures look crisp, and the sounds sharp. And in an age of 5 hour
single-player campaigns, having a decently long journey is nice.
HasutoDarth Stewie
1/14/13 3:47pm
I’ve been working for a while in the mobile industry
and at least there the common way is to have coding guidelines which state how
you should code. This typically cover both general style (how many spaces,
should you have a prefix on class members/globals etc) and what specific
language features you should use, when to use them and typically why. (The
latter becomes important when dealing with a language that is as
poweful/dangerous as C++.) Google has put their style guides online if anyone
is interested in what an example can look like:
http://code.google.com/p/google-styleguide/ (I don’t work at Google).
Once code has been written it is typically reviewed
by other people in the team to make sure everyone knows what has changed and to
look for any mistakes or things which could be done better. This can sometimes
be bruising to the ego, but at least I find that it generates better code and it
means that people are more thorough. (It becomes a matter of pride to not make
it easy for people to find mistakes in your code so you review it yourself one
extra time before submitting to code review.)
Regarding what tasks you work with it becomes quite
natural that you work on a specific part and with time become somewhat of an
expert in that code. In general good workplaces tend to shift people around a
bit though so you don’t become too entrenched. This is typically good for
everyone because it means that if an emergency occurs in that code they don’t
have to call you if you’re on vacation.
langdonxdchichkov
1/14/13 4:13pm
Are you trying to advocate nested ternary statements?
klandshomeJohnCarmack
1/14/13 4:20pm
John Carmack, the king of code. I had a strong hunch
that this article (a great read) would attract the attention of Mr. Carmack
himself. Thank you for your input and your feedback. Kotaku, a brilliant job in
posting such a longread by a developer that loves their craft.
Starting the curly brace on the same line as a
function is something I have considered, but for some reason I have not adopted
it yet.
RealmRPGersarcasmrules
1/14/13 4:30pm
A lot of small things. When I first started
co-developing in C# and C++, my brain had trouble switching from one mode to
the next. What I found really cool was that eventually my brain just “knew”
what language it was in and I’d almost never accidentally start typing or
highlighting in the wrong language (for some strange reason, Visual Studio’s
block highlight rules are different between C# and C++).
Okay, that has very little to do with changes. But as
babou said, the biggest thing is that you’re going to need to get used to
working on a lower level. You’ll need to start passing parameters by reference
so that you’re not slowing down your execution. You’ll need to find smarter
solutions to certain problems. For example, C++ has no equivalent to
reflection, so writing a scripting language or tying data files for variable
information can be a pain until you’re very comfortable with templates and
inheritance.
sarcasmrulesRealmRPGer
1/14/13 4:33pm
So I’m guessing I need to stick at Java for a bit
until I completely understand OOP! Thanks for the advice.
chubbsondubsDarth Stewie
1/14/13 5:20pm
Yes it can “dirty” up the code for everyone else, but
this is really subjective. Some dirtiness isn’t harmful (say I use 3 spaces,
Bill uses 4, tabs vs spaces, I use camelCase, Doug uses not_camel_case, etc.)
This often is what people call coding conventions and technically they don’t
matter. However, other dirtiness is very important. I write small methods that
can easily be reused and testing in isolation, Randy writes a single method
with 1000s of lines of redundant code. I decompose my problem using
abstraction, OOP modeling or functional programming, Randy doesn’t understand
abstraction or how to model objects and uses maps and arrays frequently as
model objects. I follow a model-view-controller architecture separating the
model, visual display, and control logic where Randy doesn’t have a model and
frequently rebuilds the data from the UI. These differences will cause serious
headaches in the future. To some degree rigorous testing can pound Randy’s
poorly written code into a robust product. However, it might not be easy to
modify it, and it could easily require massive amounts of re-testing to
revalidate any changes because its fragile.
redinzanesarcasmrules
1/14/13 5:23pm
It’s not that hard though.. My Games Engineering
courses in univerity started with in-depth java and some C# in Unity, and we
were dumped into DirectX11 C++ with minimal introduction. As long as you have a
basic understanding of Java you can code C++ as long as you understand some of
the differences.
Multiple classes or “beautiful code” may be a bit
harder on the other hand, I still struggle with how to use header-files.
RealmRPGersarcasmrules
1/14/13 5:25pm
I always tell people that C++ is the best
foundational knowledge for a coder to have. Once you understand how it works,
you can readily understand how other languages work — In particular, what it’s
doing “behind the scenes” and how that may be causing problems or how it may be
utilized. So, I like to try to get people’s feet wet by having them learn C++ “via”
other languages. In other words, co-development using simpler languages. This
allows me to start them on C++ early then ease them into its more complex ideas
like pointers, classes, virtual functions, templates etc.
It’s largely an age-based thing, however. The younger
the person is, the less exposure I feel the need to give them to C++. If they
can develop in a very simplistic language (such as BASIC — not Visual Basic,
mind you, but pure BASIC) through and through, then I can slowly progress them
through the years.
If, however, I’m teaching a college-level student, I
always want them to get into C++ as quickly as possible. This can be difficult,
so I try to introduce them to new concepts by giving them languages with
restrictions so that they never feel overwhelmed. If this is you, I might
suggest taking the bullet and looking at C++. Understanding all of its concepts
can take some time, so the more you work with them the better. Start off with
pointers. Understand what they are, how they work, and the various syntax for
using them.
Unfortunately, C++ does an awful lot of neat things
that are bit complicated, so it would be best to have somebody teach you as you
go.
E. Mathieu SternbergDarth Stewie
1/14/13 5:49pm
Sadly, yes. There are lots of ways to dirty up code.
Since you’re not a programmer, you may not have
encountered the moders VCS (Version Control System). This is the ‘central
repository’ from which most developers check their code out, and later back in
after making their fixes. A programmer would be assigned to work on something
and when he commits his fixes the VCS would record what changes he made. Good
VCSs have filters that prevent a user from checking in something that doesn’t
pass the basic rules of the language in which he works— and can check (some of)
the style rules Carmack and McGrath mentions. Good development environments
have other programs that immediately and automatically check those changes back
out, try to build a working version of the program, and email everyone when
someone breaks the product, etc. The best environments go so far as to
automatically start the program in all its glory and run it through automatic
tests to assert that it does what the developer claims it should do.
I don’t know what kind of VCS, build system, or test
system, they have at id. I’d be very surprised if it weren’t as pipelined and
elegant as the code itself.
Terminal VelocityJohnCarmack
1/14/13 6:34pm
Carmack you beautiful, beautiful man... I know
nothing about coding, but I truly admire your passion for computers, cars and
rockets! I was 10 in 1992 when I first heard your name, and I will never forget
all the memories you gave me. Keep on rocking!
cakeloverJohnCarmack
1/14/13 6:41pm
> I am a full const nazi nowadays, and I chide any
programmer that doesn’t const every variable and parameter that can be.
And so they should! If I had a dollar for every time
someone ‘reused’ some method parameter I’d be Mark Shuttleworth ritch.
PixelSnaderchubbsondubs
1/14/13 7:06pm
Randy sounds like how I’d work! (I’m a non-programmer
forced to do programmy things sometimes)
neolestatJohnCarmack
1/14/13 9:30pm
John, I don’t anything about code and don’t want
to... Just wanted to come by this comment and say thanks for all the good
games... In one way or another I’ve played every Id game apart from the Quake
ones and enjoyed them all. I’m Looking forward to Doom 4! Thank you again.
lcidJohnCarmack
1/14/13 11:35pm
We gamehackers really appreciate all the
statically-allocated vars.
ErikPragtJohnCarmack
1/15/13 3:54am
Hi John,
A really nice read, and thanks for sharing your
insights you gained during your development of some of the most awesome games
in history. On a code level, I think most of the lessons your learned (and
more) are covered in the book ‘Clean Code’ by Robert C Martin. It’s a Java
book, but most of the principles apply to most programming languages, and
especially to OO languages like C++ and Java.
If you have some spare time, it might be worthwhile
to read some chapters.
Kind regards,
Erik Pragt
Kurt_Hustlesarcasmrules
1/15/13 4:56am
I recommend learning C first it makes you more
appreciative when working in a higher level language like Java. You can read
the K & R in an afternoon and be back on your way to Java land the next
day.
iexiakDarth Stewie
1/15/13 7:58am
Think of it like 2 painters painting parts of a
portrait on the same canvas.
If you’ve got 2 realists or 2 abstract or 2
impressionists or 2 of the same, you’ll probably end up with a coherent
painting. You may be able to tell the subtle differences and recognize which
painter painted an area.
Now combine lets say a realist and an
impressionist...You are immediately going to be able to tell the differences.
You could probably label each area clearly as who painted that area.
But in the end you still end up with a painting. As
long as the code works, the beauty is in the eye of the beholder. And thanks to
the flexibility of modern languages, there are multitudes of ways to do the
same thing, even from within the same language.
iexiakdchichkov
1/15/13 8:05am
The answer is PHP
Also it doesn’t really matter how its done. To your
computer they are both the same number of instructions.
To me the first statement is significantly easier to
read, and more attractive if only because it will maintain it’s legibility if
you add more lines between the {}. If it had tabs it would be the easy winner
of this question.
Yes the ?: method takes less space, but at what cost?
What if I wanted to put in another command, all of a sudden I need to rewrite
the whole line and it isn’t as readable. What if i wanted to put in a comment
right in the middle? Less readable.
Both would be massively improved by some tabs though!
Packetchubbsondubs
1/15/13 1:50pm
I actually would disagree that differences in
indentation is harmless dirtiness. I have encountered so many chunks of code
which have become a disaster due to different people with different indentation
methods working on it.
If everyone uses tabs the result is not usually so
bad, but there’s a special kind of pain in loading a file and realizing “Oh
god, someone was using tabs and someone else using real spaces” and discovering
the file is unreadable unless you can figure out their settings and duplicate
them (or run the file through an indentation tool).
Casey Kinseychubbsondubs
1/15/13 2:20pm
While I agree with @chubbsondubs that the actual
application of Computer Science methodologies and practices are the sort of
problems that would be most likely cause the end product to suffer, I have to
disagree about the inertness of stylistic aspects like naming convention and
code formatting.
Code really needs to be systematic and predictable,
and that need increases pretty dramatically with the size of your team. Like
the OP mentioned, one of the great things about an elegant codebase is you can
read it and know exactly what it does. CamelCase? That’s an object.
uses_underscores? That’s a variable/pointer. ALL_CAPS? That’s a global
constant. I get hints about what I’m working with, and without having to read
the function definition. This is even more important in dynamically typed
languages where you likely don’t have a type-hint at all. Delivery time will
suffer on a product if your team is having to constantly cross-reference your
code in order to interface with it, so it’s a good idea to standardize your
APIs. This is one reason why PHP has gotten a pretty nasty reputation for
producing low quality coders, because even its standard library follows very
little convention. I wrote PHP code professionally for 5 years and still found
myself in the documentation on a daily basis. bin2hex, or bintohex? strtolower
or str2lower? array_sort, arraysort, or just sort? Time to hit the docs: It’s
bin2hex, strtolower, and there’s at least 5 methods for sorting an array.
Whether or not the end product suffers because of
this is debatable, I think it certainly delays it, though. Maybe you end up
re-writing a method cause you couldn’t find Randy’s method, and you write one
that behaves slightly differently. You’re going to have a lot of trouble tracking
down a bug when your team has sprinkled the code with my_foo() and randy_foo()
interchangeably. Bugs get shipped and then everyone goes home and kicks their
dog. Don’t kick your dog!
NelsonCJohnCarmack
1/15/13 2:26pm
If you like strong typing, you’ll love Ada. How come
you’ve never commented on it before?
sarcasmrulesredinzane
1/15/13 5:04pm
Yeah, I’m doing C#/Java in Unity at the moment to
bolster my learning. I love that engine!
sarcasmrulesRealmRPGer
1/15/13 5:07pm
Well I’m learning C# and Java currently, and will be
introduced to Pascal at college (UK equiv. of post-16 education) and then
hopefully C++ and other low-level languages at university.
sarcasmrulesKurt_Hustle
1/15/13 5:09pm
C sounds good, will get GCC now and have a play
around. Bookmarked K&R on Amazon, and will order that in the future. £30
seems a lot for a book though!
RealmRPGersarcasmrules
1/15/13 5:50pm
Yeah, I used to talk to a lot of people from Europe.
What America calls “college” they call “uni” or “university.”
I would say that’s pretty good. I didn’t get any real
exposure to C++ until college (aka uni), though that was more to do with lack
of a means than personal choice. If it was up to me I would have studied C++ in
high school.
Jud WhiteDarth Stewie
1/15/13 11:05pm
Usually the developers who care about coding style
the most will chastise the ones who dirty it up. When time and budget permits
this is usually accomplished in code review where a peer reviews a piece of
code that’s being submitted. This can all go to the wayside when deadlines
approach, which becomes one form of what’s called “technical debt”.
eideticexDarth Stewie
1/16/13 12:30am
Yes dirty code is bad for many reasons, not all of
which are merely cosmetic.
Dirty code can and will lead to bugs, not just in the
section that’s dirty, but in seemingly unrelated sections as well. I’ve lost
count of how many times I had to go in to bug fix code that I wrote only to
find the bug was not in my code but in someone else code that they just hacked
together in what looked like a drunken stupor.
I’ve had it come back to bite me so many times that I
got into a habit. Whenever I’m done with a particular piece of code (be it a
function, class, or entire system), I go back through it and clean it up. This
involves everything from optimizations that I could not have figured out
without working code to just renaming stuff to make it more readable.
Having done that for a few years now has lead to my
first iterations of code being a lot cleaner and a lot more efficient. Much
less junk code, less bugs, faster execution times, and most important less
resource usage to get essentially the same tasks done. It wasn’t easy, it was
actually so frustrating that I just wanted to abandon it and go back into my
old habits, but I stuck with it and got huge rewards for my efforts.
I truly believe every programmer should adopt
practices like this, but sadly I’ve only gotten one other guy to adopt it and
his code certainly improved a lot from when we first began to discuss such
things. Shame that his current job doesn’t leave much time for him to work with
me on fun projects anymore, really enjoyed working with that guy.
JamesDuvallangdonx
1/16/13 9:00am
oh god please say he isn’t
I have never seen a good use of nested ternary
statements.
EDIT: actually, I’ve never seen a good use of ternary
statements full stop, but we discourage them for readability issues where I am
anyway so I might not have seen enough to form an opinion.
sarcasmrulesRealmRPGer
1/16/13 11:10am
Cheers dude, some other guy on this thread recommended
the ‘K&R’ book so I might order that if I have £30 lying around. Or get a
copy from the library. (What’s a library? I think it has a lot of... paper, I
think?)
Dan SuttonJohnCarmack
1/16/13 1:08pm
I tend to like strong typing... but I understand what
you mean. If you think about it in machine code, there’s no typing at all (and
no OOP either) so it becomes a question of how much overhead is placed upon the
code by imposing that type of structure in the source vs. how unreadable the
code becomes if you don’t.
Like anything else, common sense comes into it
somewhere: I doubt it makes sense to have an overall set of rules which you
hope cover every contingency; by the same token, if you don’t have any rules
for this type of thing, the code becomes unreadable.
Of course, it’s also possible to overdo the OOP thing
and turn one’s (object) code into a massive nest of subroutine calls... at
which point you start having to trust in the ability of the compiler to
optimize what you’re doing. Fairly obviously, the fastest code is something
which can execute inline; equally obvious is the fact that if you try to write
an entire system like this, you’ll need a computer with more bytes of RAM than
there are atoms in the known universe to run it.
So it becomes a compromise: speed vs. realism; one
has to be flexible in this regard: this flexibility represents the concessions
one is forced to make both to the hardware running the program, and to the poor
bastard who has to come along and read your code, then try to understand it!
Lion_Tsdchichkov
1/16/13 5:49pm
there is nothing to compare above. we are talking
here about the ID code style readability and usability. but not about your
ability of building deep ternary conditions.
SamyBoiJohnCarmack
1/17/13 3:12am
Wow! One of the few people in this world who inspire
me to be a better programmer, here on Kotaku!!
My sincere thanks for all that you have achieved to
date and my best wishes to everything in the future.
A Big F’ing Fan
IIIHasteIIIJohnCarmack
1/17/13 6:49am
Hello John, I know this isn’t really related but can
id Software stop ignoring Quake Live?The game has so much potential and it’s so
sad seeing it go to waste. The gameplay is pretty much perfect at this point
but the game still lacks some core features around it, like the official ladder
system for example. The community developed many necessary features for you but
they are not integrated into the game. To this point I paid over $100 for the
subscription and I will renew it again but for what, 1 update every 4 months? I
know the game made less profit than expected but you’ve given up on it too soon
instead trying to fix it and market it better. There is really strong community
behind this game, some players chose QL as THE game and don’t play anything
else. They deserve better.
mrClintJohnCarmack
1/17/13 1:36pm
Hey!
How will game development benefit from functional
programming style?
Also, one of my teachers said that agent oriented
programming is a paradigm that is getting increasingly more popular in software
development, what do you think?
crea7ordchichkov
1/17/13 5:38pm
Dude, your color scheme and unaliased fonts so awful.
And try to buy full hd monitor to place it in the vertical orientation to keep
braces at the separate lines. You’ll like it.
BlakeDarth Stewie
1/17/13 6:06pm
I would say you should always treat your code as
though it will be shared, because one day someone else is going to need to read
through it (either future you or someone else when you’re sick or have left or
just need more people), and the faster someone can figure out whether or not
that’s the code they want to be messing with the better.
A company where you have one programmer per system
with each system having their own style will run into problems the moment
anybody leaves.
Also having readable code means people don’t need to
call you up when you’re on holidays in order to fix things.
BlakeLayn
1/17/13 6:16pm
At my work the coding standards have braces on new
lines, I personally prefer it, my main thoughts on it are that it helps break
code into smaller chunks, and makes it easier to find where those sections
start and end.
It’s not a strong preference though, as long as there
are braces for each block I’m generally pretty fine with it.
I tend to disagree with most of the vertical space
arguments though, if your function is pages long then you should be breaking it
into smaller functions not killing your new lines.
If having braces on new lines causes your code to be
unreadable, your code needs to be cleaner.
Blakesarcasmrules
1/17/13 6:23pm
My uni course dropped us into C++ soon after Java, I
think it’s good to get into the C side of things early.
For small things you won’t have to do much different,
just pass your objects by reference or pointer.
As far as memory management just remember if you call
new on something, you have to call delete on it, if you call malloc on
something, you have to call free on it, and you should almost always have the
same class that news something be the one to delete it.
If you think of your program heirarchically as far as
who owns what, with lower things in the heirarchy never able to refer to
something higher, you shouldn’t run into many problems with the rest.
LaynBlake
1/17/13 7:32pm
Well it IS customary to put braces on new lines. It
just makes it harder for me to read code. It has nothing to do with my code.
When i look at the example up there, in the first
picture i’ve register the structure with one look while in the second picture i
have to take a longer look, having to go from the top to the bottom of the
function to understand the structure.
Do you understand what i mean? I see more at the same
time, so i read it faster
I do use empty new lines to break a function into
smaller sensible chunks
Blakesarcasmrules
1/17/13 7:44pm
It sounds scarier than it is. Here is something that’ll
cover all your standard use cases.
Basically you have a new base data type called a
pointer, which is a memory address of an object (so a MyClass* points to a
MyClass in memory).
The ‘new’ keyword allocates enough memory to store an
object, calls the constructor on that point of memory, then returns its
address.
So
MyClass* mc = new MyClass();
Will make mc store the address of your new MyClass,
that has just had its constructor called on it. In order to call or refer to
members of something pointed to by a pointer, you use the -> operator. So to
call an update function on your new instance you just write
mc->Update();
The MyClass you’ve created is going to sit at that
one spot in memory until you delete it, so when you’re done using your MyClass,
just call
delete mc;
Which will call the destructor of your MyClass
instance, and free up the memory. Don’t use mc after this, that memory address
could be used by anything after this point.
malloc and free are basically the same except they
just give you a number of bytes and let you do what you want with it.
So
void* buffer = malloc(512);
Will make buffer point to a block of 512 bytes for
you to do whatever you want with, when you’re done, you just call
free(buffer);
to release the memory.
The main reason you do this stuff is because if you
just have
MyClass mc;
in the middle of a function, it’ll get created on the
stack, and your stack memory has limited size.
new/malloc has basically the entirety of their RAM to
play with, so you can malloc a block of memory 500MB in size if you want,
trying to make a char buffer[512*1024*1024]; on the stack will kill your
application quite quickly.
As long as you remember that whatever new’s
something, should generally be the guy who deletes it, you should be fine, and
there is more you can do with pointers and references, but the above is the 95%
use case, and you shouldn’t need to worry about those other things until you’re
comfortable with all that.
CISSP-LawJohnCarmack
1/20/13 9:10pm
Mr. Carmack,
Just have to say that it’s awesome that you took the
time to interact with the community in this way. As a 31 year old man, I’ve
been a fan of yours for decades; whether it was the games you’ve created,
contributed to or had subsequently inspired — they hold a special place in my
gaming heart. Admittedly, I was never the greatest programmer in the world, but
because I was inspired by many of the contributions you and your peers made to
this industry throughout my formative years, I gave it a shot nonetheless.
Did I ever make it into the industry with my
education? No, my skills as a coder just weren’t what they needed to be, but
because I was inspired to try, I was ultimately exposed to other aspects of
technology in general which were ultimately more my forte (BS, MS in
Information Systems and Information Security and ultimately a Doctor of Juris
Prudence with an emphasis of law pertaining to my background and personal
tastes).
In one way or another, the contributions that you and
your peers have made to the medium, industry and art form, have done well to
inspire others to do great things both similar and dissimilar to what you’ve
done. You’re no doubt a brilliant man, but more than that, your willingness to
involve yourself directly with your fans — many of which you’ve inspired to do
the same — speaks volumes of your character.
Thanks,
Ernesto
riverfr0zenJohnCarmack
1/20/13 9:44pm
Have any of you guys tried unit testing your
programs?
zhanxw00JohnCarmack
1/20/13 10:29pm
Thans for the article. I have the same feeling from
reading Google Coding Standard.
The key points in this article is the consistence and
clearness; and following the coding standard helped in that way.
TexZK88JohnCarmack
1/22/13 4:59am
The article written by the OP matches *EXACTLY* what
I thought when I first read the gameplay source code. Many of my coding style
choices of today come form there :-)
Oh, and of course I have to thank John for releasing
the Wolf3D source code back in the days — that’s where I started learning C as
a teenager :-)
LudovicUrbainJohnCarmack
1/30/13 4:41am
Somehow the great minds think alike. I was truly
shocked to hear you went to C++ / OO, yet welcome back to the bright side of
the force ;)
Sundaram RamaswamyDarth Stewie
3/07/13 12:36pm
Of course, like in a network where the weakest link
decides the throughput of the communication system, in a team’s delivery, the
wrost code(r) decides the performance of the output of the whole product; this
is the reason programmers are to be extremely desciplined i.e. they should know
their change’s repercussions before making ‘em.
Collapse replies
Chris PersonThe Anti-Fanboy
1/14/13 12:48pm
I agree. I had the pleasure of spending 15 minutes in
a room with John Carmack, listening to him talk in terms that did not pander or
simplify, without stopping to take a single break. The man is inspired in a way
that only other programmers can truly understand, but when you hear him talk
you feel in your bones that everything he does is intricately, intentionally
and thoroughly thought out.
It makes you really consider just how much of what we
love in this medium is largely invisible to most of us.
dragonflietThe Anti-Fanboy
1/14/13 1:26pm
I disagree very fundamentally. You are right about a
few aspects. One has to be extremely well versed in something to fully
comprehend the details of minutiae. In this sense, you have to have a working
knowledge of coding to understand what is good about some instances and what is
bad in others. Likewise, you must be well-versed in literature to really
understand and appreciate the works of great writers, in painting to appreciate
painters, etc. Additionally, people who truly love a form often are artists
(generally bad ones, but that is neither here nor there), as they would like to
produce their own. I simply disagree that one must be a musician to appreciate
music, or a painter to appreciate painting (and here I mean “truly” appreciate).
tenshouThe Anti-Fanboy
1/14/13 2:02pm
I’m so happy to read it. It’s sometimes hard to
explain how programming is a creative process, and how beautiful a code can be
- not just for the eye, but functionally.
MentatYPdragonfliet
1/14/13 3:17pm
While you make some good points, I think the flaw
here is in the practical sense. True you don’t have to be in the field to
appreciate all the nuances—you just have to be well versed in it. The problem
with programming is that it’s pretty well impossible to be well versed in it
without being one or having been one at some point in time, unlike music or
visual arts for instance.
LowOnStimpaks started this
thread
1/14/13 12:25pm
LowOnStimpaksby Shawn McGrath
1/14/13 12:25pm
(image29)
NEEEEEEEEEEEEEERRRRRRRRRRRRRRRDDDDD!!!!!!!
Outriderby Shawn McGrath
1/14/13 12:44pm
This is way over my head, but still pretty neat. My
programming experience is limited to simple custom code editors in various game
making programs and picking apart small bits of HTML or CSS when I don’t want
to bug a web developer at my day job. I think I understood a lot of the
structural and “best practices” stuff discussed in the article, but the specifics
were way outside of my knowledge base.
xilefianOutrider
1/14/13 1:09pm
HTML and CSS aren’t programming languages, they’re
design languages like how PNG describes an image and DOC describes a text
document
Outriderxilefian
1/14/13 2:34pm
Yes, this is clearly a good use of my time and yours,
especially because of my aspirations to go into web development that I
apparently have now. I will be much more prepared for that interview that is
completely outside of my skill set or career path that I guess I have to go to
now that you’ve set me straight. You are a true difference maker.
visionincisionxilefian
1/14/13 2:52pm
PNG and DOC are not design languages, they are
compression formats...
HTML and CSS are a type of programming language, CSS
has no logic but they are used to program a design. PNG and DOC are not
something you write or program or design.
xilefianOutrider
1/14/13 3:03pm
A lot of people read over these discussions and
younger people may make the wrong assumptions if they read over comments and
then go down a career path with the wrong information.
And this isn’t web development
xilefianvisionincision
1/14/13 3:14pm
No they’re not compression formats, they’re file
formats, but inside them is a design language (I’d know, I write binary readers
for these things). A compression format would imply that it is reducing
(compressing) the amount of data behind it, PNG and DOC are not compressed at
all, they’re freely expressed formats just like HTML, the big difference is
that HTML is human readable as a form of XML inspired markup language.
You are 100% displaying incorrect information when
you write “HTML and CSS are a type of programming language”, programming is
writing logic, there is no logic beyond visual design principles when it comes
to HTML and CSS, they are markup languages that display information, no
processing happens what-so-ever, a program is a set of instructions, HTML and
CSS is better described as a collection of data.
The easiest way to think about it is:
Excel makes spreadsheets that display data, the
spreadsheet files, are the information that the program binary reads and then
displays.
Your web browser is a program that opens up HTML
files and it reads then displays them, the files will never process, the HTML
code has no logic, the browser will only read and interpret what it thinks the
HTML is describing.
PNGs and DOCs are something you write to describe
design, it’s the definition of the formats itself, in the same way that a
browser reads HTML, photoshop can read PNGs and Word can read DOCs.
HTML PNG and DOC are all file formats that describe
something, you can write a PNG file by manually assembling a format compliant
image in a text editor and you can write an HTML web page by manually
assembling a format compliant markup in a text editor.
visionincisionxilefian
1/14/13 5:57pm
Well that’s a very good explanation. Thanks, I
thought they were compression formats, so I was confused by that. You’re right,
and thanks for the explanation. BTW for the purpose of this article it’s just
as important to keep HTML clean as it is to keep C++ clean, logic or not there
are certain rules all editors should follow.
Outriderxilefian
1/15/13 3:08am
Wow, I am genuinely impressed at how committed you
are to this, despite the apparent spiral into madness that you’re experiencing.
Bravo.
tylerwaynexilefian
1/15/13 12:27pm
I’ve been in this debate once before, and I still
stick to my guns that HTML, even though it’s primarily a markup language, still
counts as a programming language because it affects the execution of a
computer.
Please read this comment thread and tell me what you
think of my arguments there.
I believe that HTML is a programming language based
on content rather than logic.
Reply
Collapse replies
THE_MOOGLEKING started this
thread
THE_MOOGLEKINGby Shawn McGrath
1/14/13 2:40pm
Functional? Yes. Practical? Very. Should it be a
standard? In a perfect world, yeah.
But beautiful? Odd choice of words here, especially
from a guy whose game tries to set him up as an artist...
Darkmoon_UKTHE_MOOGLEKING
1/14/13 2:44pm
I take it you’re not a programmer then?
THE_MOOGLEKINGDarkmoon_UK
1/14/13 2:46pm
I work with code on a regular basis, but I view it as
more of a craft than an art. (at least, by my definiton, the goal of a craft is
to serve a function, and the goal of art is to communicate).
“Elegant” would be my choice of words.
MentatYPTHE_MOOGLEKING
1/14/13 3:10pm
Think of it like a house—something that is functional
at its core but can also be beautiful if created well. We’ve all seen (and
maybe even written) ugly code before. If ugly code exists, shouldn’t beautiful
code exist as well?
I use “elegant” to describe code that is precise and
succinct—not overly verbose in achieving its purpose. If 10 lines of code is
able to do what a typical programmer does in 50 lines, I consider that code “elegant”.
metronome49THE_MOOGLEKING
1/14/13 3:37pm
His game tries to set him up as an artist? What does
that even mean?
THE_MOOGLEKINGmetronome49
1/14/13 6:10pm
Dyad in my opinion was a bit pretentious, is what I
mean.
MonkeyChunksTHE_MOOGLEKING
1/14/13 6:23pm
Yea, “beautiful” is definitely a choice of words that
could only serve to emphasize some final product like Dyad, which is why it
shouldn’t have been used to describe code.
osvicoTHE_MOOGLEKING
1/14/13 10:44pm
Not functional; imperative.
fibreTHE_MOOGLEKING
1/16/13 10:40am
Does crafting with a language count as communicating?
DaveInsurgentfibre
1/18/13 3:12pm
I think there is no debate there. It absolutely is
communicating - not just with the machine, either, but others who may come
across it. That includes yourself - because after 6 months, coming back to code
you’ve written but not looked at since, you might as well be a stranger in many
cases.
DaveInsurgentTHE_MOOGLEKING
1/18/13 3:14pm
Is elegant not a synonym for beauty? You could argue
that it carries additional connotations (as Wikipedia may say) — but then you
have to start debating whether the code counts as simple. Also, “work with code”
is not the same thing as what was asked.
DaveInsurgentMonkeyChunks
1/18/13 3:17pm
You can’t really say that. I mean - you did, but in
doing so, you really said, “I’m not the target audience - but let me speak
about it as if I am.”
WanderingSoulgurfinki
1/14/13 1:22pm
It looks complicated, but it can be easy to
understand once you learn it. If you’re curious about C/++ programming, there’s
a lot out there to get you started.
cplusplus.com
cprogramming.com
dreamincode.net
stackoverflow.com
c.learncodethehardway.org
EDIT: Tried to get these to turn into links, but... I’m
Kotaku stupid apparently... >_<
MANoftheHOURgurfinki
1/14/13 1:41pm
LOL I always give my brother (Who can speak/code in
many different programming languages) a hard time when he talks about code.
yucomplyWanderingSoul
1/14/13 2:24pm
Burner account? We are the lowly kotaku users who are
not given that privilege.
9a3eedigurfinki
1/14/13 2:33pm
IT ARE TEH CAMPOOTERS MAGIC WORDS THEY MAK THE
GOOGLES AND THE ANGRY BARDS AND TH FACEBOOKS WERK
gurfinki9a3eedi
1/14/13 2:39pm
EMARGERD ORLY I TAUGHT IT WAS JOST DA THINGIZ DAT
CAME IN DEM CD ROMS DAT MAEK IT WURKZ
gurfinkiWanderingSoul
1/14/13 2:40pm
Lol. Expert at C++ programming, doesn’t know how to
make hyperlinks. XD
Thanks for the info! ^_^
WanderingSoulgurfinki
1/14/13 2:44pm
Expert? Hardly lol. However, once you nail the basics
down, it’s all pretty much just implementation. Hope the links help. :)
mr.blackgurfinki
1/14/13 3:28pm
Expand
(image30)
Quick, look at this kitty, it’ll calm you!
DennyCraneDennyCraneDennyCrane
started this thread
DennyCraneDennyCraneDennyCraneby Shawn McGrath
1/14/13 1:09pm
“If you need to comment something to make it
understandable it should probably be rewritten.”
I’m a fan of Quake 3’s InvSqrt, and it’s almost the
exact opposite of that:
float InvSqrt (float x){
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
Beauty is in the eye of the beholder, I guess.
(If you want to figure out what that hunk of code
does, I recommend a read over here: http://www.beyond3d.com/content/articles/8)
kevinskiDennyCraneDennyCraneDennyCrane
1/14/13 1:15pm
I kind of agree that anything that has to be
commented to be understandable should be rewritten. That’s probably why I’ve
grown to loathe Cascading Style Sheets so much. It’s virtually impossible to
use correctly if you want the vast majority of people to see it properly, and
even the W3’s site encourages you to engage in all sorts of hacky coding to
pull off things that Cascading Style Sheets just weren’t designed to do. It’s
pretty disgusting.
dusparrDennyCraneDennyCraneDennyCrane
1/14/13 1:18pm
You forgot the comment that is in it:
//Black magic hax
//low level floating point-bit hacking
justanothertechieDennyCraneDennyCraneDennyCrane
1/14/13 1:26pm
“If you need to comment something to make it
understandable it should probably be rewritten.”
I think this is a perfect example of “Just because
you read it on the internet doesn’t make it true”.
DennyCraneDennyCraneDennyCranekevinski
1/14/13 1:30pm
In something like a game engine, though, I completely
disagree.
Performance is king. If a completely unreadable mess
gives you a performance advantage in an often used inner loop, you go with the
completely unreadable mess.
It’s one thing in an application where performance is
almost irrelevant (Which, to be honest, is true of every single piece of code I’ve
ever written), but if performance is critical, readability goes out the window
on the list of priorities.
DennyCraneDennyCraneDennyCranedusparr
1/14/13 1:43pm
Don’t forget the
//What the fuck??
After the magic number!
Kered13DennyCraneDennyCraneDennyCrane
1/14/13 1:54pm
For 99% of your code, it’s more important for your
code to be readable than fast. This famous function is one of the exceptions.
It’s an operation that occurs very frequently, and is normally very slow, so
optimization is extremely important here. You make up for it by documenting it
very well.
gwwarDennyCraneDennyCraneDennyCrane
1/14/13 1:54pm
If you’re going to maintain code you’ll ideally want
to write it in a simple and readable way, instead of a clever one line hack.
After doing so, if you find your code is slow, usually you run a profiler,
identify bottlenecks, and then optimize code where it makes sense. Since this
is a game engine, and this is a low level function that is probably called many
many times, doing bit shifting and binary math isn’t surprising. However, I
would expect comments in this case, unless you want the next developer to bust
out a pen and paper to follow the math.
Straw HatDennyCraneDennyCraneDennyCrane
1/14/13 1:57pm
Such code is fun to mess with and geek over, but if
put into practice it’s hell for anyone who might actually have to maintain the
software.
DennyCraneDennyCraneDennyCraneKered13
1/14/13 2:00pm
One of the comments for the function is literally
// what the fuck?
So it’s rather famously poorly documented ;-)
MartinMalmstenDennyCraneDennyCraneDennyCrane
1/14/13 2:06pm
It doesn’t need a comment since the method name very
clearly states what it does.
DennyCraneDennyCraneDennyCraneMartinMalmsten
1/14/13 2:07pm
Oh, it’s commented...
//evil floating point bit level hacking
and
// what the fuck?
DennyCraneDennyCraneDennyCraneStraw Hat
1/14/13 2:10pm
Well, in that case, it’s in a rather tight function
in an inner loop which likely shouldn’t be messed with much, anyway.
But definitely fun.
dusparrDennyCraneDennyCraneDennyCrane
1/14/13 2:19pm
ahh yes, the good old Voodoo, don’t see those as much
nowadays (at least outside of Graphics)
MentatYPDennyCraneDennyCraneDennyCrane
1/14/13 3:24pm
0x5f3759df is giving me a brain hemorrhage.
kevinskiDennyCraneDennyCraneDennyCrane
1/14/13 8:18pm
I totally agree with you, actually. That’s another
reason why I hate CSS now, despite loving it so much when browsers didn’t
support much of it. There’s nothing optimal about it. You just pile a bunch of
code that wasn’t designed to do what you’re trying to do with it on top of more
code that wasn’t designed to do what you’re trying to do with it, and it’s
complete overkill for the results that you get, because it still won’t work in
everything as you originally envisioned.
And I love how proper use of HTML 5 actually more or
less requires that you know CSS and JavaScript.
RichardAKiernanThe man for the job
1/17/13 8:10pm
That bit, surprisingly, is reasonably logical once
you get down to it. Because you can’t do bitwise operations on non-integral
types in C, that line is effectively a way of making an integral variable with
precisely the bit structure of the floating-point argument passed to it so that
bitwise operations can be performed on it. Of course, there’s an implicit
reasoning that the int type is 32-bit, although unless you’re a masochist,
pretty much any computer you’re going to run Quake III on will have 32-bit int
types.
Reply
Collapse replies
Iconoclast XVII started this
thread
1/14/13 12:29pm
Iconoclast XVIIby Shawn McGrath
1/14/13 12:29pm
Beginning to think I should really learn C++. I’ve
had a job writing C# for a little over a year and a half now, but I would much
rather make games.
ugurIconoclast XVII
1/14/13 12:40pm
You can actually make games using C# in various
environments. Unity for example allows using C# (though the mono variant)
OnimystIconoclast XVII
1/14/13 12:41pm
You can make games in C#. Also, see XNA.
wakers01Onimyst
1/14/13 1:35pm
I think Microsoft is moving away from this though. Windows
phone 8 game development is supposedly with C++ and Direct 3D.
wakers01Iconoclast XVII
1/14/13 1:38pm
I have never talked with a game developer who loved
their job. I think if you have a place on the creative team, then it’s likely
better, but all I ever hear from the admittedly few developers I’ve spoken with
is horror stories and crunch time.
Iconoclast XVIIOnimyst
1/14/13 1:49pm
Yeah, I’ve been looking into that and OpenGL with C#,
but I’m not sure how many companies actually use C#, and I’d much rather make a
career out of game development than doing it on the side.
Iconoclast XVIIwakers01
1/14/13 1:51pm
I already face that, though. Three weeks in a row I
had to pull other people I work with out of the fire and work over 12 hour
days. Building games interest me a lot more than building custom interfaces for
a rather crappy monster of an association management system for non-profit
organizations.
wakers01Iconoclast XVII
1/14/13 2:13pm
Well, it may be that that is a career move that would
make you happier then. Microsoft has a lot of great resources for WP8 game
development(which is now C++). I mention that since, coming from C# and
presumably .NET, their resources might make the transition a little bit easier.
Reply
Collapse replies
reinkai000 started this
thread
reinkai000by Shawn McGrath
1/14/13 12:33pm
Interesting. In the programming classes that I took
it was always “Lots of comments!” and “Make everything line up!”. Interesting
to see people saying the opposite. I suppose that an experienced programmer
wouldn’t need either.
makkurareinkai000
1/14/13 12:47pm
The reason why comments and such are emphasized so
much in course work is that code is not only written but maintained.
Comments can make code easier to understand WHY [and
sometimes HOW] something is being done.
Lining things up is stylistic but does has its
negatives, as pointed out here [increased vertical white space].
The problems I encounter is where one programmer
thinks something is self-commenting and intuitive and when another programmer
comes along, the code makes no sense to them.
I like some comment lines so WHY things are happening
are not lost and HOW things are being done [if they’re complicated or overly
clever approaches] are understood by more than the original programmer.
Comments may make things messier but, when used
carefully, can strike a positive balance between form [beauty of code] and
function [understandable, more maintainable code] in my opinion.
Wrexisreinkai000
1/14/13 1:24pm
The self documenting thing is a fallacy. You think
your code is easy to understand, so you don’t document it - then someone else
takes it over and they’re lost completely.
This of course, where ego kicks in, and you think
they should have hired someone as smart as you to code.
Straw Hatreinkai000
1/14/13 1:54pm
Lots of comments is somewhat unneeded, but a
reasonable amount of comments is nice, specifically regarding what different
functions do, what the basic framework is, blah blah.
Most of my job is doing maintenance for old code.
While most of it is easy enough, there’s always someone who was coding in some
flavor of the month framework where everything is convoluted and there’s hardly
any documentation.
There’s no real need to pad comments for the sake of
padding, but some basic commenting is much appreciated for anyone trying to
maintain the sucker years later.
visualdeityreinkai000
1/14/13 5:34pm
Curly braces lining up is a style choice (I prefer
having the more compact version Shawn talks about, but both are legitimate).
Comments aren’t, though. Self-documenting code is a worthy goal, but that doesn’t
remove the need for comments - and like anything else, it can be taken too far.
You can actually make code less maintainable by unpacking it too much, where a
short function and a helpful comment would have sufficed.
Reply
Collapse replies
Lockgar started this thread
Lockgarby Shawn McGrath
1/14/13 12:38pm
I HATE when people make single line if statements
with no { }. Chances are, that’s gonna be why the code breaks.
I’m one of those types that like spacing with the
extra 1/4 of useless { }, so that maybe connected. Its just nice knowing where
the clear start is. Although I completely understand why you would rather just
have it immediately after the condition. I always get unlucky and have if
statement conditions last 3 lines.
GiTSLockgar
1/14/13 12:48pm
I usually put { } after if’s and stuff because then
if I want to add more inside the if later, the scope is already there for it xD
and saves me 2 seconds of typing! Tbh I think that was the reason, pretty sure
I read that in a C++ book somewhere and forget which... It was long ago and has
become somewhat of a habit!
Can’t stand this though!
int c = (a > b)? a : b;
And don’t get me started when I see nested ones! I
don’t know why, I just hate them! xD Saying that though if the coding standards
ask for it... bah!
ahndaGiTS
1/14/13 12:57pm
It’s called a ternary operator. I think they’re an
acceptable way to reduce simple assignment size, but it’s very much a matter of
style. There is NO doubt they can be abused.
Mark PurnellLockgar
1/14/13 1:15pm
#1
if(value =< 1){
value++;
}
else{
value—;
}
#2
value = (value =< 1) ? value++:value—;
#3
if(value =< 1){value++;} else{value—;}
Not sure if #3 is legitimate, but it seems the most
readable of the three.
Personally, I usually use number two, but each to
their own.
LockgarMark Purnell
1/14/13 1:38pm
#3 is legit, I do that from time to time if I know
its something that will never need to actually be changed.
#2 is just plain evil.
#1 I don’t know why, but it always throws my eyes
off. Its like saying, Here is the if statements, and here is where it ends.
While doing it like this.
if(value =< 1)
{
value++;
}
else
{
value—;
}
Says to me, Here is the if statements. Here is whats
inside of it, here is where it starts, and here is where it ends.
LockgarGiTS
1/14/13 1:44pm
Yeah, that c = statement is just plain evil.
Kered13Mark Purnell
1/14/13 2:00pm
#2 does not do what you think it does. More
specifically, it will never change “value”. Postfix in/decrement in/decreases
the value by 1, then returns the ORIGINAL value. If you assign this back to “value”,
then it will overwrite the in/decrement and you will be back where you started.
SgausmanMark Purnell
1/14/13 2:50pm
#2 is also redundant, it would be like typing value =
value++, technically all that does is value = value; value++;
jpaughLockgar
1/14/13 3:15pm
I hate it when they use the brackets, but don’t put
the brackets on a new line. It makes my head hurt. But to each their own!
Mark Purnell’s #1 is a good example, I would write
that like:
if(value =< 1)
{
value++;
}
else
{
value—;
}
Kered13Sgausman
1/14/13 3:18pm
Actually it does:
tmp = value;
value++;
value = tmp;
So not only is it redundant, but it doesn’t even do
what you want.
Mark PurnellKered13
1/14/13 4:35pm
Interesting, is this true across all languages?
Apothecary101Lockgar
1/16/13 5:09am
The key is indentation. Indent your code correctly.
Curly braces are redundant in a well indented code, and indentation makes more
to help readability than any braces, so it’s a must.
Reply
Collapse replies
burnermankey started this
thread
burnermankeyby Shawn McGrath
1/14/13 1:06pm
What is the benefit of all this? Does denser, neater
code make things run better?
nthdegree256burnermankey
1/14/13 1:15pm
Yes. Not directly; a program with incomprehensible
function names, extraneous comments, and sloppy const usage will run just as
fast as the equivalent nicely-written program. The difference is that one will
be a nightmare to improve and debug, and the other won’t be, which means the
cleaner code will have more of its bugs found and fixed.
AyeAyeCapnburnermankey
1/14/13 1:28pm
It makes maintenance an updating of the code easier.
It’s like when you make yourself a To Do list, then look at it a week later
having no idea what you were talking about. Or when you devise a new way to
organize your files ,but a week later forget what you did, and now can;t find
anything.
When you are coding you need a way to remember what
you did last time so you can tweak/fix/update it later. Elegant code that
sticks to a consistent system makes that much less time consuming.
wakers01burnermankey
1/14/13 1:33pm
There’s a principal called clarity through
conciseness. Basically, the more concise and straightforward the code is, the
more likely it is to be clearly and easily understood by yourself or others
when you inevitably have to come back and change or refactor it.
cool.stuburnermankey
1/14/13 2:32pm
Denser? Not necessarily.
Neater? If at any time in the future, anyone
(including yourself) might have to look at that code again... absolutely.
Maintaining messy code is a nightmare.
Woshiernogcool.stu
1/14/13 2:46pm
My boss is against refactoring for refactoring’s
sake. So I ask him one day, what about sanity? Is that a valid reason to
refactor?
I understand what he meas from personal. I’ve
factored code for the same game I was working on until I realized that I was
trying optimize code as I was writing it. It’s better to get it done, and then
go back because year’s later, you’ll still have nothing to show for your work.
cool.stuWoshiernog
1/15/13 11:47am
Premature optimization is probably the biggest waster
of time that I see people around me doing.
Seriously, do you honestly think you need to unroll
those loops? Honestly, WHY ARE YOU USING SHIFTS HERE??? When was the last time
you profiled your code??? You understand that modern compilers are smarter than
what your grandfather programmed on, right?
Reply
Collapse replies
Platypus Man started this
thread
Platypus Manby Shawn McGrath
1/14/13 1:19pm
For what it’s worth, I prefer putting the starting
brace for a block on the next line instead of the same line (first thing under
Spacing). IE I prefer this:
if (a>b)
{
...
more than this:
if (a>b) {
...
The first way just seems so much more readable to me
and in a modern coding environment, pretty much everyone has big high-res
monitors (at least compared to those 20 years ago). You mention not being able
to see the next function, but if that’s not enough, modern IDEs and even simple
text editors let you collapse functions and blocks. Of course, the biggest
stylistic thing, as with all things in life, is to be consistent.
But yeah, well-written code is a great thing to see
(especially if you’ve had to endure poorly-written stuff on enough occasions).
yucomplyPlatypus Man
1/14/13 2:00pm
Whitesmiths style. Personally I prefer any indent
style as long as it remains consistent throughout
Platypus Manyucomply
1/14/13 2:14pm
Though I’ve never looked into the names of the
styles, what I was referring to looks more like Allman style than Whitesmiths.
But yes, consistency is indeed king.
CowLion started this thread
CowLionby Shawn McGrath
1/14/13 11:16pm
A friend of mine (who happened to program a 3D game
engine in Visual Basic capable of rendering Doom 3’s MD5 meshes) was
practically obsessed with John Carmack’s programming. He always claimed that id’s
code was the cleanest out there. I’ll be sure to send him this article.
This is why, despite the fact that id is now owned by
Bethesda, I will never doubt Carmack and his company’s ability to create a bug
free game. Yeah, bugs will exist, but not to the degree seen in Bethesda Game
Studios’ products.
(My friend also liked to say that Valve’s code was
incredibly messy and he was surprised Half-Life ever ran.)
UcarenyaCowLion
1/17/13 8:42pm
That’s why I hope ID can make an open RPG with both
Engine level and tool-set level exposure. A cleaner Elderscroll with
moddability
CowLionUcarenya
1/18/13 12:28am
I’d just love to see ID supply Bethesda with their
next engine. At least that would give them a good foundation to create such
massive games.
Reply
Entroperator started this
thread
Entroperatorby Shawn McGrath
1/14/13 2:47pm
Programmers are the magic-users of the digital world.
They plunge their hands into the very stream of the electronic environment and
direct the flow of it to their liking. I’ve always tried to comprehend their
workings and thought processes, but I’m barely a 5th level bard with minimal
ranks in Use Magic Device compared to their 20th level cleric/wizard (8/12)
with Improved Spell Focus (Transmutation).
In summation, I tried to read the article in
completion. My brain hurts. I can feel it. The grey matter actually hurts.
SummerReadingAndProgrammingEntroperator
1/14/13 3:50pm
The book covered by this innovative book review may
interest you, Entroperator.
InquisitiveCoderEntroperator
1/14/13 4:19pm
To be fair, C++ is a very difficult language to read
and write. It had to retain backwards compatibility with C, so what they could
do with its syntax was pretty restricted. Newer languages like Java, and
especially dynamic languages like Python or Ruby are a lot easier on the eyes.
Additionally, any programmer can write obscure code in any language. Even
programmers have a hard time reading bad code.
All programs can be reduced so executing instructions
sequentially, making a decision (if age > 18 do this, else do that), and
repeating instructions until a condition if met (while Right Arrow is pressed,
move character to the right). If you can read a flowchart, you’re capable of
the same basic thought processes as a programmer.
Reply
Adam Panzica started this
thread
Adam Panzicaby Shawn McGrath
1/14/13 3:45pm
For the most part, I agree with a lot of the
practices in what you consider ‘beautiful code’. But I do have a couple...
disagreements isn’t quite the right word, but more justifications for why some
of the rules shouldn’t be hard and fast.
The first, and simplest one, is on the use of ‘cuddled
braces’ (putting the opening brace on the same line). You wholesale ignore one
of the biggest reasons against using cuddled braces: Ease of reading scope.
With cuddled braces you’re depending a lot on proper indentation and spacing in
order to quickly tell where nested brace sets begin/end. With non-cuddled
braces, it is very, very easy to look through code and immediately tell where a
nesting level begins and ends, as there is much more visual white space. I
agree that it takes up more lines of code, but that isn’t always a bad thing.
The next is on comments, specifically
function/class/method header comments. You’re forgetting one very, very
important use of those comment blocks: Documentation generation, such as with
Doxygen. While yes, it may be very, very easy to tell from looking at a
function definition and the accompanying code what a particular chunk of code
does, you have to remember that a developer working with your code might not
always have access to the raw source code, they might only have access to the
documentation for the API and a precompiled library. And having more
information in the documentation for a library is never, ever a bad thing. I
don’t know how many times I’ve been pissed off because the documentation for a
function consists solely of a method signature. What units are the inputs and
outputs in (when dealing with numbers)? What are the valid input/output ranges?
So yes, it puts more onus on the developer to make sure the comments are in
sync with what the function actually does, but it makes the lives of everyone
that has to work with your code much easier.
Finally on STL/Boost/any ‘standard’ library:
Portability. Yes, you can roll your own classes for doing common things. But
then when you try to compile for a different target, you have to make sure you
follow the rules for that platform as well. And do you really think that you
can make a more optimized version of a standard container than people that have
been optimizing them for dozens of years? I would rather have other people who’s
jobs it is to optimize standard containers do that work for me, so I can
concentrate on actually USING the standard containers to do useful things. Only
if a standard container couldn’t meet my performance requirements would I ever
consider putting in the effort to roll my own. My guess is (and Mr. Carmack’s
response seems to confirm this) at the time a lot of the underpinnings of Doom
3 / Quake II/III were written, STL/Boost and what have you were not nearly as
well optimized as they are now, nor were compilers at optimizing them, so
re-inventing the wheel made sense. I highly doubt it does now.
Reply
jivecom started this thread
jivecomby Shawn McGrath
1/15/13 7:13pm
I’m not a programmer, I don’t understand coding
languages, but I can 100% appreciate your meaning. I apply the same sort of
mentality to everything, specifically how the files on my pc are organised (not
word-for-word, obviously, but some of your principles translate to general
organisation). When people look through my documents, they incorrectly
attribute it to me having OCD, which is stupid. I’m not compulsive, I just like
having things organised. It’s easy for me to find things if all those things
are placed within a very clear structure, right? I don’t know how people can
live having multiple media files of the same type (i.e. songs) on wildly
different areas of their drive (like having all your rap under My Music, and
all your metal under My Documents\Received Files). I also try to keep excessive
subcategories to a minimum. For example my videos fall under only two
categories: TV Shows and Films. Within those folders are folders for each file,
i.e. Top Gear has its own folder instead of having all my Top Gear episodes
sharing a folder with all my Justified episodes (which would ruin everything
since my TV Show files all follow the same naming convention: S##E##). I don’t
toss everything in one videos folder, but I don’t segregate my Films into
folders for each genre.
This kind of stuff is everywhere in my life, because
I find that having a clear organization system which is simple and elegant can
make my life significantly better in the long run, even if people do
erroneously assume that it’s just because I’m a clean freak.
Incidentally, why is being clean and organised seen
as such a negative by general people? Why do people feel the need to explain
why other people like stuff clean and organised? Is it normal to just be a
sloppy pig who doesn’t give a shit? I don’t get it.
Reply
SkipErnst started this thread
SkipErnstby Shawn McGrath
1/14/13 5:24pm
This article taught me two things.
1. The author probably wouldn’t/doesn’t like Python
because yo don’t use curly braces at all.
2. The more I think I know about programming, the
more I realize I’m a beginner. (granted I don’t program in C-anything, so that
didn’t help me parse this stuff at all either)
The man for the jobSkipErnst
1/14/13 7:21pm
Use Ruby!
1. Python is a well-designed language, but you’ll
probably have to refactor your programs sooner or later and you wouldn’t
BELIEVE what a pain in the ass significant whitespace makes this! This is why
people don’t use FORTRAN nowadays. The C programming language’s enduring
influence was the lack of that BS. Significant whitespace is a massive step
backwards.
2. Don’t worry, you can still find a sysadmin job
with just shell scripting experience. Programming is boring and hard anyway.
A protip, when your boss (in a systems administration
job) leans over your shoulder and sees you work in Vim in a terminal emulator
(the fact it runs in a terminal is great reason to use it apart from it being
the best of all text editors), it makes them think you have skills. Seriously,
pumping out shell scripts or even code in programming language (e.g. Ruby,
Perl, Python) will reinforce their faith in your good work.
And don’t put yourself down. The line between ‘scripting’
and ‘programming’ language is really blurred nowadays that I’d only call SQL
(which is not Turing-complete, but still) and shell scripts ‘scripting’ as they’re
so easy to pick up and are generally suitable for pretty small tasks.
skrawgThe man for the job
1/14/13 8:35pm
Don’t agree with significant whitespace being a step
backwards, I think overall it leads to less time being wasted typing loads of
curly brackets.
InquisitiveCoderThe man for the job
1/15/13 3:09pm
How, exactly, does significant whitespace hurt
refactoring? Are you doing it manually...? That’s a task best left to an IDE.
zanyzapperskrawg
1/16/13 10:24am
Oh please - I’m tired of programmers griping about
how much time it takes to type some insignificant thing. Skip reading one Gawker
article and you’ll make up for the time it takes to type all your curly braces
for a year!
skrawgzanyzapper
1/17/13 10:51am
It is annoying if it keeps breaking your
concentration, at least I find it that way personally.
Reply
Collapse replies
xhrit started this thread
xhritby Shawn McGrath
1/14/13 5:58pm
I agree with almost everything here, as I take great
pains to ensure my code is visually pleasing to look at and easy to read. I do
however have a few differing viewpoints. My main pet peeve is trailing
whitespace. The first thing I do whenever I open a new source file is delete
all the trailing whitespace.
I use couts over printfs; in my opinion they are
easier to use in long strings with lots of variables. It is the difference
between having to count the number of parameters to match up specifiers with
the data they represent, or not having that mistake to make.
Also, I think wrapping everything in getter and
setter functions is essential, and even more so if you are using 3rd party
libraries. Otherwise you will run the risk of being forced into using divergent
syntax within your own application, and that gets messy real fast. It might not
be an issue for ID since they have a full staff of certified geniuses who can
make everything they need from scratch, but for the rest of us it is almost
essential to use 3rd party libs.
Here is an example of my code, from my open source
Flash-like project called Xenos Engine, which uses Irrlict for 3d rendering,
and Open Dynamics for physics. Irrlict is a c++ style API and uses euler
angles, ODE is a c style API and uses quaternions. Xenos however, uses
x3dpoints both internally and externally and was designed to be used via the
Lua scripting interface.
Reply
zer033x started this thread
zer033xby Shawn McGrath
1/15/13 12:01am
I really liked this article and definitely agree with
using const on anything that shouldn’t be changed which is something I really
need to start doing more often. I also definitely agree with including braces
even where optional and I do this always. I think I might try that horizontal
spacing in classes, I really like the readability of it.
As for vertical spacing I don’t fully agree things
should be that compact, it can become hard to read that way, but they
definitely don’t need to be as spaced out as that example either. I generally
keep blocks of logic compact, but will separate each of them by a line so I
will declare variables all together then put a space then do a loop then put a
space and do whatever the next logical part of the function is whether it be
more loops or instantiating anything or setting variable values.
The over-use of accessors is something I do, but that
is just how I have always learned is to keep class variables private and only
allow access through a public interface.
As for comments, I really think heavy commenting is a
good thing especially in a team environment, but even on my solo projects I
comment a lot so that I can remember what I was thinking at the time. I’m still
trying to get better at design though so sometimes my design methodology and
function design isn’t the best so I have to remember what I was thinking. I
need to really break things down more I think and follow that function does one
thing rule.
Reply
DoraDoraBoBora started this
thread
DoraDoraBoBoraby Shawn McGrath
1/14/13 12:33pm
You know, I always thought the coding used for
Neverwinter Nights was great (of course it HAD to be fairly straight-forward
since the game was essentially a level editor) but if you crack open the files
people use to mod games like Baldur’s Gate the coding is even simpler there and
that game wasn’t even intended to be modded like NWN was. Granted, it’s a
vastly simpler game from Doom 3 in some ways, but the way its code is
structured and presented makes it ridiculously easy to not only read and
understand, but also write yourself even if you’re not typically into coding.
All the functions are simple and obvious, you can pick up everything from
context, and it really is a great thing to cut your teeth on before moving onto
bigger and more intricate things. ... not that, uh, I have. Just saying that it’s
another great example of easy to understand game code. (And I think in a lot of
cases the community even wound up streamlining it and making it easier too.)
doomguyDoraDoraBoBora
1/14/13 3:17pm
The code you’re referring to is a scripting language
(which is designed to be so easy to understand even a game designer could use
it), not proper game engine code, so it’s not comparable.
But a scripting language is a great place to get
started for people who don’t want or need to be full-fledged programmers.
Reply
DocSeuss started this thread
DocSeussby Shawn McGrath
1/14/13 4:09pm
I don’t understand code. I survived—barely in
learning C++ this fall, partly because I was learning it at the end of a
lengthy work day, partly because my teacher had never taught (and knew little) C++
before, and partly because, back when I fell ill, my logic/math areas of my
brain diminished greatly.
But... I do get parts of it.
I find myself stumbling through this article, unsure
of what exactly I’m seeing some of the time, but the bits I do get give me a
greater appreciation for the efforts of the folks at id. I’m cool with not
being a good programmer—I’m good at shit like writing (id really needs to hire
better writers...) and design.
I remember reading that Rage had some of the most
beautiful, flawless code out there, and if it had hiccups, those were almost
(if not always) related to driver issues, or the fact that the engine was
severely limited by the weakest of the HD game playing devices, the PS3.
Reply
RealmRPGer started this
thread
RealmRPGerby Shawn McGrath
1/14/13 4:02pm
Actually, std::vector can be shortened up even
further with C++11’s version of for each:
for( myType& item : vector_oftype){
}
This is very nice and very clean, but the Doom 3 code
still predates it, so... irrelevant. But for modern code, I don’t think the
argument holds nearly as much water. Iterators being incompatible with each
other, on the other hand...
Also, almost every time I use StringStream, it’s for
quick string conversion. Sure, atoi etc is likely faster, but it’s a bit
bothersome for the limited scope with which I actually need to use conversions
(aka not in any kind of loop). I combine this with a Binary/Text auto-converter
to output data with a single class as either user-readable format or compressed
data format that can be changed at any time for debug vs optimization.
Reply
xilefian started this thread
xilefianby Shawn McGrath
1/14/13 12:49pm
It’s beautiful until you find the remains of a failed
attempt at an OGL multi threaded renderer and the slow-loading, lazy purpose
implemented human readable scripting.
Don’t get me wrong, Doom 3 gas the greatest code I’ve
ever read, but there’s some design philosophy’s that were lost from Quake3
(scripting) and the gradual move away from the client server design, the OpenGL
multi threading attempt is just a shame that OGL’s limitation has stifled what
would have been a fantastic creation in 1999-2000 when John Carmack started on
it, even Rage contains a third attempt at implementing it.
I haven’t read this article, does it include the use
of bit saturation on the GPU to blend the lighting? That’s my favourite part
Reply
Acidboogie started this
thread
Acidboogieby Shawn McGrath
1/14/13 1:05pm
you lost my sword at the comments section then got it
back after the comments section. Sure I agree that one-line functions shouldn’t
need like 5 lines of comments (or any, for the example given), but sometimes
not having to infer broad scale system design decisions and being explicitly
told can save tens of hours and a ton of frustration especially if you make a
slight mistake with the inference and end up chasing geese that just
coincidentally seem to support the wrong inference. . .
theruegentlemanAcidboogie
1/14/13 1:42pm
Yeah, simple and descriptive comments are incredibly
useful; a little bit of clutter is a small price to pay for ensuring that
someone who is tired and frustrated won’t accidentally skip over what they are
looking for.
Reply
visualdeity started this
thread
visualdeityby Shawn McGrath
1/14/13 5:39pm
I agree with a lot of what was said in this article,
but I disagree with making variables public. In a project you’re working on by
yourself? Sure, fine. But as soon as you have a project where more than one
person is working on it, the importance of having consistent interfaces to each
others’ objects becomes hugely important. You can’t decide that variable X
works better as type Y and change it when your variables are public, because
someone might be depending on it being what it was originally.
It can make for clutter and repetitive methods, but
good encapsulation is a really important practice. Don’t be so quick to write
it off.
Reply
twistedsymphony started this
thread
twistedsymphonyby Shawn McGrath
1/14/13 1:38pm
As a software developer I really loved this article,
myself and another one of the developers I work with are always discussing best
practice ideals in terms of code organization and formatting (since our company
has no standards to speak of).
I was happy to see that a number of the practices we’ve
adopted were mentioned here, but there were a good many more that I’d never
even considered and will definitely look into including with my next project.
I’d love to see more articles like this though I
doubt much of the Kotaku community would find them as interesting as I do. In
any case, thanks for the great read!
Reply
Stuart Marchant started this
thread
Stuart Marchantby Shawn McGrath
1/15/13 1:02pm
I agree with everything except the vertical spacing.
I’ve read so many people’s code that just sucks to go through when their braces
are all over the place. In Java, I can accept it because it can change the
resultant jar size, but in C++ the formatting is critical to transparency and
the sum of “lines of code” is meaningless.
When you work alone, perhaps this is better, but in
my experience, though it might require more scrolling, refactoring and
comparisons in general in a version controlled environment work better when the
braces follow logical indentation rather than being jammed all together.
Reply
macshome started this thread
macshomeby Shawn McGrath
1/14/13 1:51pm
Finding a good coding style is important for anyone
writing code. For example I end up with a lot of comments sometimes since I
usually pseudocode my classes first. Then I can remove redundant comments, but
have a nice flow in comments to read/fill in with code.
Just about every programmer than gets past the
hobbyist stage can benefit from reading Code Complete.
Also make sure you follow the style recommendations
of the vendor you are using the language of in most cases. It makes a big
difference if you are using the conventions that are proper to the language you
are writing.
Reply
Nicholas Payne started this
thread
Nicholas Payneby Shawn McGrath
1/15/13 1:05am
A painfully fascinating read as a student of game
development. The only thing I categorically disagree with is the preference of
a C-style approach over the use of the “<<“ operator in stringstreams.
The latter is infinitely more readable to me. Perhaps that is because I learned
C++ well before I learned C, so C syntax that has been someway “simplified” in
C++ still looks quite bizarre to me.
Nevertheless, this was excellent, and I daresay I
learned a fair bit.
Reply
trigedge started this thread
trigedgeby Shawn McGrath
1/14/13 12:51pm
Great article. More of this kind of stuff on Kotaku.
Anyway... I agree with most of what this article says
except the:
goal of readability > benefits of encapsulation.
Antipattern? If you want to expose your members
outside of the class, then maintain control through accessors. It’s a simple
yet effective technique. Sure there may be cases where it’s not necessary, but
I say better safe than sorry.
Reply
Kellen started this thread
Kellenby Shawn McGrath
1/14/13 2:59pm
I’m just starting as a professional software
developer. I totally understand how helpful using const can be, but the rant
against helpful commenting by using an extreme example of stupid commenting
threw me off.
I think the idea of self-documenting code is a myth.
Your experience when measured against my inexperience may be part of our
disagreement here.
Also, it seems to me you really just want to write C
instead of C++..
Reply
Cerabret started this thread
Cerabretby Shawn McGrath
1/14/13 9:10pm
Reading this gave me the exact same feeling as when i
watched a video in an article over at WoW insider. the article was how cool it
would be to have a mahjong mini-game in wow and included a video of a street
game in Hong Kong. They played at such a speed they seemed telepathically
communicating their moves.
In both instances I can’t claim to understand a
single thing...yet i’m still mesmorized by the act.
Reply
Mythos started this thread
Mythosby Shawn McGrath
1/14/13 12:59pm
That is beautiful, although my only experience with
coding is altering .VMT files to reskin Source models and using a hex editor to
rename those models. Still, I’ve also noticed that even those very simple codes
can vary wildly in style, and the horizontal spacing technique was something
that I already did instinctively to make the code more organized and readable.
Reply
Randall Ward started this
thread
Randall Wardby Shawn McGrath
1/14/13 12:30pm
Ya know, most of this stuff is above me ( I only code
in HTML) I get what you are saying however and this was a damn good article.
Thanks for the uber geek read, I’m sure there will be some that don’t get this
at all and eyes will glaze over reading the article but I thank you for making
my brain do a few push-ups this morning.
Reply
Anodos started this thread
Anodosby Shawn McGrath
1/14/13 4:27pm
When learning to write code, i start with lines of
codes that dont work, then i change or randomly “mutate” them into it does
something, and i have no idea why.
Then when I write something new, everything breaks
and i have no idea why and the process starts all over again.
Unrelated, im retaking programming this year.
Reply
Olaf Piesche started this
thread
Olaf Piescheby Shawn McGrath
1/14/13 5:37pm
“This is a waste of lines of code and reading time.
It takes longer to write it, and read it compared to...”
Oh dear lord, NO IT’S NOT. It may seem like a waste
of time until you need to log the value of x everytime it is changed. Or are
trying to find out which piece of code is changing x to 42. Or are trying to
find out which pieces of code are using the member variable v that describes
the velocity of your space ship. Just three of many examples that mean that, if
x is public, the piece of code you’re looking for, you know, the one causing
the terrible crash, could be *anywhere* in your 300,000 line code base. Have
fun hunting it down with data breakpoints (or greps for ‘v’ over the code base
in the last example). I’ll just set a break point in the accessor and find the
instance I’m looking for in a few seconds, thank you.
Private variables and accessor methods are there for
good reason. Separation of data and interface are important and will save you
orders of magnitude more time than you’re spending on writing them in the long
run. Trust me on this one.
jnewellOlaf Piesche
1/15/13 11:24am
Exactly. This part completely glosses over the whole
reason that you would setup accessors in the first place by using a trite
example class. Sure you can use a public var directly and avoid the accessors,
but you set yourself up for issues when you need to do anything else beyond a
simple get or set of the value.
Doing this simply for style is bad advice.
codeDonkeyOlaf Piesche
1/18/13 10:13am
+1.
getter/setters are an arse to write up, but my God,
these single accessors are a gift when you are tying to debug...
jcbbjjtttOlaf Piesche
2/08/13 4:54am
Thank you! If you’re going to use an OO language, you
need to be taking advantage of encapsulation to protect yourself from stupid
mistakes that would otherwise be impossible to find.
HWBPOlaf Piesche
3/11/13 5:22pm
If you’re using the getter and setter for debugging
alone, you could set a hardware breakpoint on the address.
Reply
Collapse replies
nesstee started this thread
nessteeby Shawn McGrath
1/14/13 1:57pm
The one thing I disagree with is vertical space.
Vertical space makes everything more readable, to me at least. I always couple
my liberal use of vertical spacing with tabbing.
Vexorgnesstee
1/14/13 4:19pm
Agreed. It’s the same thing as putting writing into
paragraphs instead of making one big wall of text. You might be saving a bit of
space, but you’re also going to be making things a lot harder to read than they
need to be.
Reply
Eclipse started this thread
Eclipseby Shawn McGrath
1/15/13 9:05am
actually Doom 3 code is quite ugly in some regards,
the vertical space thing for example, messes up the code indentation, as a {
and it’s relative } should always be at the same column.
But that’s a sort of minor thing of course, overall
it’s very well organized and understandable even if not much documented
Reply
chronophile started this
thread
chronophileby Shawn McGrath
1/19/13 7:06pm
Non-Programmers certain wouldn’t appreciate it, but
going through the clutter of someone else source code can be very frustrating.
Especially when not well commented/documented it can really slow you down when
your on the job. So it’s great to have shining examples like this to pattern
after.
Reply
Veraxus started this thread
Veraxusby Shawn McGrath
1/14/13 1:48pm
Note to Editor:
Replace the square brackets with HTML equivalents
instead of constantly reminding us that square brackets = angular brackets
< is represented by < ;
> is represented by > ;
Sans space, of course.
Reply
TheRogueX started this thread
TheRogueXby Shawn McGrath
1/14/13 5:16pm
I love this article, but damn, I barely understood
most of it. Coding strikes me as an arcane art, lol. I WISH I could understand
it, but I don’t even think I’d get it if I took 4 years of college for it,
hahaha.
Reply
quantity-question started
this thread
quantity-questionby Shawn McGrath
1/14/13 2:48pm
It’s a shame the idTech development tools are so much
more complicated and so DIFFERENT the standards like Unreal and Source in terms
of usability though. Their code really IS great.
Reply
BurkusCat started this thread
BurkusCatby Shawn McGrath
1/14/13 3:37pm
I follow all the idTech 4 guidelines suggested except
the spaces whenever parenthesis are used and also I use lower camel case for
functions, not just variables.
Reply
xilefian started this thread
xilefianby Shawn McGrath
1/14/13 2:24pm
void MakeProgrammerVomit()
{ PukeLots();
PukeMore();
}
Borgle started this thread
Borgleby Shawn McGrath
1/14/13 2:16pm
Good article, though I have an issue with your
aversion to comments. If this is a project that you know for sure that the only
person ever looking at the code is going to be you, then by all means feel free
to abandon comments.
If you are working with a group of people, or if you
are working for a company where someone else may have to maintain your code at
some point, please include comments. While it is useful to think in terms of “Can
I understand this without comments” that doesn’t mean that the next person
looking at your code will be able to understand it.
Perhaps you write a function that returns X but you
want it to return Y. Someone who has to troubleshoot your code later will see
that the function returns Y and not think twice. If the comments say “This
should return X” you’ve potentially saved the person a lot of time.
Just my 2 cents.
xhritBorgle
1/14/13 6:05pm
Agreed. Code is only as valuable as it’s
documentation.
Reply
RetrO[RaB] started this
thread
RetrO[RaB]by Shawn McGrath
1/14/13 12:27pm
Umm... it’s John Carmack, did you expect anything
less than beautiful perfection? The guy is a fucking master of his trade, and
is 90% of the reason why Id has created such legendary and influential titles.
Immediately after Wolfenstein 3D’s release, he said “I can do this better” and
a few years later, bam, we had Doom, which solely brought the FPS to the
mainstream, and has led to the creation of many beloved FPS franchises, as well
as influenced the action/horror genre what with Doom’s tense, horror plot. Love
you JC, Doom 4 plz<3
RastervisionRetrO[RaB]
1/14/13 12:55pm
Organizational skills and genius aren’t skills that
are commonly found together. I’ve worked with a number of brilliant programmers
than had no concept of clean well organized code.
Mr_AntimatterRetrO[RaB]
1/14/13 1:37pm
Me and a programmer friend got to speak with him at
Dallas’a A-kon anime con one year.
It was like talking to Jesus. Seriously, the man
knows his stuff, and is happy to talk with you about this or that. He casually talked
about re-writing the Doom III audio code, for example, like it was a walk in
the park. Yet that same task would have taken me years.
Also, the man does not age. It’s like the saying
goes: once you hit max level, you stop leveling.
RetrO[RaB]Mr_Antimatter
1/14/13 4:48pm
You’re very lucky indeed! The guy is seriously a
master. Could he be the second coming of CodeChrist?
RetrO[RaB]Rastervision
1/14/13 4:51pm
You raise a very valid point - there are plenty of
guys who can put together some spectacularly functioning code, but it could
look like a complete mess. The fact that JC can be such a brilliant programmer
AND be so organized is like a miracle, and it shows. The guy can do the same
thing that 14,000 lines of code can do in 8,000 lines of code - I’m surprised
he doesn’t do freelance code optimization. Someday, he’ll make Doom run on a
wristwatch - it’ll happen.
bullshooter4040RetrO[RaB]
1/14/13 8:34pm
The great thing about Carmack is his ability to make
the incredibly complex sound simple even if you don’t quite understand it. His
command of his craft and equal ability to explain it is wonderful and quite
rare in the software industry.
Reply
Collapse replies
13xforever started this
thread
13xforeverby Shawn McGrath
1/14/13 1:54pm
C++ is a mess of a language, thus a lot of
unnecessary ugliness when it comes down to using newer features. C++0x (now
C++11) is an attempt to modernize it without making it even worse (yes, they
learned from templates… I hope), but it’s still very hard to do, because the underlying
language design is so old.
So, let’s hope someone will come up with a new
language that will incorporate all the language designing experience of past 30
years or so.
Personally, I won’t go near C/C++ if I have a choice,
I’m all for C#. Yes, it’s not perfect and it won’t cut it for a few specific
tasks, but it fine for almost anything, including some games. And it’s clean
and nice.
The man for the job13xforever
1/14/13 7:37pm
As long as C# is controlled so stringently by
Microsoft, I wouldn’t touch it. I work in enterprise (generally, not ATM), and
using C# is shooting yourself in the foot majorly. Those Windows Server
licenses are extremely expensive, not to mention that third-party support
reeks. Same goes for games. How are those games going to run on Mac and Linux
without major debugging efforts? Mono still lacks support for a lot of the .NET
framework, the single feature of C# that makes it a worthwhile language.
I think Pascal is quite nice. Compiles down to
bytecode. PascalStrings (BIG improvement over C). And anyway, for low-level
stuff you should be using straight C without any memory-inefficient OO crap.
I am a big fan of the JVM personally. Again, super
efficient, and a big plus is I can use just about any language I want - in my
case, Ruby (JRuby is the implementation). Ruby is the perfect language as long
as you agree with the Perl philosophy. It’s how you do OO right. Non-pure OO
languages like C++ are just doing it wrong. You can also use various dialects
of Lisp if you’re into that, Smalltalk... you mention it. It exists. And hey,
Scala REALLY nicely makes Java into a great language. It’s a very impressive
effort and again takes the kitchen sink approach, except that it adds features
like functional programming. You should check out Scala and JRuby, and in
general, respect the JVM, yo.
13xforeverThe man for the job
1/15/13 1:05am
I see it’s a popular belief about “tight Microsoft
control” and closed ecosystem. I’ve had this discussion not so long ago on
reddit:
And yes, Mono is a little behind is case of BCL and
compatibility with Microsoft libraries, but on the other hand they have a lot
of Mono-specific libraries (cecil anyone?). Not by far, mind you, and it’s not
all that critical for games either: look at all the XNA titles ported to OS X,
Linux and even consoles (not only XBox360 mind you).
Pascal is nice, yes, I only gave my favorite language
away. This doesn’t mean there are no other alternatives ;)
JVM on the other hand has the same issues that C++
does. It’s old. It’s design limitations are causing all sorts of problem for
expanding support for newer features. It’s ugly, it’s slow and it’s less and
less usable. It’s still manages, but in terms of long-term evolution, it’s had
its peak of fame I think.
TruYuri started this thread
TruYuriby Shawn McGrath
1/14/13 6:34pm
“Another thing that id does that I believe is “right”
and not a style issue is they *ALWAYS* use { } even when optional. I think it’s
a crime to skip the brace brackets.”
This is my only real problem with this article. I
skip them because they are unnecessary and without them think code looks
cleaner. In your and/or Doom 3’s examples, the mess of brackets on such
conditionals looks trashy.
EDIT: Just for clarification, I do insert them when I
first write the conditional, in case more code needs to be inserted. If not,
though, I really don’t think it’s a crime to not have them.
minneyarTruYuri
1/19/13 9:35pm
Thinking the “code looks cleaner” is the only reason
why you would ever skip them, and it’s not a very good reason.
I’ve been working on a project for the last several
years where one of the coders never puts brackets around his single-line
conditional statements. He is, of course, convinced that it looks better and
there will never be a need to add another line.
Inevitably, somebody else will come along and have to
fix a bug in the code, and they’ll have to add another line to it. Usually they
notice it doesn’t have brackets and add them — but sometimes they don’t,
because it’s easy to miss when you’re used to relying on indentation to mark
blocks of code. So every once in a while somebody will add a new line of code
that breaks the conditional statement because the second line is no longer part
of it.
Sometimes the effect is immediately obvious, and
sometimes it introduces very insidious, subtle bugs that take days to diagnose
and fix. It’s not an exaggeration to say that over the five years or so this
project has been under development, we’ve probably lost a few weeks’ time to
bugs that were introduced as a result of somebody writing a bracketless
conditional because it “looked cleaner.”
Always, always, always put brackets around your
if/else blocks. I don’t care if you think it looks cleaner. It’s not about you,
it’s about the maintenance programmer who has to fix your bugs in half a year.
(Actually, just last week I added another step to our
build script that lints the code and throws an error if there are any missing
brackets. The guy who never uses them hates it, of course, but everybody else
likes it, and he doesn’t get a vote because I’m in charge of maintaining the
build scripts.)
TruYuriminneyar
1/19/13 11:55pm
I was more referring to personal projects and not a
team project. I’ll code my personal projects however I want, and adhere to team
standards when I need to.
Reply
Christopher Todesco started
this thread
Christopher Todescoby Shawn McGrath
1/15/13 5:30pm
I hate curly braces at the end of the lines; I always
put them on their own line. It’s not that I like vertical space, although I don’t
get the obsession with conserving it— it’s not paper, you’re not “wasting”
anything. But what bugs me the most about it is your curly braces aren’t at the
same point on every block, it can get lost in a wall-of-code, and if your
conditional statement is exceptionally long it can end up off the screen. It’s
for that reason that I will always use
}
else
{
minneyarChristopher Todesco
1/19/13 9:24pm
Putting them on their own line won’t make you “run
out” of space or anything, but it does mean you can’t see as much code on your
screen at once, which is annoying. The indentation levels in your code should
make it obvious when blocks begin and end.
LpintoChristopher Todesco
2/05/13 5:18pm
He lost me when talking about saving vertical space..
i guess he doesn’t spend a lot of time trying to fix another guy’s code..
saving vertical space like that is way harder to read the code, and if i start
talking about debugging code.. try debugging code like this
if ( x != y ) { std::cout << “hello world”
<< std::endl; int j = callafunctionherer ( x, 3); }
Reply
sarcasmrules started this
thread
sarcasmrulesby Shawn McGrath
1/14/13 1:07pm
I put the opening { on it’s own line... and I also do
too many unnecessary line breaks. Overall, this article makes me feel guilty.
mangobrainsarcasmrules
1/15/13 4:29pm
Please don’t feel guilty about this. I HATE the
bracing style in the article. Mine used to be identical, but I found myself
making up rules about whether or not the brace went on its own line if I had to
split a long if statement/function declaration over multiple lines. Once you
start making up rules on the fly, other developers on your team will get them
wrong (because they aren’t you), *you* will get it wrong (because you’re
evaluating it case-by-case), and eventually you will find yourself spending too
much time playing “hunt the curly brace” when reading over old code.
ALWAYS put the brace on its own line. Omit the braces
IF AND ONLY IF the if-condition fits comfortably on a single line, and the code
inside the block also fits comfortably on a single line. Then you know if you
see braces, to think “code starts here”; if you don’t see braces, the code is
concise enough that you don’t need to think.
sarcasmrulesmangobrain
1/15/13 5:03pm
Cheers man, I guess code *is* easier to read if you
can clearly see where braces begin and end.
Reply
dekonstruktiv started this
thread
dekonstruktivby Shawn McGrath
1/14/13 5:55pm
i’m still tryongto comprehend the purpose of the
final “const”. although i’m a fairly experienced software developer, i have
very little experience experience with anything C++.
if anyone would be able to clarify this detail for
me, it’d be very much appreciated.
mangobraindekonstruktiv
1/15/13 4:43pm
The trailing const on a method definition means “allow
calling this method on const instances”. For example, if I have a Player class
with moveTo() and getPosition() methods, it makes sense to make getPosition() a
const method (because it only reads things from an instance), but not moveTo()
(because it modifies things inside an instance).
If I don’t declare getPosition() to be a const
method, then I can’t call it from a function which has a const Player& as
an argument. This is bad, because it means I can’t write const-correct code
which deals with Players, leading to an overall lack of const-correctness in
the code base as a whole, meaning I lose all kinds of warnings and errors the
compiler might otherwise generate. Declaring it const means I *can* call it on
a const Player&, the compiler prevents me writing code inside the method which
accidentally modifies any class members, and because a const Player& can
now be used in a meaningful way, I can continue making the rest of my code
const-correct.
Proper application of const-correctness even protects
against noob thread safety errors. For example, the [] operator on a std::map
is *not* declared const, because the operator doesn’t just read the contents of
a map - it also auto-creates keys which didn’t previously exist. Using [] to
access a shared map in a multi-threaded program is a great way to turn a
harmless-looking read into a write, leading to race conditions, memory
corruption and endless hours of debugging fun. If you have a map as a data
member, the compiler *won’t let you* use [] on it inside a const method,
preventing the mistake from ever happening.
Apothecary101dekonstruktiv
1/16/13 5:05am
It means that method won’t change the object’s state.
Reply
The man for the job started
this thread
The man for the jobby Shawn McGrath
1/14/13 7:27pm
Non-standard C++? Disgusting.
Actually, just the fact it uses C++ is awful. It’s
such an unnecessary extension to C - a brilliant language - and it loses many
of its benefits. Frankly, you need to be a very good programmer to do OO in
non-fully OO languages such as C++. The OO feature is seriously overrated.
If you want an example of a near-perfectly
architectured program, look at the Linux kernel. Not all code is perfect (it
receives thousands of code commits by 600+ genius software engineers a month
which are carefully regulated), but the architecture is amazing. I think
Torvalds is the Knuth of our generation - except that he put his ideas into
practice and created a highly successful project with it.
I’d love to see a code analysis of the Linux kernel!
It’s 14+ million lines of code (mostly C, some assembly and make et al), but
you can skip most things like drivers. Just the fact such a portable and yet
extremely efficient, cutting-edge and powerful kernel can fit in 14 million
lines is a wonder in itself.
The man for the jobThe man for the job
1/14/13 7:28pm
TL;DR: I’d take procedural programming over OO
anyday.
Apothecary101The man for the job
1/16/13 4:45am
You say that because you’ve never worked in a project
with more than 500K LOC. Heck, I bet you’ve never worked in a project with half
that size...
Reply
CHOPPERGIRL started this
thread
CHOPPERGIRLby Shawn McGrath
1/15/13 5:35pm
You C programmers write some hideous code. IMHO, C
needs to eat a hot death and die. The only reason this hideous beast is still
alive is because it compiles fast code, and that’s it. Braces and pointers and
handles need to burn in hell. So spoke a python game programmer.
I disagree about commenting. You should comment
liberally and profusely out the ass. Comment everywhere. Comment as necessary
where necessary. Nothing is obvious by looking at code. One comment with one
brief sentence in it can describe a world of what is going on in a function,
where as it’d take you an hour or more looking at the function going through it
line by line to try and figure out what the fuck is going on.
What does it matter how much you comment... its
ignored at compile time and adds zero bulk to the finished product... both in
times of compile time and executable size. So please, comment, comment, comment
out the ass. Comment with your name and email address somewhere. So I can write
you when shit breaks. Or I can report a bug in your code to you.
I comment out lines all the time... and leave them
there. Because it tells me what I’ve tried, what didn’t work, and what I may
want to uncomment later, fix up, and use all over again.
Then need to beat it into your heads in Programming
101. Don’t be afraid to comment. Comment to help you. Comment as you need to.
Comment important shit you don’t want to forget. Comment. Comment. Comment.
Most of us hardcore programmers learned programming
right from the bare metal, learning cool new tricks looking at other people’s
programming and reading.. their comments... if nothing more, a line at the
front of the whole program, telling you what it does in one sentence.
CHOPPERGIRL
minneyarCHOPPERGIRL
1/19/13 9:22pm
Liberal commenting is a crutch for bad coders. As you
said here:
One comment with one brief sentence in it can describe
a world of what is going on in a function, where as it’d take you an hour or
more looking at the function going through it line by line to try and figure
out what the fuck is going on.
Comments should never be used to explain what a block
of code is doing. If a block of code is so complex that it takes an hour of
looking at it to figure out what it’s doing, then it was written poorly and
needs to be rewritten. Comments should by used for explaining why a block of
code does something, so that when somebody comes through and wonders, “Why did
they do it this way?”, they’ll have the answer.
I comment out lines all the time... and leave them
there.
This is a terrible practice if you have to
collaborate on a team with other people. Inevitably, somebody else will be
reading through your code, see perfectly legitimate code you’ve commented out,
and wonder, “Why is that commented out? That looks like perfectly good code!”
Then they’ll waste time checking to see if it works and trying to figure out
why you left it commented out in there.
There is never an excuse to leave code commented out
because you may need it later. That’s what a version control system is for.
Just delete code when it’s not being used; if you need it later, go back to a
previous version and grab it. If you need to explain why you did something in a
particular way, then that’s what a plain language comment is good for.
Then need to beat it into your heads in Programming
101.
I’ve worked with a lot of programmers who did get it
beaten in their heads in “Intro to Programming,” and it’s terrible. Their code
is filled with diarrhea in the comments. They’ll write a five-line function
named “doThisThing” that has a big comment header on it that just says “does a
thing”, then inside it they’ll declare a variable named “myVar” that has a
comment next to it saying “This is my var”. I’ve seen files that had four
copies of a single function in it, three of which were commented out with no
explanation, because apparently they didn’t trust their VCS.
Reply
Darkmoon_UK started this
thread
Darkmoon_UKby Shawn McGrath
1/14/13 2:50pm
Nodded along very happily with most of this article,
it’s nice to see someone take the time to appreciate the craft of anothers
code. It’s not something you can get at first glance and takes an investment of
time. The only thing I disagree with strongly is the endorsement of K&R
style. K&R brace style is ugly and asymmetrical: the beauty of code - where
practical - should extend to its on screen layout, and this means visually
matched braces: far easier to read. Even Kernighan and Ritchie themselves deny
actually proposing this style - stating it as a mere ploy to save the per-page
printing cost in text-books. Personally, it’s utterly offensive to my eyes and
thought process. But, hey we’re all different and the auto code formatting
features in any respectable modern IDE can set the format this way or that, at
the whim of whichever programmer happens to be working on it.
Levi DettwylerDarkmoon_UK
1/14/13 4:08pm
“Even Kernighan and Ritchie themselves deny actually
proposing this style - stating it as a mere ploy to save the per-page printing
cost in text-books.”
A source for that would be positively splendid.
Reply
ArindamChakraborty started
this thread
ArindamChakrabortyby Shawn McGrath
1/16/13 8:20am
In the first snippet of code, if idPlane is supposed
to be const and not to be changed, why does it need to be passed by address? A
simple pass by val should have been enough!
minneyarArindamChakraborty
1/19/13 9:08pm
Passing by reference is more efficient than passing
by value. To pass an object by reference, the processor only has to push a
pointer on to a stack; to pass by value, it has to make a copy of the entire
object you’re passing in, which can be much slower for large objects.
Honestly, there’s almost never a situation where
passing by value is actually a good idea. Many languages (Java, Python, Ruby,
etc.) only allow passing by reference.
Reply
Marauder_Shields started this
thread
Marauder_Shieldsby Shawn McGrath
1/22/13 10:56am
Okay, I’m not sure how often you program, but I
program literally every day, either for work or for fun. [EDIT: I’m not
pointing this out to brag or anything; I just wanted to qualify that I work
with code a lot, before I started ranting]
I have to say that this article really and truly
concerns me.... I’m seriously worried for the ideas you’re giving young / new
programmers, because a lot of this is flat out BAD. Not to say that everything
is wrong, but there are a few points that are just not things you should do if
you are trying to write good and maintainable code.
First off, saying that direct access to class
properties is better than getters and setters is TERRIBLE. That is entirely bad
practice. There’s a reason why getters/setters are popular and are good
practice. Abstraction is GOOD. You almost never want to directly be
manipulating underlying data, especially when you are working with a class
external to the current one. Why? Because /HOW/ data gets set might be more
complicated than just adding something! Some other calculation may need run
when you alter a variable, some flags may be set as well. There may some
formatting that happens when you get a variable. If you are working with a
third party library, and they change the implementation of how something works,
and you’ve been using direct access to properties, your code may be entirely
broken!
If you rely on always being able to manipulate
underlying data, you’re going to get screwed at some point. Whereas, if you
rely on always using getters/setters, you might have to type a little bit less
code, but that’s not really that big a deal. A big and important principle in
object oriented programming is that people don’t need to know how a class works
to use it. You SHOULDN’T need to know it. If the original programmer provides a
nice interface for dealing with the class, you can rely on those to always
work, regardless of how they change the underlying properties or private
methods.
Your advocation of direct property access is somewhat
in opposition to your statements about const / rigid parameters. You shouldn’t
be directly fiddling with things that aren’t parameters to your function. It’s
a related concept; you shouldn’t be directly meddling with properties, because
you may not know what depends on them.
Not to sound insulting, but your emphasis on “waste
of lines of code” sounds frankly like something a first year comp sci student
would say. Lines of code aren’t endangered. Fewer lines does not make it go
faster. Your definition of “more readable” as “I can fit more functions on my
screen” is in fact not the definition of readability. Your definition of
readibility is great if you have a fairly intimate knowledge of the code, but a
lot of time that isn’t the case. I will say, however, that there is a correct
balance for whitespace; too much makes things difficult, and you can lose
grouping, but squishing things up too much makes it far harder to mentally
parse what is going on, and to quickly pick out particular lines.
This isn’t a code-only problem, whitespace is
important when ANY text is presented on screen. Here’s some information about
the importance of visual whitespace in UX design:
http://uxmyths.com/post/2059998441/myth-28-white-space-is-wasted-space.
They make the point that proper use of whitespace “Allows for easier
readability and scannability”, and “Prioritizes” elements. The same goes for
code.
And comments. Oh comments. This is a tricky one.
Comments are necessary, but I do agree there are times where they are
pointless. But not every single function ever can be renamed in such a way that
they need no explaination. Writing comments is a vital part of writing good
code, especially if you are working with a team and not just yourself.
Overcommenting is not really a bad thing, unless you have 10 lines of comments
before each single line of simple code. I tend to think about things in terms
of “what if somebody else was using this code as a library” when I write code.
Yes, my function name may be self explainatory... in context. But a user who
knows the gist of what my code does, but not specifics, might be entirely
confused about what “fetchThingaMaBob” does.
oookay, whew. That was long. Aaaaall of that being
said, there are a number of very good points you bring up, and I think the most
important is use of const and properly managing data. Being someone who has
done a little Functional Programming, and loves it conceptually, there is a lot
of value in immutable data and respect for scope. I find it interesting that id
chose to reimplement a lot of STL, but I also think that sometimes that can
make a lot of sense. The point about unified parsing is also a good one; if you
can reuse code (without cobbling together some unholy frankenstein program of
barely fitting classes), you can. That’s the fundamental point of the DRY (Don’t
Repeat Yourself) principle.
Reply
masturbating_bears started
this thread
masturbating_bearsby Shawn McGrath
1/14/13 9:58pm
Thanks for sharing. Unfortunately I have to say, I
disagree with this guy on soooo many fronts. Your definition of beautiful code
is literally code that looks nice. I agree that readability is very important
when writing code, but you’re sacrificing performance and going against
standards that are there for a reason (ex. making a field public in a class so
you don’t have to write getters and setters for it; I died a little bit inside
when I read that).
“I can read that entire algorithm on 1/4 of my
screen, leaving the other 3/4s to understand where that block of code fits
relative to its surrounding code.”
Okay, but is it easy to parse and read with no white
space logically separating similar tasks? White space is very important in code
for readability. It changes a block of messy, hard to parse, statements into an
easy to read and understand piece of code.
“What does that even mean? I can’t even find the
method name without some aggressive syntax highlighting. It’s conceivable that
there’d be more definition code than body code. This is clearly not easy to
read and thus not beautiful.”
You could have easily solved that mess of templates
if you took 5 minutes to stop coding and did a little system analysis. Code
that is designed efficiently is the most beautiful code of all, from a
performance and an architectural point of view.
“I think programmers are taught in school that
comments are good; they aren’t. Comments are bad unless they’re totally
necessary and they’re rarely necessary”
That is the most wrong thing I’ve ever read. If a
programmer is coming into an in-development project and needs to understand the
code base quickly without really worrying about implementation then comments
are very, very necessary.
The only things I really agreed with was the const
and rigid parameters, and always using curly braces, regardless of the number
of statements in the block.
/rant
Reply
mangobrain started this
thread
mangobrainby Shawn McGrath
1/15/13 4:55pm
ALWAYS PUT BRACES ON THEIR OWN LINE.
ALWAYS.
DO IT NOW.
I used to put braces on the same line as function
prototypes, if-conditions, elses, switch statements, you name it. Then,
occasionally, one of those things would get so long that it needed to be split
over multiple lines to be understandable, and suddenly I had a problem - if the
continuation of the if-condition is indented, and the code inside the block is
indented, where does one end and the other begin?
So I started making up special rules on a
case-by-case-basis, so sometimes braces would be on their own line, sometimes
they wouldn’t, and sometimes they wouldn’t be there at all. As time went by, I
started working on development teams instead of by myself (the horror!), and
those other developers annoyed me because they couldn’t follow my style when
editing my code - but of course this wasn’t *their* fault, because my style
wasn’t consistent. I also found myself spending more time figuring out the
structure of old code; time which should have been spent thinking about its
function.
So, the rules I have now are simple:
1. If you’re going to use braces, put them on their
own line.
2. The only time you do not use braces is if BOTH an
if-condition (or the word “else” on its own), AND the code inside it, fit
COMFORTABLY on single lines. Two *different* single lines, that is. (Obviously
this means the code inside must be a single logical statement, but it also
means that you still use braces even if the only reason it takes two lines is
because it’s commented.)
Stick to this, and two things start to happen:
firstly, as soon as you see braces (which are now clearly visible), you know “code
starts here” without thinking; secondly, the only time you *don’t* see braces
is when the code is so tiny that you’ve already read it without thinking.
When I’m reading your code, I don’t want to think
about syntax, I want to think about functionality.
Reply
Apothecary101 started this
thread
Apothecary101by Shawn McGrath
1/16/13 4:43am
It means that method won’t change the object’s state.
Apothecary101Apothecary101
1/16/13 5:06am
I messed up, some remove this comment?
Reply
galopin started this thread
galopinby Shawn McGrath
1/20/13 5:20am
I am not as happy as the others when i read this,
sorry, and i will try to explain you why.
1. length versus getLength :
Get has a strong means of retrieve from memory for
coders, but here you compute a length, and so, the verb is wrong even in your
convention. It adds a missunderstanding of the method underlying
implementation. That’s why it is better to not put a verb when talking about
properties. The implementation may also change with time and again, the verb
will become invalid even if the property name remains valid !
2. public members :
This is the most terrifying advise you gave. public
members are a nightmare for code maintenance, refactoring and debuging. a class
is a black box providing a service (and in a perfect world, a single service).
To ignite a car, you do not bypass it to directly interact with the engine, and
so class/service do not expose so often their members. In your example, you
argument with “what if i want to often add some value to a class member”, i
would say that if you need to do that often, this is mostly because the class
should expose a method with the increment value to do it for you. This is a far
safer and maintenable code.
Imagine that the class is a monster, and the member a
damage amount. If at a time, you want to trigger some mechanism when the damage
amount is more than a value, you will have to update a lot of sparse code and
copy/paste (the first number one bug creator). With a method service, you keep
the change in a single spot. With time, you may also want to change the damage
amount underlying type from int to float. Again, with the member method, you
keep the modification in a single spot, you may even prevent older code to
compile and safely update all the spot where you still add an int by declaring
the old method signature as = delete;
A third example on this simple one, what if instead
of holding a separate damage amount, the monster class is change to keep only a
life amount and takeDamage had to substract the amount instead of add it !
3. Simpler template services :
Once remove the old story of compiler not so great
with dealing on highly complex template code. Did you not think about the
possibility that the id studio developers have to stick on a schedule to
release a game. Coders capable of writing a really good hastable generic enough
enough were probably more usefull at optimisation the engine ! Take the choice
to not push the generic programming is never a design choice, it is a matter of
man ( man-days on writing it, man-days on debuging it, man with enough
knowledge to do it well, ... )
4. swapping declaration/definition and
function/method :
In the article, you use the terms a lot, and several
times you miss were wrong with the meaning of them. classes declare methods,
and if you are not in a class, you are a function. The term “free function” is
in fact a pleonasm.
The article purpose is to give advice to less skilled
and experienced programmers, you should be really strict on terms. A
declaration expose a class layout and method signatures, a function signature
or some variables. Then the definition implements the declaration, by giving
the code for functions and methods or instancing a type to a named variable.
This knowledge will help a lot with some of the most common compiler and linker
errors for example.
To not be only negative, you are right on some points
to me :
* a good managment of constness is important, and you
should listen at this for a modern point of view on the mechanism if you are
interested in modern C++ : http://herbsutter.com/2013/01/01/video-you-dont-know-const-and-mutable/
* reduce spacing to have more code visible on screen.
I will emphaze the need of good syntaxic colorisation for that and if you have
a method that is more than one screen, there is probably a problem more
important than the spacing.
* be right on the comments you add in code,
meaningless repetition is not only an evil inside databases.
Reply
LudovicUrbain started this
thread
LudovicUrbainby Shawn McGrath
1/30/13 4:49am
Thanks for the article, it’s really interesting.
About the spacing and {}, I’ve coded like that since
day one, just because it felt right (self-taught PHP at the time).
Never went into the OO / modern style of either
skipping brackets (I’d honestly fire people for that) or putting them on
another line (imho the shorter way is always clearer).
About the over-C++ization : writing class ClassType
is over-OO already, and you can’t just use OO if you’re trying to write fast
and reliable software, because it’s an overweight inadequate (in most cases)
dirtyboxing (in many cases) approach to programming.
About string construction, if there were no
performance penalties, I’d always vote for newstring = string1.string2.string3.’sep’.string4
.
Printf has always looked overweight to me (although
it probably isn’t).
And of course my hunch was right as usual, because
the printf parameter mismatch is a direct consequence of separating the logic
in two lists (you can’t actually have parameter mismatch with a simple concatenation
operator, be it . or concat(s1,s2,’,’,s3,s4)).
Operator overloading is evil, take a functional
approach instead, it will be both cleaner and safer, unless we’re talking about
a missing language function, like in this case vector add/multiply. In that
case vectors should not be classes but types by the way.
Simple is beautiful, adding a get before length
stinks of OOP and excessive verbose.
There is nothing gained from adding get or set
anywhere in code.
About the Style Conventions:
Space Padding of parenthesized expressions, no
thanks.
if(x==3){
print “fu”;
}
If you have issues reading it, your text editor has a
text spacing option somewhere.
Headers for functions are annoying, they make the
source code too long to read, and the rest is useless OO stuff, so I can’t
really comment on that.
Reply
parkedcar started this thread
parkedcarby Shawn McGrath
1/14/13 12:43pm
The only time I’m commenting code is when I’ve
hardcoded something for testing purposes (IE: I don’t have a required value, so
I’m setting it to a valid value) or if I’ve done something I know is poor
practice, but justified. “Did this because this,” with a brief rundown of what
it’s doing so that when someone else has to touch that code, they see my
land-mine and understand why it’s there. (before throwing it to a proper way,
having it blow up again, and then having to revert it.)
I do agree with the verb on function naming, too.
Good read, though. As a rookie programmer who’s
skirting the idea of game development it’s always fun to hear other programmers
rant about pet peeves.
Reply
pwn463 started this thread
pwn463by Shawn McGrath
1/14/13 1:20pm
This is a terrific article! I also happen to agree
with everything you said, but even if I hadn’t it’s still interesting to see
what practices teams use to keep their code maintainable through the lifetime
of the product. Can we have more of these code dive articles?
The one thing I didn’t agree with 100% in your
analysis was comments. Comments describing “what” a method or class is doing
are dumb, and can be communicated better via method names, but comments
explaining “why” are very useful. A comment explaining why a particular
solution to a problem was used can save a lot of work when you (or someone
else) have time to refactor that code; there’s a big difference between “prototype
code, rewrite when I have more time” and “because of blah blah blah we couldn’t
use solution1 and had to go with solution2.”
Reply
DaveVdE started this thread
DaveVdEby Shawn McGrath
1/14/13 1:31pm
The one point in my life that I can say that changed
my thinking in programming was when I was building a UI toolkit for an
industrial controller using Anti-Grain Geometry as the 2D drawing library (http://www.antigrain.com/). In it, almost
every aspect is written in the form of a template, finely grained and
composable, basically a bunch of algorithms that are combined into powerful
stuff. There was very little documentation, so you had to rely on the
sourcecode, and it opened my eyes. Before then, I felt that templates were the
stuff of collections and iterators, but boy I learned.
Now I’ve moved to C#, and have to do with generics
and reflection and LINQ, but I still carry some of what I learned back then
with me.
Reply
Demo-grafic started this
thread
Demo-graficby Shawn McGrath
1/14/13 1:35pm
Wow. You sound just like my IT director, and I don’t
mean that as an insult
My boss is a very big proponent of clean, functional
code. I’ve been studying PHP, and while I can make some functional, rudimentary
web applications, the code is ugly as fuck, and the last thing I wanna do when
I’m done with it is re-factor the code.
I totally understand the need for clean code when
making something that can be hardware intensive, like a game, but when I’m just
building a simple Asset Management web app, the last thing I want to hear after
testing is “Well, it works, and it’s pretty fast, but your code sucks. If you
did this and changed code A to code B, your “add_new_asset” function would probably
be about 1 or 2 seconds faster.”
Personally, I’m not the kind of person whose willing
to spend two hours refactoring code to shave 1 second. It’s not that I have
contempt for it, quite the opposite, but my mind always brutally fights me on
things like this.
Things like this have convinced me that coding is not
in my future. While I respect his opinion, and understand the WHY for clean
code, I simply know myself enough to not have the patience to invest deeply
into doing something like this for a living, especially knowing that the guys
who know what they’re doing are always gonna have a better way to do it. I’m
perfectly happy being a network admin and all-around go-to guy for company
support.
Reply
gwwar started this thread
gwwarby Shawn McGrath
1/14/13 1:37pm
I’m not that familiar with C++ but here’s the tl;dr
version:
* Don’t mutate your inputs as a side effect of
calling a function. It will cause unexpected behavior.
* Your function name should say what it does.
* Only comment when you need them.
* K&R 1TBS spacing is better than Allman style
(is this a graphics preference?)
* Brackets shouldn’t be optional (python would
probably make the author sad)
* Template (generics) code is ugly and hard to
follow, only use it where it makes sense.
* Don’t put C’isms in C++
* Operator Overloading for Vector Math makes sense
* Operator Overloading for Strings is hard to read,
use printf with formatting
* Use consistant tab spacing
* Use Java style naming for method names
Reply
Irma_Gerd started this thread
Irma_Gerdby Shawn McGrath
1/14/13 5:02pm
“I can tell what this method does by its name. If its
function can’t be inferred from its name, its name should be changed. If it
does too much to describe it in its name, make it do less. If it really can’t
be refactored and renamed to describe its single purpose then it’s okay to
comment. I think programmers are taught in school that comments are good; they
aren’t. Comments are bad unless they’re totally necessary and they’re rarely
necessary.”
Software Engineers please disregard. This person has
obviously never worked with cut-rate “developers” hired last week to meet the
upcoming on-site UAT deadline.
I love clean code, and I get where this guy is coming
from, but I think he forgets that a lot of projects have code, and a lot of
projects hire people that lied when they said they’re coders just to get a
sweet gig. Documentation is seriously necessary.
Reply
Mmmmhm started this thread
Mmmmhmby Shawn McGrath
1/14/13 7:19pm
Must be a game developer thing. I guess when you know
you’re going to write the game, release it and bug fixes for 6-12 months after
aside, won’t be messing with the code again, you don’t focus on keeping things
clean.
Try doing that on projects that need to be enhanced
and maintained for years or even a decade after initial release and see how
hard life gets.
You write it once, you rewrite it a million times. In
90% of cases, readability and maintainability are more important than
performance or “elegance”. Your sloppy code or overly optimized or overly
abstracted code ends up costing far more in labor costs to maintain than it
saved when you cut corners or tried to over-engineer it in the first place.
Reply
AlexGK started this thread
AlexGKby Shawn McGrath
1/14/13 8:47pm
Great article. Just a few things I don’t totally
agree with:
1.- Comments, done wrong, can be a nightmare, and
make things even less comprehensible. However, saying comments are no good at
all it’s quite a falacy. Self-documenting code, as of today, is a holy grail, a
utopic goal.
Not all methods nor all lines of code require
explanation, but some of them do. Even using comments in Visual Studio (idTech
4’s compiler) has its advantages (explanation of method and parameters while
typing, thanks to Intellisense). The PPP (Pseudocode Programming Process http://www.coderookie.com/2006/tutorial/the-pseudocode-programming-process/)
is a great tool to keep comments informative, useful and easy to maintain...
not that I practice it. I know I should.
2.- Not hiding your variables is a highway to logical
clusterfuck. Information hiding is a powerful tool to manage a program’s
complexity.
3.- Definitions with horizontal tabing are evil. I
remember reading variable/parameter definitions with TWO columns, each with
tabs. Easier to the eye? Maybe. Hard to edit? Hell yeah. Not worth it.
Reply
JaTochNietDan started this
thread
JaTochNietDanby Shawn McGrath
1/14/13 9:28pm
Quite a good article. Although I would like to point
out one style of coding that I do not like and it’s this idea of adding spaces
everywhere within functions and statements. Like the for loop example where it
does not have brackets on separate lines.
for( i = 0 ; i < in->numVerts ; i++ ) {
dot = plane.Distance( in->verts[i] );
That just annoys the hell out me. I know it’s
nitpicking but I stick to this:
for(i = 0; i < in->numVerts; i++) {
dot = plane.Distance(in->verts[i]);
// dot = plane.Distance(in->verts[i], sides[i]);
(If there was a second param)
I guess really it’s just about habit and personal
preference when it comes to something like this. I just find the former to be
going too far with trying to be neat.
Either way, good article. I’ll have to take a look at
the Doom 3 source code sometime.
Edit: Kotaku’s commenting system doesn’t show my
indentation unfortunately.
Reply
Optimus6128 started this
thread
Optimus6128by Shawn McGrath
1/15/13 9:53am
That’s a very interesting articles and there are some
programming disciplines I could learn from (I never bothered about const for
example).
About the brackets positioning, beauty and
practicality can be subjective. For example not only I have a hard time reading
code where the brackets are put to the right after the for (I can’t clearly see
the start and end of a code block) but the longer version seem nicer to the eye
too to me (first code looks too squished to me). I’d definitely go over longer
pages of code that are more clear to my eyes, but that’s a personal preference
anyway.
I only wonder what happens when one works in a
company with a quite different style. In my first job, coders were happy I also
followed the bracket below the line style. I am working in another project
where it’s the more squished style and I had to bring some brackets down in a
code with lot’s of if/else logic to understand what’s happening (but it was a
bad code anyway :).
Reply
TheRealJoped started this
thread
TheRealJopedby Shawn McGrath
1/15/13 5:01pm
Vertical space in code is a must for me. It is easier
to scan through something to find what you are looking for. It helps separate
logical parts as well. But, I guess some people like to work in cluttered messes
because that is what the code ends up looking like.
Which brings me to curly on the next line. For me its
an OCD. I can’t stand looking at something as inconstant as curly on the same
line. They are oddly shaped blocks, next line curly brings everything into
focus and allows very fast scanning of a method.
I totally agree with forcing curly braces even when
not needed. It drives me crazy reading through lazy code. It is right along the
lines with people who name their input parameters a, b, c, d for everything. No
joke, seen this far too many fucking times.
Strong agree on sprintf() vs streams, it makes the
code far more readable.
Reply
Apothecary101 started this
thread
Apothecary101by Shawn McGrath
1/16/13 4:41am
The key is indentation. Indent your code correctly.
Apothecary101Apothecary101
1/16/13 5:06am
And this one too :-S
Reply
Apothecary101 started this
thread
Apothecary101by Shawn McGrath
1/16/13 5:22am
My first comment is missing so I’ll repeat it here.
All that fear to templates is completely irrational, and so it is its supposed
illegibility. Cobol programmers won’t be able to understand “hardcore” C++
code, that doesn’t mean C++ isn’t easy to read. The same way, if you barely
know the rudiments of template metaprogramming, don’t expect to easily
understand highly optimized template code. If you want to see a good use of
templates (and a really beautiful code), take a look at LLVM.
Also, printf-like output is in no way easier to
understand than “<<“-style output. The only reason to use printf-like
style, and it is a STRONG reason, is internationalization. Printf-style is
multi-language friendly and “<<“-style is not.
Regarding “for_each”, “remove_if” and the like, you
seriously need to take a deep dive into functional programming. Most modern
languages incorporate functional-like constructs and there’s a powerful reason
behind that decision. It will make you a much better programmer and also will
help you better understand templates.
Reply
A_P started this thread
A_Pby Shawn McGrath
1/16/13 5:58am
“* Code should be locally coherent and
single-functioned: One function should do exactly one thing. It should be clear
about what it’s doing.
* Local code should explain, or at least hint at the
overall system design.
* Code should be self-documenting. Comments should be
avoided whenever possible. Comments duplicate work when both writing and
reading code. If you need to comment something to make it understandable it
should probably be rewritten.”
Can you imagine how awesome government would be (in
comparison to current forms) if law-makers had to (or were at all encouraged
to) apply these rules to crafting laws?
Hell, just imagine if bureaucratic form creation
(think tax documents) followed these rules!
I would say that these are not so much definitions of
beautiful code as of beautifully transparent systems.
Reply
EdwardAlchemist started this
thread
EdwardAlchemistby Shawn McGrath
1/16/13 8:41am
I enjoyed this post :3
But I find it a bit amazing to see how much the
coding style advocated by the writer differs (as he says himself) from what is
usually teached at universities. In my university´s C++ introductionary course,
we learned to comment to ensure that you always understand what everything is
about, and we were also teached to use white lines and line breaks to make code
less compact, so that it becomes more readable and thus make it less likely for
the programmer to misunderstand a certain part of the program, leading to all
kinds bugs.
While I agree with the author that you should try to
write your program in such a way that it requires as little commentary as
possible (especially since when you get back to a piece of code you haven´t
worked on for 2 years, you might not be able to understand it anymore if it is
not self-explanatory even with comments), I do believe line breaks and white
spaces are in fact a handy way to improve the readability/understandability of
your code.
And if you follow the style of keeping your functions
as short as possible, then even with some more whitespace they should still fit
on your screen, together with part of the code directly above and below them,
me thinks.
Reply
Neal Bailey started this
thread
Neal Baileyby Shawn McGrath
1/16/13 12:39pm
“Code should be self-documenting. Comments should be
avoided whenever possible. Comments duplicate work when both writing and
reading code. If you need to comment something to make it understandable it
should probably be rewritten.”
Couldn’t disagree more. Perhaps this is suitable for
a small team of local developers but when it comes to enterprise systems
development, code that isn’t property commented (articulating summary, params,
return values, etc, etc) is automatically rejected by our quality assurance
people, as it should be.
Considering the varied and extreme range of problems
programmers solve and the algorithms they devise to solve them, excluding
comprehensive member level inline documentation is absurd; at least in any solution
that must be maintainable.
Thank god I have never been on a Sprint with any of
these “programmer” friends of yours.
Reply
HDiedrichs started this
thread
HDiedrichsby Shawn McGrath
1/17/13 3:21pm
I agree with pretty much everything except for the
data parser. While do agree with the initial tools and initial data input
should use one format I don’t agree unwinding and winding of serial data is the
best method for loading data into the final product. On devices like ps3 and
iPad a player wants in fast. I would prefer a system of taking a memory snap
shot as part of the game dev cycle, writing that to file then merely allocating
a large chunk of ram and copying in the snap shot with a LUT fixup for pointers
after the fact. In fact a lot of old C style games I worked on did exactly
this. Very fast load times. Also winding is problematic in serial data systems.
You may not end up disposing of all objects. With a memory snap shot you just
clean out or reuse the allocated buffer and forget about mem returning.
I also agree there is way too much C++, templates and
stl used. Especially in memory critical apps you can’t just rely on stl to be
memory efficient. Would like to see people use more memory pools which can
merely be reused as opposed to winding back up objects. Another area is setting
up data for multiple processors which can be a whole nother topic entirely.
Sounds like Doom 3 would have been cool to work on.
Reply
Fresh_Mentos started this
thread
Fresh_Mentosby Shawn McGrath
1/17/13 5:10pm
In programming languages which get compiled prior to
distribution, vertical spacing is no detriment to the size of the source code,
and what with monitors getting larger, thus allowing more on-screen lines of
code, trying to fit more code on screen at once for the sake of visually
determining the context is less of an issue. (Having to hit page up/down once
or twice does not make code so far removed from it’s neighbors that I can’t
easily discern the context.) Good use of vertical spacing (as in adding blank
lines) can go very far to IMPROVE the readabilty of code.
Putting curly braces on their own lines also boosts
readabilty; matching the beginning and ending of a block of code is much easier
when the braces line up vertically. Putting a brace at the end of a line of
code for the sake of saving a single line is a ridiculously counter-productive
practice.
Reply
jcbbjjttt started this thread
jcbbjjtttby Shawn McGrath
2/08/13 4:50am
I don’t like the statement “Comments should be
avoided whenever possible.” That is a road to disaster. I am all for self
documenting code. But, a comment should be the programmer (not the ‘doc-writer’)
explaining what the function / method *should* do not what it does. This allows
others to help debug and find mistakes. If you write your comment before you
write your code, you’re less likely to write bugs and it allows you to write
good unit tests. I’m not advocating that you should document all your getters
and mutators but anything that does work beyond this should be documented.
Also, if you want to read some really beautiful code,
go read some Haskell. Now *that* is a beautiful language.
Reply
Polantariss started this
thread
Polantarissby Shawn McGrath
2/17/13 9:17am
It’s funny, at least in my experience, a lot of the
things you are complaining about that others have done, while I understand them
completely and agree almost 100%, a lot of schools and classes preach these
things.
For example, the {}s being on their own individual
lines. I hate it. When I was in school, I got points off on projects for not
doing it. I never understood the need for get/set functions either, but they
are preached in classes as well. If you understand the code you’re working with
there’s absolutely no need for get/set, but school requires it and preaches it
like it’s the word of God.
That’s the problem. Beginner Programmers are sent
into the working world with bad information. I’m not sure where teachers are
getting these things, but ninety-nine percent of the time it’s wrong,
inefficient, or just bad to work with. I started programming with some
scripting languages when I was 12, and branched off to major programming
languages as I grew up. Throughout all my years in college I have learned
nothing useful at all, and in fact teachers have tried to break my practices
that I have learned are far more efficient through my own experience and I feel
bad for anyone who learns off of them, I really do.
Reply
Hexanol started this thread
Hexanolby Shawn McGrath
1/14/13 12:41pm
You can actually traverse a vector with less code in
C++11:
for(auto t : vector_of_type)
or if you’re feeling jingly-jangly you can use a
lambda:
std::for_each(vector_of_type.begin();
vector_of_type.end();[&](vector_of_type::T t){\*code*\});
Also; you have a trait common to many self-taught programmers
where you go on about stylistic choices. I wouldn’t want to work with you, and
certainly not under you.
Reply
PrinnyGod started this thread
PrinnyGodby Shawn McGrath
1/14/13 1:03pm
(image 31)
Look around you.
Look around you.
:Sees the article talking about programming and
examples of programming code:
Just look around you. There, now take a closer look.
Have you worked out what we’re looking for? Correct. The answer is “Locomotion.”
Reply
gnat started this thread
gnatby Shawn McGrath
1/14/13 1:34pm
One has to also consider performance when using
layers of abstraction, STL, etc. Which is likely another reason Carmack kept it
more C-style and simple.
Implementations of STL on certain platforms are dirt
slow when you’re doing real time simulations and need to grind the sheer amount
of data involved... the more layers you add, the slower you are.
Reply
derWiskinator started this
thread
derWiskinatorby Shawn McGrath
1/14/13 1:37pm
Love the article, but I disagree a bit on your
opinion of comments. While your example for “GetVal” comments is correct,
generally all operations more complex then that *need* comments. It’s my
opinion that you should design your source before you start typing it, and the
comments help contain that design. This is especially true for things like
complex classes. If you’ve got a complex class like “Model” or ... “World” I
want to see comments that tell me what happens within a Model (versus what
happens in other classes).
Reply
yucomply started this thread
yucomplyby Shawn McGrath
1/14/13 2:09pm
Awesome article, DYAD looks really good too so
congratulations on that aswell. The low bitrate of youtube does not do your
game justice. DYAD is very fast paced and the low bitrate of youtube results in
bad macroblocking. Is there an alternative video service with higher bitrate
you could upload the footage to?
Reply
InquisitiveCoder started this
thread
InquisitiveCoderby Shawn McGrath
1/14/13 2:19pm
Call me spoiled but this is exactly why I can’t
stomache C++...As if managing your own memory wasn’t bad enough, its syntax
will always be a mess and ugly to read.
But to stay on topic: Great article. Definitely a lot
of real programming gems in there. You might want to check out Clean Code, it’s
an entire book dedicated to writing beautiful code and reusable code. There’s a
lot of overlap between id’s practices and what Robert C. Martin and company
suggest. The Kindle version is pretty cheap too.
Reply
hipone started this thread
hiponeby Shawn McGrath
1/14/13 3:38pm
>Using these completely breaks const, and for the
sake of argument
> I prefer to ignore their existence and never use
them in practice.
Then you’re doing it wrong. It’s still being
considered that future implementations of STL algorithms may consider
const-methods are thread-safe and perform extra parallelization over
collections.
Reply
StarTroop started this thread
StarTroopby Shawn McGrath
1/14/13 4:46pm
Yes, I’ve always loved the idTech engine source
codes. idTech 3, specifically, because I haven’t messed with idTech 4’s source
yet, but both engine were extremely easy to modify and understand.
Engines nowadays are too complicated for anybody to
learn anymore, only Unreal 3 comes close without sacrificing quality. That’s
the reason we once had a huge onslaught of free 2 play quake 3 modifications
being turned into standalone games, but now that time has passed.
Though idTech4 never caught on anywhere near as much
as it’s predecessors, I was always amazed at what it could do.
Reply
secretlibrary started this
thread
secretlibraryby Shawn McGrath
1/14/13 5:43pm
Great article. A lot of id’s C++ conventions can be
seen in the design of the D language. You should take a look at it if you haven’t.
Not to actually use it, of course as it will never be supported on the
consoles, but to see how they treated the “state everywhere” problem of
programming in an imperative language. Also, the Google C++ coding conventions
are very good as well if you want to take a look at those.
Reply
Al Roderick started this
thread
Al Roderickby Shawn McGrath
1/14/13 7:04pm
I had two proper programming classes a decade ago,
and I could follow most of what this article was saying. This suggests a few
things: you really don’t forget too easily, and the basic elements of clean
code are so very simple that it’s criminal that working pros don’t follow them.
Reply
CodeLord started this thread
CodeLordby Shawn McGrath
1/14/13 7:10pm
One suggestion: make those pieces of codes plain text
so we can actually copy and paste and talk about it, I don’t think having
taking images of code is the best way of sharing.
C++ 11 way of looping over a for loop is this:
for(auto i: arr){
}
This is as clean as it could get. It makes sense for
you not to like it, because people like to stick to things they used to work
with. But saying that it’s ugly I think is not exactly the truth.
Reply
anoncoward3434 started this
thread
anoncoward3434by Shawn McGrath
1/14/13 7:50pm
Your example for-loop has a typo (“i” for “it”), but
besides that, C++11 is much more elegant than you thought. In C++11 the loop
can be written
for (const myType &element : vector_of_type) {
...
}
with no need for “auto”, “begin”, “end”, or “++” at
all. After all, what does iterating over a vector have to do with incrementing?
:)
Reply
onlysublime started this
thread
onlysublimeby Shawn McGrath
1/14/13 8:00pm
ehh... I appreciate everyone’s style to some degree.
but brevity for brevity’s sake isn’t always better. like the vertical spacing.
i like it spaced out so it’s easier to read. condensing it to just fit more
text on the screen just makes it slower to read. I have my monitor vertical so
I can fit more code in.
and I like comments. yes, there’s such a thing as too
many comments. but the less comments you have, the more you have to read the
code and figure out what it’s going to do. the comments help you find the code
faster.
Reply
ConnorFraser started this
thread
ConnorFraserby Shawn McGrath
1/14/13 9:45pm
Really, the only thing i disagree with is where you
talk about commenting. Commenting never hurts anything.. I think it helps more
often than not. Over commenting is an issue, but I don’t think saying “
Comments should be avoided whenever possible. “ is fair.
Reply
maiko started this thread
maikoby Shawn McGrath
1/14/13 11:01pm
Great job Shawn. While I completely agree with you in
reference to overcommenting code and refusing to omit brackets even if the if
statements and loops allow it (I hate that, it makes the statement rather
unclear like most ‘shortcode’!), some points you make certainly fall under
style.
Either way, I have a grand appreciation for this
article. Thank you very much and I hope you keep them coming :).
Reply
Kenn Villegas started this
thread
Kenn Villegasby Shawn McGrath
1/15/13 12:34am
almost all of the issues addressed here are mitigated
in Cocoa and smalltalk like messages. Sure you cannot teach or expect every new
programmer to know and understand this, but when I look at C++ and to a lesser
extent, Java I find that their version of “beauty” or “elegance” is straight
nasty. If you could see the same structure written with clarity and purity (not
CS Purity) but applicable clarity and purity then you will see why the early
Carmack games were written in Objective C. The circle is complete. So while I
think I can down code my Obj C to C++ I do not think I would enjoy doing it the
other way around.
Reply
LightStriker started this
thread
LightStrikerby Shawn McGrath
1/15/13 9:33am
Little note, a company often create their own version
of STL and base variable type because of their wish for their engine to be
multiplatform. It’s often the case where they create a variable that is used
all over the engine (like vector3) but its definition is changed at
compile-time for a specific platform. For example, in an engine I worked on,
Vector3 isn’t the same thing on 360 vs PS3 (the float precision isn’t the
same), but for the programmer using it, there is not two version of this type.
But whenever they use it, they are guarantied it will works perfectly and as
optimal as possible on all platform supported.
Reply
alsoSprachAlSO started this
thread
alsoSprachAlSOby Shawn McGrath
1/15/13 9:54am
One of my favorite things about coding was the beauty
of the end result. I felt it was as close as I could really get to writing a
novel or painting. The whole process and result felt artful to me. I always
loved, when I finally got it working, going back through it to tidy it up and
make it look nice. Lord, it’s making me want to go read my Master’s Thesis
again just thinking about it. Sometimes I really miss it. I should go buy
myself an FPGA...
Good article!
Reply
mandarinx started this thread
mandarinxby Shawn McGrath
1/15/13 3:15pm
“The first line is completely unnecessary. We learned
all that information from the the function definition. “ That is not
necessarily true. All we learn from the function definition is that it splits
the surface. We do not know that it does this “into a front and back surface”.
Maybe this seems logical to you because of your previous knowledge, but to
someone unfamiliar with this genre of code, it is useful information. The
phrase “the surface itself stays unchanged” is unnecessary to those
understanding “const”.
Reply
Matthew Alford started this
thread
Matthew Alfordby Shawn McGrath
1/15/13 4:44pm
Your example...
ct.setVar(ct.getVar() + n);
While having mut/acc does clutter the code up quite a
bit (when you consider how many ‘public’ variables a class might have), the big
advantage is they create a hook to set a breakpoint to see who is using this
variable, or when it might have changed. VS’s data breakpoint feature serves
this purpose to some degree, but it requires an actual instance and fails when
the data is copied. C++ doesn’t support the syntax, but you could write a
prebuild script to generate the getters and setters for you.
Reply
mangobrain started this
thread
mangobrainby Shawn McGrath
1/15/13 5:10pm
Claiming that this:
vec.erase(std::remove(vec.begin(), vec.end(), val),
vec.end())
... is a good example of the “ridiculousness” of STL
algorithms is highly disingenuous (look it up). That line of code doesn’t just
remove a value from a vector, it removes *all* occurrences of that value,
regardless of where they are. If you’re using this to erase things from vectors
which don’t contain duplicates, you’re doing it wrong. Just find the value and
erase it - do it in a frickin’ for-loop if you want.
Given what that single line of code actually does, I
think it’s pretty concise, and less error-prone than implementing the same
thing yourself.
Reply
amelieauchalet started this
thread
amelieauchaletby Shawn McGrath
1/15/13 6:04pm
Have you ever looked at the Google C++ style guide ?
It’s full of good-sense and it makes for very
readable code.
For instance: name your class member variable in
unix_style_with_train_underscore_, but name methods like ThisIsWhatIDo().
Make copy constructors private when you didn’t
explicitly define one.
Have accessors / mutators (they really prevent bugs!)
but name them “my_variable()”, so it’s immediate that it accesses my_variable_.
This has obviously been honed over millions of C++
LOC and it makes for easy to read code.
Reply
Year Of The Pigeon started
this thread
Year Of The Pigeonby Shawn McGrath
1/15/13 7:43pm
I used to hate the insistence that all fields should
be private and have getters and setters but having done some very heavy
programming in the last couple of years I’ve become a bit of a getter/setter
nazi. I’ve just found myself in several situations were after a while it made
more sense to have a method rather that a field to represent a property or I
needed to perform some operation every time a field is accessed or set and I
fall on my knees pulling my hair and shouting, “I was such a fool! Why didn’t I
listen to my IDE’s suggestions”
Reply
Sorgfelt2 started this thread
Sorgfelt2by Shawn McGrath
1/16/13 10:27am
I appreciate your blog, and appreciate beautiful,
logical programming (although, it often is in the eyes of the beholder), but,
as a programmer concerned about the effects of his work (I got a degree in
physics, but dropped out of graduate school and largely abandoned physics when
I realized that I had no practical choices other than weapons development), how
about giving the user a bit more of that love of beauty, rather than killing
and mayhem? Many of the scientists who developed the atomic bomb regretted what
they had done. Let’s not regret what we are doing to this society.
Reply
carlosht started this thread
carloshtby Shawn McGrath
1/16/13 10:51am
I recommend the book “The Art
of Readable Code” by Dustin Boswell. In the end beatiful code should be
easy to understand. “Smart” code snippets that do something faster or in a
clever way should be second to having code that is fast to understand and
modify.
Reply
huluvu started this thread
huluvuby Shawn McGrath
1/16/13 3:53pm
Well, ok but it’s kind of ugly to write...
if( !counts[SIDE_FRONT] )
...even if it is correct C syntax. This uses an
implicit cast of 0 to FALSE. If counts is an array if integer, it’s better to
use a formally correct boolean expression:
if(counts[SIDE_FRONT] == 0)
This also removes one negation.
Reply
MattTheFat started this
thread
MattTheFatby Shawn McGrath
1/18/13 3:10pm
Excellent article. I agree that the code developed by
someone who started with C tends to be much tighter, and which I equate with
beauty. Templates, while I understand the intent, I think they clutter up the
source to the point where it is more detrimental than good. I think that’s why
they weren’t included in the original Java spec.
Reply
CPTN_Gorillaz started this
thread
CPTN_Gorillazby Shawn McGrath
1/14/13 1:08pm
I started taking a web design class 3 days ago. Right
now we are using notepad to make a simple text based website with some images.
This is like the holy grail of coding, uniform, consistent, and easy to follow.
Nice job id software.
Reply
tramplerofarmies started this
thread
tramplerofarmiesby Shawn McGrath
1/14/13 1:28pm
After writing VHDL for a year, going back to C feels
like a visit to a transsexual brothel.
Reply
StacyD started this thread
StacyDby Shawn McGrath
1/14/13 1:31pm
Don’t Look at some of the newer Android code. DON’T
DO IT! Its still better than most, but OMG.... just take a look at
com.android.settings code and not want to smack someone.
Reply
SilentBob_DN started this
thread
SilentBob_DNby Shawn McGrath
1/14/13 1:32pm
Now i want Phil Fish to analyse Dyad’s code and we
will have enough material for Indie Game: The Movie 2 in no time. Make it
happen.
Reply
Clay Grisetti started this
thread
Clay Grisettiby Shawn McGrath
1/14/13 1:41pm
*Stands up in the middle of seated auditorium and
begins clapping* Well put sir. Just beautiful.
Reply
gunwarriorx started this
thread
gunwarriorxby Shawn McGrath
1/14/13 2:00pm
Loved this article! It was so… positive! The article
was positive, the comments were positive. We all got to appreciate something
cool!
Can this be what all Kotaku articles are like?
Please?
Reply
wakers01 started this thread
wakers01by Shawn McGrath
1/14/13 2:01pm
Interesting read. I feel sorry for the
non-programmers that tried to wade through it though.
I will say that I definitely prefer the Allman style
for indentation. I just think it makes the code a little more readable.
Reply
addMitt started this thread
addMittby Shawn McGrath
1/14/13 2:03pm
I wish they taught stuff like this in college (and
required reading things like “Effective C++” which Carmack linked to) so I didn’t
feel like the worthless programmer that I am with the useless, overpriced
degree that I have.
Reply
Griwes started this thread
Griwesby Shawn McGrath
1/14/13 2:14pm
You do know it’s not called “STL”, right? Common
misconception, but one that is really irritating. http://kera.name/articles/2010/08/it-is-not-called-the-stl-mmkay/
Reply
ThatGuyFromTV started this
thread
ThatGuyFromTVby Shawn McGrath
1/14/13 2:17pm
I’m going to college for CSE and I just finished a
class in Java. I’ve never seen C++ code, but... holy shit, I actually
understood some of the code.
Reply
Enicot started this thread
Enicotby Shawn McGrath
1/14/13 2:35pm
Generally speaking, code is giving a free pass on
being ugly as long as it’s delivered on a “working” status.
Also, I disagree with the whole “no in-out policy”,
if you know what I mean, wiiiink*.
Reply
I’m here mostly for the
chicks. started this thread
I’m here mostly for the chicks.by Shawn McGrath
1/14/13 3:15pm
(image32)
Why don’t you reconst your
flavo-fibes—errrrghhhhhhhhh!
Reply
Protector one started this
thread
Protector oneby Shawn McGrath
1/14/13 4:03pm
What a great article! Definitely stuff here I
heartily disagree with (tabs??), stuff I do agree with (the paragraph on
vertical spacing—YES), and plenty of stuff I didn’t understand, but I’d love to
see more articles like this on Kotaku!
Reply
R W started this thread
R Wby Shawn McGrath
1/14/13 4:56pm
Ha they code like me. I guess when you learn from
assembly to high level, and you know the hardware from the motherboard down to
the gate level, you do it the best way.
Reply
FlippinC started this thread
FlippinCby Shawn McGrath
1/15/13 6:59am
Amused by a story on good coding that has bad HTML
coding - the footnotes don’t work in one direction; they link to ftn.id001
(etc.) but are named ftn.001 etc. Whoops!
Reply
nekomimi_ started this thread
nekomimi_by Shawn McGrath
1/15/13 10:36am
You might want to take a look at this:
And also to the source code of Chromium, which mostly
follows it:
Reply
damager started this thread
damagerby Shawn McGrath
1/15/13 12:59pm
As a reader, I was taken out of the flow in the
Minimal Templates section, simplified C++11 example when you mistyped a
variable using ++i instead of ++it.
Reply
killerbot started this thread
killerbotby Shawn McGrath
1/15/13 4:11pm
in C++11 you can even further simplify your code :
instead of : for (auto it = vector_of_type_begin();
it != vector_of_type_begin.end(); ++it)
just use range based for loops :
for (auto element : vector_of_type_begin)
Reply
MarioAnthony started this
thread
MarioAnthonyby Shawn McGrath
1/15/13 10:40pm
I used to want to code games when I was a kid. Little
did I know this is what it would be like. Much props to people who ‘get’ this.
Reply
hansloken started this thread
hanslokenby Shawn McGrath
1/16/13 4:01am
I find your conclusions very interesting and they
correlate well with modern Agile software development principles (which I won’t
go into :-). Cool to see that some things are true for programmers regardless
of the domain you work in.
Reply
WildWillyWoo started this
thread
WildWillyWooby Shawn McGrath
1/16/13 6:52am
I find it fascinating that an article supposedly
about “beautiful code” should present its code samples in an utterly garish,
and unreadable, color scheme.
Reply
dalssoft1 started this thread
dalssoft1by Shawn McGrath
1/16/13 10:23am
Try “Refactoring” and “Refactoring to Patterns”
Reply
Thomas Roy started this
thread
Thomas Royby Shawn McGrath
1/16/13 10:50am
Yeah, that code is beautiful. I don’t believe in
writing getters and setters proactively when the public access is read/write.
In 25 years of coding I don’t think I’ve ever come across a case where I didn’t
write one and later regretted it.
Reply
The_CH started this thread
The_CHby Shawn McGrath
1/14/13 1:56pm
Except for 1 thing: I despise K&R bracketing. A
curse on the world.
Reply
Weiman started this thread
Weimanby Shawn McGrath
1/15/13 1:31pm
Matching curlies should be in the same column or the
same line. That’s all.
Reply
Very knowledgeable post thank you for sharing Python Online Training
ReplyDeleteWhy look at the fashion industry and the fashion world these days? Well there is a good reason to look at fashion especially if you plan on getting a job in the fashion industry. There are different types of jobs in the fashion industry. If you decide to be a designer you have to be up on the latest trends of celebrities and political people alike. Sensitive eyelash glue
ReplyDeleteWrite more, thats all I have to say. Literally, it seems as though you relied on the video to make your point. You definitely know what youre talking about, why waste your intelligence on just posting videos to your blog when you could be giving us something enlightening to read? Beauty for You online shopping
ReplyDeleteBeauty. What is beauty? A question which has given all the philosophers, observers and wise men sleepless nights trying to provide a definition which suits all sorts. But beauty exists both independently and exclusively contradicting every definition that's been used to define it. Stating the word of Confucius:- "Everything has beauty but not everyone can see it. Al-Hijama Coventry
ReplyDeleteAh,so beautiful and wonderful post!An opportunity to read a fantastic and imaginary blogs.It gives me lots of pleasure and interest.Thanks for sharing.Digital Marketing Training in Chennai
ReplyDeleteDigital Marketing Course in Chennai
MMORPG OYUNLAR
ReplyDeleteİnstagram Takipçi Satın Al
Tiktok Jeton Hilesi
Tiktok jeton hilesi
antalya saç ekimi
ınstagram takipci satın al
instagram takipçi satın al
metin2 pvp serverlar
takipçi
smm panel
ReplyDeleteSmm panel
İs İlanlari
İnstagram takipçi satın al
Hirdavatci Burada
BEYAZESYATEKNİKSERVİSİ.COM.TR
servis
Tiktok Para Hilesi
DriverToolkit 2023 Crack is a powerful software having ability to update automatically all the PC drivers from its large driver data base. Driver Toolkit License Key
ReplyDeleteKaspersky Total Security Crack is a best security app that helps you to protect your multiple devices with multi antivirus protection. Kaspersky Crack
ReplyDeleteThis blog post is incredibly useful and instructive. I want to thank you for sharing this information. I also have a website with a lot of useful information.
ReplyDeletedot-net-full-stack-developer-in-hyderabad
That's all I have to say—just write more. It seems like you mostly relied on the video to get your point across. fullstacktrainingcenter
ReplyDelete