Project Hex Part 6 – A Comment on Comments

  By Shamus   Dec 1, 2010   154 comments

If you remember from last time, I’ve got a bug in my program. It’s supposed to look at the terrain and determine which way is downhill, and it’s coming up with the wrong answer. Sometimes.

I’m going to post a block of code directly from the project. This is the top of the file called Hex.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*-----------------------------------------------------------------------------
 
  Hex.cpp
 
-------------------------------------------------------------------------------
 
  This module deals with the prickly business of turning a stright grid into 
  a hex grid.  It creates the relationships between the points, fightures out
  how they link together, and so on.
 
 
  "Hexes" are built on a normal grid. They are made by connecting points to 
  form rows of interlocking "house" shapes, like so:
 
 
    +--|--+--|--+--|--+--|--+
       |     |     |     |
       |  .  |  .  |  .  |
      / \   / \   / \   / \
     /   \ /   \ /   \ /   \
    |  .  |  .  |  .  |  .  |
    |     |     |     |     |
    +--+--+--+--+--+--+--+--+   
       |     |     |     |
       |  .  |  .  |  .  |
      / \   / \   / \   / \
     /   \ /   \ /   \ /   \
    |  .  |  .  |  .  |  .  |
    |     |     |     |     |
    +--+--+--+--+--+--+--+--+   
       ^ 
       |       
       +---This column gets shifted down.
 
    These are made to look like hexes by taking every other column of points
    and shifting them downward by a half unit. Every vertex connects to three 
    others, EXCEPT for the one floating in the center of the hex. 
 
    There are six different types of points:
    1) Ones that form the tip of a house's roof.
    2) Ones that forn the tip of an inverted house.
    3) Ones at the bottom of a house.
    4) Ones at the bottom of an inverted house.
    5) Ones at the center of a house.
    6) Ones at the center of an inverted house.
 
-----------------------------------------------------------------------------*/

Coders will notice that this is almost fifty lines of nothing but comments. There’s no actual code here. Just notes.

Years ago, I made a habit of leaving comments when working on group projects, but never on personal projects. After all, why write notes in code if I’m the only one who will ever see it?

Of course, I gradually learned how useful comments are, even if you wrote them yourself and you’re the only person who reads them. You can write a block of code, work on it for days, and recall it in perfect detail. But two years later it can look just as strange and foreign as random code blocks written by madmen on the internet.

A lot of the discipline of programming is dedicated not to writing code that simply works, but code that is easy to understand and reuse. The challenge here is managing complexity. The problem is that programs are too large and complex to fit easily within our limited and highly distracted human brains. We need some way to avoid becoming overwhelmed. We can’t make our programs simpler, so the best we can do is to try and make our source code simpler.

Some programmers insist on pure object-oriented design. Or a certain style of naming variables. Or a way of formatting code. Consider…

1
2
3
4
5
if (bFdom) 
{
  float fIntr = fBal * fRate;
  fBal = fBal + fIntr;
}

And compare to:

1
2
3
if (fdom) {
  bal += bal * intr;
}

Same code. Same behavior. But different programmers will insist that one is right and good, which the other is the work of an idiot. Do you indent lines with space or tabs? Does an opening bracket go on a line by itself? How are variables named? How much crap should you cram into a single line of code before you start thinking about breaking it into multiple lines? There are many schools of thought on this sort of stuff and some people take it very seriously. This orthodoxy has grown in complexity over the years as human beings have tried to come up with better ways to avoid drowning in the sea of data that comprises even a mid-size software project.

Just thirty years ago things were much simpler. Most non-academic programs were just report generators. “List out all customers who have not paid their bill in over 90 days and the outstanding balance is more than $100. List the name, address, contact info, and amount due. If they owe more than $1,000 then also print ‘HIGH PRIORITY’ next to their name.” Simple stuff. I actually did a bit of this kind of work back in 1993 or so. Very dull, but very simple. There were a lot of horrible languages back then, but that was okay. Languages didn’t need to be very good because we didn’t need much from them. In fact, software was so simple that it was possible (and occasionally required) to make flowcharts to show the flow of a particular program. I maintain that these were a grotesque waste of time and paper (outside of educational purposes) but there really were companies that kept huge binders of source code and flowcharts for everything they wrote.

Software is now incredibly complex and any halfway-useful consumer program is going to be too immense to even contemplate turning it into a flowchart. Even my project – barely in its infancy – tops 5,000 lines of code. If I lost my mind and wanted to make a flowchart of the thing, I’d need a sheet of paper the size of my living room. A completed modern game would most likely cover a football field.

The bad languages of the past had many flaws. Some were too obtuse. Some were too verbose. Some were just unable to scale up in complexity without the source becoming unmanageable. The weak were culled. The survivors influenced and shaped the next generation of languages.

Over the last decade I’ve noticed a lot of people joining the “The Code is the Documentation” line of thinking. Also known as “self documenting code”. The idea is that the code should explain itself, and comments are a crutch. If you just format your code with enough precision and are anal enough about your variable names, then this will solve all of the problems with managing complexity. Let’s apply this to that code snippet I used above:

1
2
3
4
5
if (FirstDayOfMonth) 
{
  Interest = Balance * InterestRate;
  Balance = Balance + Interest;
}

To me, that makes a bigger difference than anything the coder might do with spaces or tabs or where they stick their damn curly braces. Even a non-coder has a pretty good chance at being able to look at this and tell what it does.

But I disagree with the notion that comments are a crutch. The most important aspect of my code – and the most complex – is the way I’m cutting a grid of squares into a grid of hexes. That is complicated business. I don’t care what you name your variables, the only way to explain that stuff to another programmer (or yourself, in the future) is to write it down. Even if that means drawing diagrams using ASCII art. When I began this project I found myself reviewing my old terrain project. The ASCII diagrams I’d put in that code were invaluable for helping me to understand what was going on. Five minutes of work in 2006 just saved me an hour of confusion here in 2010. (Not to mention how nice it was to have it there during the project, and for everyone else who downloaded the source.)

So many of our struggles with language syntax, formatting, and usage are just so that we can more readily understand code that has already been written. If you’re unhappy with your current programming language then maybe changing languages will solve your problems. But maybe you just need to leave yourself better notes.

As for fixing my bug. It was twofold. The first problem was that the code I’m using to import bitmaps is screwy. If you remember, I’m using a grayscale image for my topography, where brighter = higher. For some reason, the brightness values are getting reduced. There should be 256 distinct levels of brightness, but the values ‘m getting are topping out at just 23. With so few levels, a lot of subtle surface detail is lost and areas where there were supposed to be mild slopes were perfectly flat. I’m not going to bother tracking this down. The problem is with some Windows functionality, and we already knew those were rubbish. This system will be replaced once I start generating the terrain procedurally, so I’ll just ignore it for now.

The second problem was that this:

1
2
3
4
5
6
  static grid_coord   utip[] = { 0,-1,  -1, 1,  1, 1};
  static grid_coord   itip[] = { 0, 1,  -1,-1,  1,-1};
  static grid_coord   ubot[] = { 1, 0,  -1, 0,  0, 1};
  static grid_coord   ibot[] = {-1, 0,  -1, 0,  0,-1};
  static grid_coord   ucen[] = {-1,-1,   0,-1,  1,-1, 1, 0, 0, 1, -1, 0};
  static grid_coord   icen[] = {-1, 1,   0, 1,  1, 1, 1, 0, 0,-1, -1, 0};

Should have been this:

1
2
3
4
5
6
  static grid_coord   utip[] = { 0,-1,  -1, 1,  1, 1};
  static grid_coord   itip[] = { 0, 1,  -1,-1,  1,-1};
  static grid_coord   ubot[] = { 1, 0,  -1, 0,  0, 1};
  static grid_coord   ibot[] = {-1, 0,   1, 0,  0,-1};
  static grid_coord   ucen[] = {-1,-1,   0,-1,  1,-1, 1, 0, 0, 1, -1, 0};
  static grid_coord   icen[] = {-1, 1,   0, 1,  1, 1, 1, 0, 0,-1, -1, 0};

If you don’t see the difference, don’t worry about it. It was a single misplaced minus sign. Took me a few hours to find it, though.

I guess we should at least look at a screenshot after slogging through all of that.

hex_edges15.jpg

A Hundred!202014We've got 154 comments. But one more probably won't hurt.


  1. Mari says:

    But…flowcharts are FUN. Generally useless, but loads and loads of fun. I guess that’s probably not a really compelling reason to use them, huh?

    • Zak McKracken says:

      I actually have made flowcharts for most programming stuff I did (which is definitely in the “small” category).
      I found it helpful for myself as a sort of map to the code, and for anyone else to understand the algorithm and the implementation without having to read the complete code. I didn’t go through every line though, rather made one or two blocks for each routine in the code, so you understand where they are called and what for and so on.

      These days I’m mostly using other people’s (much more complex) code, and everytime I’m asking about how some thing is being handled or what a parameter does and someone tells me to just look it up in the code, it makes me want to explode. Happily that’s not so often, but it does happen.

      • Trix says:

        Even if the program is too complex for a complete flowchart, I’ve found having a chart of the top level stuff to be quite helpful as well, particularly if I’m sorting through a bunch of existing functions.

    • Maldeus says:

      I would like to see a football-field sized flowchart of a modern game.

  2. Duffy says:

    I agree, and getting into the habit of using our code as documentation also tends to improve our coding. If I notice a section of code that is doing something in a let’s say a “roundabout” manner it usually stands out with redundant variable names, confusing formulas, or extraneous ifs/loops that do not match or flow with the rest of the “documented code”.

    I tend to use general comments to clarify what sections of code should be doing and to remind myself of the general work flow. This helps avoid glut in heavily used functions and insures anyone who works on it after me can at least follow my insanity.

  3. I don’t think anybody considers comments like your documentation as unnecessary. It’s the inline stuff, like if you put “// add interest to the balance” at the end of the addition line. That’s obvious from the code, and the comment isn’t necessary. (Though it would have been with your first code snippet.)

  4. elias says:

    Should be adding Interest to Balance rather than InterestRate… not that it matters. : )

  5. Nathon says:

    My philosophy on comments is that they should explain the why instead of the what or the how. Example:

    a = 3 + b; // Add 3 to b and store in a.
    Wow, that was terrible. It told us nothing the code didn’t.

    flibber += frobnicate(NUM_WIDGETS); // Flibbers need to be frobnicated in order to function properly. See manual page 3258.
    Sensible, particularly in light of a pointer to the outside world, but obtuse.

    Your example above is what I would call perfect. It explains what the goal of the code that follows it is. If the code doesn’t work properly, someone (future you) can look at the comments to find out what it was supposed to be doing and fix it.

    • Heron says:

      +1

      I was going to say the same thing, this is precisely my view on self-documenting code.

      • larryboy114 says:

        Agreed, I comment the hell out of my code and use long (RE: descriptive) variable names. Everyone I work with thinks I’m daft, but I can decipher my own code from 2 years ago (usually) and a lot of them can’t figure out what they did last week.

        • Simon Buchan says:

          Believe it or not, the idea of “self-documenting code” is that “comment[ing] the hell out of [it]” is a *bad* thing.

          The thinking is that comments have a lot of non-obvious costs – writing them in the first place, of course, but also:
          They take time to read that could have been spent reading the actual behavior.
          They can separate code that is interrelated, making it harder to see their connection (at both method and line level).
          When the behavior changes, the comments must be updated as well.
          When comments disagree with code, it is not obvious whether the comment is out of date, the code did not correctly implement the comment or the comment was simply wrong in the first place.

          After seeing a lot of heavily commented code that was almost incomprehensible, and a lot of not at all commented code that was almost incomprehensible, I’m of the opinion that *documentation*, not commenting, is important: describe architectural and implementation *decisions*, not behavior. If I’m reading a parser, I should already have some idea how a parser works – it’s not the job of a source file to tell me what a SyntaxNode is (other than maybe a one line “Base class of nodes in the AST”). It should describe what this implementation of SyntaxNode does, for example: what class creates these, how do forward references work, how using code is expected to traverse the tree, and so on.

          • MichaelG says:

            Long comments do tend to rot and not keep pace with the code. That’s why I usually write short “about to do X” kinds of comments. Those are usually the way I sketch out the code in the first place, and they are disposable. When I rewrite the code, there will be a new set of those outline comments anyway.

  6. Brett says:

    Shouldn’t

    if (FirstDayOfMonth)
    {
    Interest = Balance * InterestRate;
    Balance = Balance + InterestRate;
    }

    be

    if (FirstDayOfMonth)
    {
    Interest = Balance * InterestRate;
    Balance = Balance + Interest;
    }

    ?

  7. Ingvar says:

    I think the closest I’ve managed to approach “More code than comment” was for a piece of code implementing getpwent(3) for an alternative (potentially better-performing way) of doing “username, userid, groupid, GECOS and password mapping” than the old unix standby of a flat file, each line representing a record, with delimited fields.

    Of course, the replacement was “a directory hierarchy, full of small files, each file a single line, with delimited fields”, but BOY was lookups faster when you were looking at 20k+ records…

  8. Aquin says:

    Yeah, I put a paragraph before each function to explain what it does and why. And any complex bit of code I explain what it does there too. AND writing code so clearly also helps.

    I basically try to document the code as a tutorial for someone who wants to learn what I did. Because that will be me… six months from now. :P

  9. Skip says:

    After doing software development for the last 25 years or so, my views on comments have definitely changed over the years. Currently I’d say they are:

    1. File header comments explaining general design parameters, goals, references, etc., are great.

    2. Function headers, explaining constraints, side effects, etc., are great.

    3. Comments inside of functions are in general not so great. If you write a piece of code, and the way it works is tricky, there better be a darn good reason, and you would be much better off spending the time to rewrite it in a more understandable fashion. Especially if the goal was to just save a few clock cycles that the compiler’s optimangler probably was saving for you anyways.

    Now, those rules aren’t absolute – comments inside of functions noting limitations, or functionality that needs to be added later, but isn’t currently supported are useful.

    • Abnaxis says:

      I would like to repectfully disagree with item #3 here.

      I think it’s lazy and just a bad idea to make code less functional just to make it more readable. When I shop around today, I don’t see any processors faster than the one I bought six years ago, they just keep adding cores. Eventually, the leaders are going to be the ones who actually utilize clock cycles well, and not always the ones who have streamlined their labor force. We’re just not there yet :)

      • Simon Buchan says:

        Interactive performance (how long before this program does what I asked it) is what most people think of when they say a program is “slow” – this is completely dominated by memory and disk speed. Not to say it’s not the programmer’s fault, but you want to be able to re-arrange the way your code works to not need some memory or whatever to fix those problems, and having simple, readable code is far more useful than code that uses 4% less CPU cycles (saving 10 microseconds in a 2.3 second operation).

        • BritishDan says:

          As a professional programmer, I have to disagree with the statement “this is completely dominated by memory and disk speed”.

          This is only true if all your program is doing is loading new chunks of data (which frankly is poor code design in it’s own right). Think for a moment about how some people struggle with long draw distances in Minecraft, that certainly isn’t because it’s reading all your blocks from disk. Or performance issues in Dwarf Fortress aren’t due to any super data reads.

          In personal experience, I’d say that basic optimization is absolutely essential for programs that are trying to render graphical scenes, and even more if their rendering is largely based on human input. Video games are, by nature, very complex state machines with extremely complex calculations going on inside of them all the time. I’d say that 50% of all the innovation in game coding over the last 15 years has been around figuring out how to optimize certain standard functions (choose what to draw in an FPS, path-finding, basic AI-goal processing) to make those calculations usable in an environment where a player is expecting near instant feedback.

          (though MichaelG is right and spending hours optimizing code that you may chuck out later is a morale killer)

      • MichaelG says:

        Remember that premature optimization is deadly. You spend a lot of time tweaking code that just doesn’t matter, since it’s not time critical.

        For best results, first get the architecture right. All the code should be as clear as you can make it, not as fast as you can make it. Then if you need more speed, go back and optimize. You’ll be surprised at how few optimizations in your code really matter.

        • Blake says:

          Can be less true in games, but is generally pretty accurate.
          When all things you do are time critical (you have 33ms to do everything you want KGO!) you need to make every decision carefully with regards to what functions can be easily broken up later and what needs to be set up with optimisation in mind from the start.

          This is more important on older/portable consoles than the big ones these days but still needs to be considered.

          Having said that it still as you said comes down to focusing on the architecture rather than the innards of any one function.
          When profiling is done slow functions can be fixed up as long as the program is set up correctly.

        • MrWhales says:

          what you say here(which i 100% agree with) reminds me of advice given to beginning writers. Write everything you are thinking, then later on go back and make it flow better and what-have-you. So, get the program to turn on, before you try to make it go quick. 1 legged horses dont run too quick anyways.

          • Aldowyn says:

            Yeah, I do this with a lot of things, not just programming. Just get it to work, jury-rig it if you have to, THEN make it look all pretty and work exactly the way you want it to.

            • MrWhales says:

              Exactly. Works for everything! including duct tape.

            • Chris says:

              …and unfortunately that’s also the approach many coders use towards commenting and general documentation, also:

              “I’ll get the program to run, and then I’ll go back and add comments and finish the documentation.”

              And because time runs out, or the NEXT hot project comes crowding in, or simply because programmers get bored doing doco, it never gets done.

  10. Factoid says:

    A quick aside from the variable naming conversation…I just wanted to throw in that a line from one of your previous Hex articles really resonated with me.

    Debug the code you wrote. Not the code you think you wrote.

    Those are words to live by in my opinion. I’m trying to come up with a non-programming analogy to match it and haven’t come up with anything quite as pithy. I’m not sure if that’s an original shamus quote, or just some gem of programming wisdom passed down through the ages, but it was very apt and I find myself applying that thought to problems I have (or think I have)

    • Chargone says:

      anyone who’s ever written Anything then attempted to check it for spelling without using spellchecking software has had this problem at some point. (assuming you’re referring to what i think you’re referring to without going back and looking at the article)

  11. FatPope says:

    “any halfway-useful consumer program is going to be too immense to even contemplate turning it into a flowchart”

    I can’t exactly agree with you there. My entire job in telecoms was programming through flowcharts. We used a combined UML-IDE program, so you add code directly to the flowchart diagram. It was a monumentally large codebase with thousands upon thousands of people working on the same project – I can’t imagine anything even being remotely comprehensible without these diagrams!

    • Blake says:

      He said it’s too large to turn into a flow chart, not too large to create via crazy flow chart.

      It sounds like an interesting way to work but as long as a project is strict about what controls what data and how that’s communicated to other parts it’d certainly be possible to work with without the flow chart.

      Imagine however trying to plan that flowchart before writing code or even worse, writing it in code then trying to create a flow chart out of it.

      • FatPope says:

        Well most of the flow chart was created before any code was written.

        Unlike a paper flow-chart of this size though this was actually usable. Each task on the flow chart could be expanded into another flow chart created to represent created to split up that task. So you had many, many layers of flow charts within flow charts.

        Really it’s just abstraction layers if you think about it

  12. Kdansky says:

    Yeah, good documentation is so important. Not the things that tell me what the next line does. But the kind that tells me what a class or a function does, or why the next sixty lines are actually necessary. To give an example from ten minutes ago: I just wrote a hundred lines that bother with the exceptional case that someone managed to flip the direction of a line. Now, for comments, I don’t actually need to comment that much, since all is extremely straight-forward: Run through the line, check in which order we find the important points, then reverse order if necessary. But will I remember in half a year why I added those lines? And do my colleagues know? Definitely no.

    As for variable names: I will come to your house and break your kneecaps if you use names like “fBalIntS” or “xPtrCst”.

    And on the topic of Hungarian notation, most people do it completely WRONG.
    http://www.joelonsoftware.com/articles/Wrong.html
    This is how it’s done right! A must read for programmers.

    • Jarenth says:

      I have never heard the words ‘Hungarian notation’ before, which should clue you in on the kind of programmer I am (hint: not the well-payed professional kind), but that was still an interesting read. Thanks for the link.

    • Blake says:

      “pretty soon you forget all about that and then you can start obsessing about something else irrelevant to making money like replacing one kind of string class with another kind of string class” – I lol’d.

      • BlackBloc says:

        Our product’s C/C++ code base is over 15 years old, so I had the sheer privilege of replacing naked char pointers (and the occasional naked void pointers) with STL’s string class. Ah, memories.

  13. StranaMente says:

    Well, being a lawyer, all this tech talk is incomprehensible to me. But as an artist I noticed that the shadows are still black.
    Black shadows are bad. Really bad. Even with transparency on.
    Set them to a dark brown, or blue, you’ll get a nice improvement.

  14. Atle says:

    Personally I like (as if anyone cares):

    // General explanations
    if (fdom) bal+=bal*intr; // Special notices

    And I don’t like all the extra white space people fill the page with. I use white space to enhance structure in the code. If there are lots of air every where, that becomes very difficult, and not in my opinion not very readable.

    Also I use long_telling_variable_names for important variables, and short variables as local temporary variables.

  15. Zak McKracken says:

    On long variable names:
    OK, so I’m an engineer, and I’m used to reading formulae, so I don’t really require variables that look like words.
    I also find long names too bulky often, at least if you have a program that’s actually made to compute stuff and uses more complex expressions than “a=b+c”. You can always break up a big formulae into smaller ones but that means even more variable names, and usually I’ve already got loads of them. So usually, I put a variable list at the top of each routine, like decent scientific literature does (plus a short explanation what the variable actually means in the current context), and then abbreviate as abbreviate can. Muuuch easier to read code if expressions fit within one line.

    For example, you wouldn’t want to find this in a program:
    fstagnationpressure = freferencepressure + (fdensity / 2) * freferencevelocity^2
    if you could just write:
    P_T = P_0 + rho/2 * V_0^2
    which will be recognizeable to anyone who knows their Bernoulli (and can just be copy/pasted into the OOo formula editor ;)

    • Duffy says:

      I kind of disagree.

      If your code is ever only checked by people that should know the formulas or used in such a way that the formulas are displayed/manipulated, then the shorthand route sounds fine.

      But as a general coder I often have to implement formulas I do not have memorized or sometimes do not entirely understand aside from that they arrive at a desired conclusion. Requiring a reference key that may have many similar variables to other formulas in the application only creates more confusion. When you have fully stated formulas it’s easier to read them at a glance.

      I personally think the habit of shorthand variables in science is due to traditionally having to manipulate the formulas by hand.

      • Leyic says:

        You’ve touched on another important part about writing documentation: Know your audience. People don’t like reading comments that don’t explain anything new (to them), so if your intended audience should already understand a concept you’re using, you only need to point out that you’re using it without explaining what it is (i.e. no sense in explaining elementary physics to professional physicists). Seeing as academic and scientific projects usually involve accompanying papers complete with nomenclature, it can make sense to reuse the nomenclature in the code. If your project has no such paper, then you need to ask what conventions your readers will be most familiar with.

        That said, mathematical shorthand notations really are useful for comprehending sets of equations, especially where tensors are involved (i.e. Navier-Stokes).

    • Aelyn says:

      I tend to take a middle ground here. I like the defining of variable names early, but I prefer something more readable. I’d probably use fstagpress, frefpress, fdensity, and frefvel for instance.

      • Aldowyn says:

        Something long enough and close enough to the original to be recognizable but short enough that it’s not ridiculously bulky.

        Probably where I stand too. It would help if the names of variables weren’t already given. (Taking a college-level Java course at my high school)

    • decius says:

      *Smack*
      What are you doing, saying ‘rho’ when you mean ‘density’!? I can understand not wanting to use characters not on your keyboard, but using ‘rho’ means that you think “rho” when you need to think “density”.

      Or are you of the opinion that density changes in liquid systems tend to be small enough to be ignored, and treat them as constants?

      A variable list at the top of a program that used (real) physics extensively should also include a way to read the notation actually used; P_0 is reference pressure, maps to “P, subscript 0,; avgthemneutflux is average thermal neutron flux, maps to “Bar sigma, subscript nt”.

  16. TechDan says:

    Long time reader, first time commenter. I just want to say, if you ever think that your chosen language is annoying or tough, please have a thought for us poor engineers that are required to be able to do all of our necessary coding in MATLAB. I hate MATLAB so much.

    Also, really enjoying the series. I’ve been trying to improve my commenting lately as well, especially as I’ve been given more and more projects that require to run mass simulations of various aerodynamic problems.

    • Leyic says:

      Generally speaking, MATLAB is great for prototyping heavily numerical code and a few other very specific tasks, but terrible at pretty much everything else, so I kind of sympathize with you. “Hating” MATLAB might be a bit much though, since it sounds like it’s the wrong tool for your job. Asking someone to do all their coding in MATLAB is like asking someone to hammer a nail but then giving them a screwdriver.

      • TechDan says:

        You pretty much hit the nail on the head. I’m still a student, but any coding we are required to do is required in MATLAB, because it is, for whatever reason, the “go-to” computing tool at Georgia Tech. At least for those of us in the College of Engineering.

        It can be highly useful for certain things, but it is also horribly unwieldy for a lot of what I have to do.

    • Trix says:

      MATLAB has some amazing capability. You just have to know how to talk to it :)

      Did a program in MATLAB for analyzing satellite links back when I was in school. Comparable to C++ in some ways, but you can tell it was made by/for engineers.

  17. Deoxy says:

    Variable names: CamelHump. Underscores are really annoying, but giving no indication of which parts mean what can be annoying, too.

    Of course, that’s also assuming you are using a caseless language. Case sensitivity of names is among the dumbest things I think I have ever seen in my life. Really, you’re going to use AVariableName and AvariableName to mean different things? What the crap is wrong with you?!?!!??! Debugging any errors or other people understanding the code will both suffer TREMENDOUSLY from that. (That *nix systems do that with files names also strikes me as really dumb.)

    Comments: yes, “a = b + c // add b and c to get a” is REALLY dumb. However, if the variable names are not sufficiently descriptive, it CAN occasionally be useful to do something like “a = b + c // add taxes and interest to get total cost”. I’ve found this to be very useful when modifying code where the original coder used crappy names.

    Indentation: tabs? Spaces? I don’t really care (other than that tabs tend to be a bit longer than I would prefer) so long as you use the SAME level of indentation for stuff at the same level. (Curly brace, if you are using such an annoying language, on the same line or the next is pretty much the same – I don’t really care, just be consistent.)
    Edit: duh, leading spaces dropped… using underscores instead
    If A then
    __If B then
    ____If C then
    __do something
    __end if
    __end if
    __do something else
    end if

    Yeah, that’s BAD. Especially if you are nested 12+ deep. Keeping track of how many levels deep you are can be stupidly easy (consistent indention) or maddeningly difficult (inconsistent indention) – this does not seem like a hard choice to me…

    • Robyrt says:

      For added hilarity, have 1/2 your coders use tabs and 1/2 use spaces. Then try to decipher the code years later when the tab length has changed!

      • Heron says:

        My first three months on my current team we were all using arbitrarily modified Eclipse autoformatting settings. Every other code review included the comment “please fix your autoformatting settings”.

        We distributed a common settings file, which fixed the problem for a time, but then we had to upgrade our OSes and things fell apart.

        It also doesn’t help that Eclipse does this stuff per-workspace and has no way to set global defaults for new workspaces.

    • MarkHawk says:

      your endifs are indented wrongly. I can only assume you meant the following:

      If A then
      __If B then
      ____If C then
      ______do something
      ____end if
      __end if
      __do something else
      end if

      Also, When nesting statements, I like to comment the closing braces/statements. eg:

      If A then
      __If B then
      ____If C then
      ______do something
      ____end if //C
      __end if //B
      __do something else
      end if //A

    • Blake says:

      “I’ve found this to be very useful when modifying code where the original coder used crappy names”
      At those times I rename the other persons variables.

      Tabs for indenting, spaces for aligning. That way people can have any indent they damn well please.

      That way if someone with 4-spaced tabs writes
      if hungry
      {
      —>int.amountOfFood..=_CountFood();
      —>int.hungriness……..=_GetHungriness();
      {

      Someone with 2 spaced tabs sees
      if hungry
      {
      ->int_amountOfFood..=.CountFood();
      ->int_hungriness……..=.GetHungriness();
      {

      Everybody wins.

      EDIT: HTML is making my tabs and spaces all crazy like.

    • Sauron says:

      Variable names: ObjectsAreCapitalised (as are MethodsThatReturnObjects). primitivesAreLowercased (as are methodsThatReturnPrimitives) (picked this one up from a former employer but, damn, it makes things easier to follow by far). If you’re not using object-orientedness, this means everythingShouldBeLowercased. Case-sensitivity is a good thing for a number of reasons:
      1) It enforces consistency in a sane fashion (unlike, say, whitespace dependence)
      2) Because of the naming scheme, there is no reason I shouldn’t use both Object and object if they both make sense in context,

      Comments: Code should be self-documenting, but anything that isn’t should be commented. Comments should always explain the why and never the what. If you find yourself breaking either rule, _fix_it_. If you come across a programmer using stupid names, vim and sed have some tools that can help you.

      Indentation: Tabs to indent, spaces to align. The important thing to remember tabs is that any decent editor can set the length of tabs (I suggest you find out how in your editor of choice, if you have a problem with the length of yours.) The other important thing is that, in most languages, if you are indenting enough that the standard 8-char length of tabs is getting in the way, you should seriously stop and consider whether there is a better way to do it.

      Curly braces (which are much better for block-identification than whitespace or silly constructions like “if blah then blah / endif” or whatever you) should go on the next line for function declarations and on the same line elsewise. Function declarations should always stand out, but otherwise you should be able to fit more lines of code on the screen at a time. More code in context makes it easier to work with more often than not.

      And, finally, consistency is more important than anything else, but, dear god, if you’re ever nested 12+ deep, you *really* need to reconsider how you’re doing things. That is ripe for refactoring.

  18. LintMan says:

    Flowcharts can still be quite useful to help clarify a subsection of code – a complex process or decision, especially if it has to be explained to or approved by non-programmers. Flowcharts don’t have to show every branch and operation as individual boxes and can be quite high level, capturing hundred or thousands of lines of code in a single box.

    Just yesterday, I was asked to do a flowchart because the 4 slides of pseudocode I wrote were deemed a too heavy for customer consumption. The resulting flowchart fit on one slide and is immediately more understandable (albeit less detailed).

  19. Jarenth says:

    I will add to this growing comment wall a little anecdote from a programming class I took a few years back. The programning work was done in groups of two, and we occasionally had to show and explain the work to our teacher. This hit a bit of a snag when my partner was trying to explain something solo (I was out that day), and failed to explain certain parts of the program because she didn’t understand what was going on in the code. Because -I- had named all my variables in that section things like ‘w00t’ and ‘w000t’ and ‘finally!’, with exactly zero explanation.

    Hey, it made sense to me at the time. I was trying to solve some difficult problem, I finally got it, I was happy. I just didn’t stop to think that it wouldn’t exactly make sense to anyone else.

    Aspiring programmers reading this: don’t do this sort of thing.

    • Sekundaari says:

      Now I wish to see a language in which w00t means int, w000t means while and finally! means return. Or something.

    • Kdansky says:

      I have given names such as ASDKLJHKASDJHF to functions, and then just copy-pasted them. Or ThisIsAnOhSOAmusingVariableName. Silly youth.

      • Mari says:

        In one of my classes we had an assignment to write a simple program using only variable names like that which had nothing to do with anything. It was early in the semester and we did it and moved on. Then right before semester exams the prof pulled the stupid proggys back out and demanded that we explain the code. Object lesson learned.

  20. guy says:

    “If you don’t see the difference, don’t worry about it. It was a single misplaced minus sign. Took me a few hours to find it, though.”

    And this is why programmers get paid so much money and can’t predict how long things take to make, non-technical people!

    Sorry, venting.

    • FatPope says:

      Well, programmers in some countries make lots of money. In the US a starting salary can be $70k whereas here in europe it’s more like $35k (with a higher cost of living)

    • Aldowyn says:

      We might be able to guess how long it takes us to make the code structure, but, as it’s nearly impossible to not mess anything up the first time (especially if you’re not quite sure what you’re doing, like me), it gets really hard to figure out where you went wrong, and there’s no way to tell how you went wrong.

      I’ve also noticed it’s a lot harder to check your own than for someone else to check it.

  21. Christopher M says:

    My main beef is counters and temporary variables that you just can’t come up with a meaningful name for, but you know that if you don’t you’re going to look at your code some days later and wonder, “What’s ‘i’, what’s ‘xpan’, and why are they in this particular order here?”

    • guy says:

      Counters are supposed to use names like i, j, k, etc. and never be used outside the loop. If you intend to use them outside the loop, give them a real name.

      • Aelyn says:

        Exactly. And if you find a variable such named *Temp in my code, you are free to use it at will. If changing the value later in the procedure/function breaks something, it wasn’t a temp variable.

      • Valaqil says:

        To inform others, even if you already know:

        Though it may not be exactly fact, it’s commonly stated that the letters i, j, k and are counting variables because of FORTRAN. In that language, those variables are automatically integers, so you usually didn’t have to guess at their type. They made for easy and obvious counters for loops.

    • Duffy says:

      In the .NET world foreach loops have been replacing the majority of counter based scenarios, though of course there are always exceptions.

  22. toasty_mow says:

    As much as I hate programming, I really do enjoy you talking about it. You just have a great ability to explain things and talk about things. And my brief foray into programming did teach me that yes, in really big programs you will need some method of organizations.

  23. IncredibleGeek says:

    I’m a grader for a computer programming class in my school, and one of the students I grade for has a habit of leaving paragraphs worth of comments on everything. Example:

    //stuff you should read or you won’t understand the dfjife ekf sof
    //ekfisl apwor coo wki ekfi wlao feoa; stime alltje the fie skie
    //qoti sifi ekfisl apwor coo wki ekfi, wlao feoa stime alltje the
    //skie alfo qoti sifi ekfisl apwor coo; wki ekfi wlao feoa stime
    //the fie skie alfo qoti sifisdlf gie skfie vnn mog eowo.
    // Also, this foek fie gie, fjfw fijw fof. Wotk skjt eokfl stime //alltje the fie skie alfo qoti sifisdlf gie skfie vnn mog eowo.
    //Akfi ejg witj lsi take the sqaure of this side of the grid and all.
    //Four score and seven years ago, a day that will live in infamy; for a
    //priori knowledge. All the world’s a stage; I am the greatest man that
    //ever lived. A penny saved is a penny earned, so if you want something
    //you have to take it. Luke, I am your father, and I brought you into
    //this world and I can take you out of it; reports of my death
    //have been greatly exaggerated.
    // We will Bury you; tear down that wall. Ask not what your
    //country can do for you, but what you can do for your country.
    //Beer is proof that God loves us, and wants us to be happy.
    //I hate to see her leave but I love to watch her go.
    // Also, be sure to invert this if you need the inverse function.

    int getCounts()
    {
    return counts;
    }

    This does not help readability of your code. Please practice safe commenting.

    • Atle says:

      That’s the problem of this “Clean code” idea in combination with doxygen and similar. It can become difficult to find the code amongst all the comments.

      But there’s no silver bullet here, I think.

    • Slothful says:

      As a student in a programming class, the only thing I use comments for is making my programs pretty when the teacher grades them.

      I’ve never actually run into situations where my programs got intensely complicated enough to need heavy commenting.

  24. krellen says:

    Comments work even outside programming. I used to have horrible times taking off work because whenever I did, something would come up the rest of my team couldn’t deal with or dealt with incorrectly and/or inefficiently, thus leaving me messes to clean up when I got back to work. Before I took my most recent break, however, I documented a “FAQ” for common problems with simple solutions, and this time when I got back there was not a giant backlog of problems needing solution. So huzzah for documentation.

  25. X2-Eliah says:

    I am not so sure about the splitting everything in OO-snippets..

    I mean, if you need to make a random method, then a method relying on that, then a method to do more stuff, isn’t it better to use a single line of code with 4/5 variables added/multiplied, with a /* explanation of result */ two-liner?

    • Duffy says:

      For quick and easy OO, if you find yourself using the same exact algorithm over and over break it out into a function. I assume that would be the only reason for such a simple function. It also clarifies what is exactly occurring every single time you call it.

      • X2-Eliah says:

        Yeah, but when that is just a single occurrence in the entire program/section, it is pretty much useless to create a swarm of methods just to accomodate a single mathematical expression – There’s the thing, when ‘readability’ (which can be commented in this case sufficiently) produces useless code.

        Besides, If I have to backtrack through 3 layers of method calls, I can’t honestly call that readable.

        • Blake says:

          If it’s that simple then the function name should describe what it does.

          Vector perpendicular = DotProduct(off,dir)

          is better than

          // Take the cross product of offset and direction to get perpendicular line
          Vector perpendicular = Vector(off.Y*dir.Z-off.Z*dir.Y, off.Z*dir.X*off.X*dir.Z, off.X*dir.Y-off.Y*dir.Z)

          because the first is easier to read and the second one has a bug in it and you probably didn’t notice.
          If everything is using the one Cross() function then if there’s a bug everything will be failing and it’ll be fixed, and once it’s fixed once it’s fixed everywhere.

          If everywhere is rewriting the math then you have to trust they’re doing it right and when they aren’t it becomes a massive pain to track down and fix.

        • Blake says:

          My thoughts on comments/standards, if something has non-local scope then people should know so they don’t go messing with it willy-nilly.
          m_,s_,g_ are friends here (well g_ pretends to be anyway).

          The rest of the hungarian notation is just a case of making variables names describe them, to my eyes both bExited and hasExited both look fine, exited on it’s own could potentially be a count of times it’s been exited but it’s probably readable on its own.
          fDistToCamera and distToCamera are both fine, fDist,dist,fD,d probably not so much.

          Most code should be readable, any time Magic™ is being done or when code has to go down a certain path for Interesting™ reasons, some comments just above the crazy code would save people deleting it later causing your awesome/terrible fix to break some time in the future.

          Comments in headers for public functions can speed things up but they should be saying what a function is meant to do not how it’s doing it, where comments in the .cpp should be focused on what/why you’re doing things.

          And now some heresy, macros can make code more readable.
          If there’s too many declared in public places it can be painful, but for things required in your system they can speed up both writing and reading.
          For instance wrapping c++ classes to make them exposed in lua, if it’s a big part of your program then everyone working on it should learn what your LUA_EXPOSE macro does and use it as it’ll make everyones lives easier.
          Besides those sorts of cases I don’t mind them in cpp files with no external access when they dramatically shorten code.
          For instance if you want to print a bunch of flags out then typing
          #define PRINT_FLAG(v,flagName) if(v&flagName!=0){PRINT(#flagName);}
          PRINT_FLAG(state, CONNECTED);
          PRINT_FLAG(state, CHAT_ENABLED);
          PRINT_FLAG(state, NEWB_DETECTED);
          #undef PRINT_FLAG

          can be much nicer than
          if (state&CONNECTED != 0)
          {
          {PRINT(“CONNECTED”);
          }
          if (state&CHAT_ENABLED!= 0)
          {
          PRINT(“CHAT_ENABLED”);
          }
          if (state&NEWB_DETECTED!= 0)
          {
          PRINT(“NEWB_DETECTED”);
          }

          Especially as you get more and more flags.

          • Atle says:

            Love macros.

            Also I think:
            if (state&CONNECTED != 0) PRINT(“CONNECTED”);
            if (state&CHAT_ENABLED!= 0) PRINT(“CHAT_ENABLED”);
            if (state&NEWB_DETECTED!= 0) PRINT(“NEWB_DETECTED”);

            is much more readable than with all the extra line feeds and brackets.

          • Duffy says:

            I’ll admit that I’m on the younger side of coding, but whats the point of macros? I’ve never used them, never seen them in any classes I took, and they seem to behave almost exactly like functions. They also seem to be defined in headers mainly? If so doesn’t this negate the concept of self documenting code when you have to go reference another file for little bits of flow logic? Do macros have issues with error checking or exception handling?

            What’s the difference between a function/method and a macro or is this a language specific thing?

            • Alan De Smet says:

              Assumption: we’re talking about C-style macros: simple(ish) textual replacement. They’re only natively available in some languages.

              The key is that the macro is direct textual replacement. They can do clever things, like taking a single argument and interpreting it as both a function call to make and a string to use in a log message. ASSERT is frequently rigged up to do this, with something like:

              #define ASSERT(a)
              if( ! a ) {
              fprintf(stderr, “ASSERT(” #a “) failed at line ” __LINE__ ” in ” __FILE__ “n”);
              exit(1);
              }

              So when I write:

              // This is file foo.c, and is line 10
              ASSERT( validate_database() );
              ASSERT( validate_internal_data_structures() );

              what the compiler actually sees is:

              // This is file foo.c, and is line 10
              if( ! validate_database() ) {
              fprintf(stderr, “ASSERT(validate_database()) failed at line 11 in foo.cn”);
              exit(1);
              }
              if( ! validate_internal_data_structures() ) {
              fprintf(stderr, “ASSERT(validate_internal_data_structures()) failed at line 12 in foo.cn”);
              exit(1);
              }

              The macro can even do things like cause the “caller” to return, useful if you have a long stream of function calls, but if any fail you want to return an error code. (You’d typically handle this case with an exception in languages that support them, but C doesn’t.)

              Generally speaking you don’t need macros, but for those rare cases in which you do, they’re a great tool.

            • BlackBloc says:

              Macros are evil things from a bygone era. They are used to answer multiple different problems, each and every one of which is better solved by another, newer concept. There is no reason to use a macro when instead you could use inline functions or template programming, for instance, to do the exact same thing. The one reason why some programmers still use macros is 1) they’re steeped in C coding practices and/or 2) macros are so powerful they can do pretty much anything if you put your mind to it, whereas inline functions and template programming are specialized tools that each only resolve part of the issues people use macros for, and some people would rather use a hammer for every job than use something a bit more… surgical.

              C++ is not C with two +s added.

              • Alan De Smet says:

                “each and every one of which is better solved by another, newer concept.”

                I am eager to learn how the following are solved by a newer concept:

                Automatically passing __FILE__, __LINE__, or __func__ into a function (typically a logging function), thus simplifying code by reducing redundancy.

                Taking a single argument and both evaluating it and providing it as a string suitable for logging (the ASSERT example, also common in testing frameworks).

  26. X2-Eliah says:

    Also, the program needs blur. Bad.

    And lots of brown.

    And blood splatter on the screen when you move the camera.

    Wait, you are trying to do Blops 2, right? Oh? Ah, nevermind then.

    But seriously, a slight desaturation of the colours would go a long way.

  27. Pickly says:

    Shamus, Shamus, Shamus, you forgot to leave us a beautiful picture of all the arrows pointing in the right direction. :)

    Nice post overall, I don’t have much to add, but most of what’s written is familiar from the civilization 4 modding I’ve been doing lately. (I’m not any more advanced at programming than that, though, so can’t really say much more about it.)

  28. Daemian Lucifer says:

    And on the sixth day Shamus debugged his code,and he saw that comments were good,so he shared it with the internet.

  29. kmc says:

    My general philosophy on comments is, if someone else is reading it and they have to read more than a handful of lines of code to figure out how I’m doing something, I write a little in-line comment. Basically, those comments allow people to skip code when they’re following how the program runs.
    I do it also to explain something if I’m using a little trick that won’t be obvious–so, for instance, I also work pretty much entirely in MATLAB. I like it because we do a lot of on-the-fly programming that turns into standard tools, and because with a bit of skill and cunning (as my boss would say), you can make things run really smoothly. Particularly when you’re doing things like 10-million-point FFTs on top of other post-processing. There are plenty of times when we’re able to take a few lines of code and make it fit on a single half of a line because of a nice little bit of math, but that is completely incomprehensible on the first or even second read-through, and to me that’s wasted time.
    Finally, I like to write a couple paragraphs at the top to clearly delineate all the inputs and outputs, their required formats, what other functions they may come from, &c–whatever makes sense. Sometimes obviates any need to look in the code at all.

  30. DrHeinous says:

    A useful saying I’ve heard, and one I try to live by is that code is “write once, read many”.

    You’ll blow throught and write the code in a snap. But you, or someone else, will probably be going back over it in the future several times over…

  31. silver says:

    I’ve seen a couple people in the above comments defend flowcharts by describing how they used UML or other higher-level-abstraction charts. In essence, they were saying, “apples are good because I’ve had great clarity enhancements using oranges.”

    • MichaelG says:

      In my experience, both flowcharts and UML are the enemies of coding if you want a rapid-prototyping style of development. The documentation just gets so huge that the last thing you want to do is revise the UML so you can revise the code, so you can try out an idea.

  32. Atarlost says:

    One thing that makes code hard for me to read is variable clutter.

    if (FirstDayOfMonth)
    {
    Interest = Balance * InterestRate;
    Balance = Balance + Interest;
    }

    I this example Interest has no reason to be a named variable. Now, at least in this case it’s something real, but it doesn’t add anything. If I’m not stupid I know that Balance += Balance * InterestRate is adding the interest.

    In some cases, though, especially those dealing with fake systems like game mechanics, that intermediate variable that in C family and lisp-like languages doesn’t even need to be named may not have an obvious name. Trying to limit yourself to one operation per line just forces you to come up with a name for a variable that you should never have named. One that would probably wind up a flash in a register after you compiled, but that could wind up allocated in memory if explicitly declared depending on how zealously your complier optimizes.

    Similarly the ?: operator, which is probably anathema to that school of coding can actually make handling the sort of discontinuities that can crop up for esoteric balance reasons clearer. At least to me.

    • Arkady says:

      I agree.

      To non-coder, perhaps
      if (FirstDayOfMonth)
      {
      Interest = Balance * InterestRate;
      Balance = Balance + Interest;
      }
      is easier, but I find:

      if (FirstDayOfMonth) Balance *= InterestRate

      far more obvious.

      P.S.: I’d like to bank at your bank – you double my money every month :-P

      • Veloxyll says:

        One problem that may crop up here is: what happens if you want the value of Interest to be returned too?

        Given that finance and accounting people tend to like any change to be written down (people don’t like it when their bank balance mysteriously changes), returning the new balance value AND the interest value is probably necessary in this case.

        Plus there’s less chance you’ll double someone’s bank balance then add the interest to the new value when using the simpler 1 equation per line method :P

        Also – this is the first time I’ve ever seen the *= notation.

      • decius says:

        Only if 6% interest is 1.06

        I see InterestRate in the first version as being 0.06; with that value your version should be
        if (FirstDayOfMonth) Balance *= (1+InterestRate)

        Which is where an explicit definition of “InterestRate”, contained in a comment somewhere, is needed.

  33. Aldowyn says:

    Wow, wading through this techy talk… Is most of this in C? I’m doing Java, and I’m fairly sure there’s some significant differences in syntax. I can get through most of the bits without code, and some of the bits with code, but it’s definitely slow going.

    Anyway… I haven’t gotten into any big-time projects yet, probably around 100 lines of code is my longest, so I don’t use commenting that much. It would help, even at that scale – most of my programs are still divided into distinct parts (i.e. these variables mean this and do this with the variables), and using comments would help a lot to understand what I’m doing. Using the right variable names is extremely important too.

    My current project (this one just for fun) is a really simple weapon description creator (think like for a text-based game .. dunno how to do graphics too well or I’d probably do pixel art as well), mostly using if/then statements (just a bit of nesting, nothing too fancy) that lets the user enter certain variables one at a time, and it’s supposed to return a description of the weapon (For example, “This weapon is a sword made of steel with a practical hilt, and it shall be known as Anduril ” It only took me an hour this morning, but I ran into a snag because I’ve got a logic error somewhere. For some reason, it’s not reading the input correctly so it comes up with the not an option text that I built into it, and I can’t figure out why. I think it has something to do with some weird convention that I don’t understand that I messed up. (That’s the problem with learning your programs straight from a book. The book does some things some ways and doesn’t tell you why.)

    • Veloxyll says:

      So many text books do this. SO MANY >: ( It’s not such a problem when it’s an advanced book, but a lot of the basic ones just state things with no reason why, If you’re lucky they’ll explain later, but sometimes just ugh.

      • Aldowyn says:

        :D yeah. Pretty much the very first thing we learned, required to do ANYTHING, the book said “hey, we’ll tell you how this works in chapter 14! For now, just memorize it and use it.” Still dunno what it does. [ (public static void main(String[] args) , if anyone’s curious. ]

        Anyway, I fixed it. It was a stupid error, like I expected, but I’m surprised it built successfully. Just some ifs that needed elses in front of them.

        • Veloxyll says:

          When they do that, it’s not so bad, but sometimes they’re like “DO THIS” and never explain it.
          For instance – the hate of Gotos. If Goto is universally reviled, then WHY IS IT IN THE PROGRAMMING LANGUAGE IN THE FIRST PLACE. (I had that one in College – I learn to program on the Commodore 64 in BASIC, then had an 8 year break before coming back to programming with Pascal. Didn’t help my teacher was terrible.
          Having never touched C I have no idea what that line does though – maybe clearing the field for future use, I dunno.

          • Aldowyn says:

            It’s Java. All I know is you need it for EVERYTHING – a “Hello, World!” program required 3 lines – the one defining the class, that, and the print statement.

            • Veloxyll says:

              Oh right. I tried to blot Java out of my memory, it just felt so clumsy

            • Bryan says:

              You need it for everything in Java because Java is a kingdom of nouns.

              Specifically:

              http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html

              Which is part of the reason I hate it…

              • Mephane says:

                I love this phrase “kingdom of nouns”, yeah.

                I am learning F# at the moment, and it’s also a nice fresh experience to have functions themselves be real first class citizens. This means that functions themselves are values, can both be parameters and return values, and applied partially only, too (similarly to how you can partially specialize templates in C++).

                The language effectively keeps all the object orientedness of C# (but with new syntax) but on the other hand encourages the use of functions. The syntax and grammar also help, for example if you have
                let pi = 3.14159265
                and later want to replace this with a function, you can easily modify it here into something like

                let pi =
                  let x = 3.0
                  let y = 0.14159265
                  printfn "let's pretend we can calculate pi so easily"
                  x + y

                and all code using pi will be entirely unaffected. Basically, you can inline code pretty much anywhere just intuitively, and turn any arbitrary piece of code in a function just as you go. Example:
                let names = [ "Alice"; "Bob"; "Charlie" ]
                names |> List.iter (fun name -> printfn "%s consists of %d chars" name name.Length)

                which produces the output

                Alice consists of 5 chars
                Bob consists of 3 chars
                Charlie consists of 7 chars

                Oh and there is no “main” function in F#. You can just write this second two-liner in a file, build the project and run it.

                Thus, the hello-world-program in F# is
                printf "Hello world."

            • X2-Eliah says:

              Let’s not forget how a normal
              cin>>x;
              becomes
              import java.util.Scanner; //just mentioned for looks
              Scanner keys = new Scanner(System.in);
              x = keys.nextInt();

              I mean, hell. You get so annoyed with this during introductory Java stages >.>

          • Alan De Smet says:

            I’m with you. The “goto considered harmful” meme is really annoying. The original letter was nuanced, but it got simplified into “never use goto,” leading to harder to read code because people only superficially understand why goto is dangerous.

            • BlackBloc says:

              “Never use goto” is a decent heuristic and is shorter to explain to students than “In your entire career as a programmer, you may encounter one or two times a reason to actually use goto, and odds are that after reviewing the issue a few times you’d find a much better solution”.

        • Sauron says:

          The reason they do that is because you really need to understand object orientedness (and, to some degree, the Java language) before “what it does” really makes any sense. If you look at it and decompose it, though, you can probably figure it out if you’ve worked with objects at all.

          A brief description, though (a couple white lies and abstractions to make the explanations easier for now, though):
          1) Everything in Java is an object, which means that all of your code needs to be in classes, which means that all of your code that does anything needs to be in methods (the term for functions that belong to classes)
          2) main is a method of whatever class you declare. It is a special method, essentially summed up as “Java calls main when it runs”
          3) the “String[] args” bit just means that it takes in an array of strings as a parameter. We call it args because it contains the command line arguments (if you run the command as “java Class these are arguments”, then the array would have the elements “these”, “are”, and “arguments”
          4) the “public” bit means that it can be used from somewhere outside the class (which is necessary in order for main to be properly called by Java)
          5) the “static” bit means that you don’t have to have an actual instance of the class in order to call it. Think the difference between “abc”.substring(1,2), where you needed a particular String to call substring(), and String.valueOf(3), where you actually calling the valueOf against the String class rather than an actual String.
          6) The “void” bit just means that it doesn’t return anything

          And, there it is, the magical line explained. The reason they put of explaining that, however, is that it’s trivial once they teach you that everything is an object, the difference between public and private, what a static method is, what return types are, and what parameters are.

  34. Michael says:

    I remember, in an act of sadism, back in college, I codded a couple programs in C using no spaces, and no line breaks, whatsoever. I crammed the entire thing into one unreadable lump of code, subs and all. The worst part was I could still debug it…

  35. wtrmute says:

    Funny, with this great declaration of love for comments, I half expected your head to crack open and have Dr. Knuth crawl out from the stump of your neck. Have you ever looked at Literate Programming?

    • Mephane says:

      Oh god, just looking at the example there does me so not want to try this out. It might work if the whole code were actual human language, but that mixture of their own macro syntax, real sentences and code fragments as cryptic as ever (or even more so) looks just terrible.

      And the human language part looks more like a syntax which can be read like human language, but not written naturally, you still have to obey a specific syntax and grammar that is different than natural speaking (as that would require an AI better than anything available today).

      Oh wait, now after a second glance I see it: The human language isn’t code at all. It’s just a macro that allows whitespaces inside. This is actually worse than I had thought.

      • wtrmute says:

        Yes, the “human language” part is actually TeX markup. It *can* be written “naturally”, but then you might have some styling issues. I’ve heard of some newer systems which use HTML or even Wiki markup, but the example in that page (being CWEB, written by Dr. Knuth and Dr. Levy) would probably use Knuth’s own typesetting markup.

        Evidently, have the whole thing be “human language” is pretty unworkable, especially in the 80s when this thing first appeared — you’ll have to have some parts in a proper, context-free language so it can be fed to a compiler, just like the documentation-parts can be fed to a document-processing software like TeX. It’s not a silver bullet designed to have random people off the street code operating systems, it’s designed so people who already *can* code can write the program in the order that they reason about the problem, not the one that the compiler requires.

  36. RTBones says:

    *shudders*

    You hunt for the misplaced minus sign reminds me of a FORTRAN problem I had with a coordinate transformation matrix (a rotation) a few years ago. Oddly enough, it was also a misplaced minus sign, except in my case, it was a “-sin”. It also took quite a while to find (and lots of math using pencil and paper to figure it out).

  37. Neko says:

    Ah, it’s those damn copy-paste gnomes.

  38. Julia says:

    My father had a job that included debugging someone else’s old FORTRAN code. One evening, he had brought home a printout of a bit of it, was looking it over, and an ordered pair that should have been (a, b) was instead (b, a). He showed it to me, and pointed out that just one error like that could make a huge difference in a program. (Either a=0 and b=1 or a=1 and b=0, I don’t remember which. I’m not sure how much it matters now.)

    So, yeah, one value being off can wreak a fair bit of havoc. I’m glad you figured that out.

  39. BlackBloc says:

    The benefit of self-commenting code is that your precious comments can then be higher level stuff that explains the holistic logic of the thing, rather than look like (ok, argumentum ad absurdum, but still):

    int a; // This is the year.
    int b; // This is the month.
    int c; // This is the day.

    You can wax about the need to be disciplined and leave comments but the cold hard facts are that writing comments takes time, therefore the time that will be spent on writing them will be something really close to a zero-sum, non-replenishable ressource. If you’re spending time documenting your code when the variable, class and function names could be doing it for you, well that’s time you’re not spending writing elaborate higher level descriptions of your algorithms.

  40. Lalaland says:

    Talk of flowcharts for code reminded me of Rational Rose and the mania for UML when I was in college, the thought of ever having to do that crap for a living is part of what turned me off coding. Ironically I hated comments and wondered why I kept getting marked down for the lack of them, ‘it’s obvious what that string of characters from the unloved parts of the keyboard does!’, until I used poorly documented and commented libraries from the internet for my final year project. In fact I only worked out how the library actually worked at a high level too late to fix my project in the end

  41. Yahzi says:

    Flowcharts aren’t dead…

    you’ve never seen an aerospace control law diagram, obviously.

    I have, and now I need Clorox for my eyes.

  42. […] Samus Young, who is going for a retro feel with his Project Hex, I was aiming for the appearance you would get if you put some cardboard tiles together with some […]

  43. Antonio says:

    Is there going to be more to the Project Hex series ?

  44. […] Samus Young, who is going for a retro feel with his Project Hex, I was aiming for the appearance you would get if you put some cardboard tiles together with some […]

2 Trackbacks

  1. By Postmortem: Laying tile « Arges Systems on January 9, 2011 at 6:59 am

    […] Samus Young, who is going for a retro feel with his Project Hex, I was aiming for the appearance you would get if you put some cardboard tiles together with some […]

  2. […] Samus Young, who is going for a retro feel with his Project Hex, I was aiming for the appearance you would get if you put some cardboard tiles together with some […]

Leave a Reply

Comments are moderated and may not be posted immediately. Required fields are marked *

*
*

Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun.

You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>

You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?

You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.

You can make links like this:
I'm reading about <a href="http://en.wikipedia.org/wiki/Darth_Vader">Darth Vader</a> on Wikipedia!