Taking Advantage of (Read: Working Around) Syntax

Posted on November 3, 2008
Filed Under Computer Science |

Syntax Smells

“Programs must be written for people to read, and only incidentally for machines to execute.”

~Abelson and Sussman, SICP

If 8 years of programming has taught me anything, it’s that programmers need to give themselves every advantage imaginable. I’m not disparaging other programmers.  I say this as someone who has been humbled on the altar of bugs many times.

The fact that my first language (C++) is one of the most complex languages probably didn’t help. C++ isn’t my favorite language, but I always find myself coming home to it, whether for school assignments, or more recently for money. Plus, it ranks higher than Java in my book. Yuck!

Most programming languages have fundamental shortcomings that prevent them from being very human-friendly. Like what? Like nested parentheses and braces and brackets. Fortunately, along with programming languages evolved code editors that do great things with indentation, coloring, and matching brace highlighting. The actual problem isn’t fixed (a colored, indented C++ program is still the exact same thing as a non-colored, non-indented C++ program), but the tools exist to make it a non-issue.

There is a wrong way to do it, and a right way to do it, but none of it is enforced by the compiler.

Assignment Within if(){

When I was 14 and 15 and hadn’t been using the language for very long, I made a whole litany of embarrassing mistakes. For instance, I would spend an hour trying to figure out why the following wasn’t doing what I expected:

 for(int i=0; i<10; ++i);{
     do_something(i);
 }

Fortunately, I stopped falling for it after a few times. However, I couldn’t seem to shake the following error:

 if(my_ptr = NULL){ // Wrong, but no compile error!
     do_something();
 }

To the rookie, this looks correct at a quick glance. Even worse, it compiles without warning. In fact, this was one of the evil no-nos that Java outlawed altogether, even though it has legitimate uses.

No matter how many times I swore I’d look closer, 2 weeks later I’d find this same bug after 30 minutes of frustrated debugging.

Eventually, I eliminated a large subset of this error by writing the equality test differently:

 if(NULL = my_ptr){ // compile error!
     do_something();
 }

This caused a comparatively small boost in my productivity. However, this helped, and it required no effort. Every little bit counts. Interestingly, this kicked me out of my groove: I started making this error a whole lot less frequently because I was thinking more about my equalities. Unless projects have strict style guides, I still code it this way.

For being a simple style change, it comes with a few benefits:

  1. Anybody can understand this code.
  2. When you screw up, it doesn’t compile.

//TODO: Lists

Some code generators, like Visual Studio 2003, fill generated functions with comments:

 void importantFoo()
 {
    // TODO: Implement this!
 }

For the authors of the code generator, this suits its purpose: informing the programmer that they have some work to do while generating compilable code.

Believe it or not, some code generators improve upon this. For instance, I’ve seen some code generators taking an exceptional approach:

 void importantFoo() {
     throw std::runtime_error("TODO: Implement function importantFoo()!");
 }

This comes with benefits: unless the programmer is a complete ninny, this code will be executed, and the nascent program will be prematurely snuffed from this Earth.

If this doesn’t cause the programmer to get off his lazy rear end and code, then what will?

The // TODO! statement is certainly not unique to code generators: it seems to be pretty popular amongst programmers, too. I am no exception them, too.

For a while, I took the comment approach to the TODO:

 void my_foo() {
     // TODO: Implement me! I am a yummy pizza!
 }

I’ve always felt a little dirty writing these. Realistically, your brain’s stack can only hold 5-9 items, so I can see an argument for temporarily using them. However, all you’re doing is passing the buck to an older, wiser future version of yourself in a brave new world with flying cars and butler monkeys.

It’s obvious that if you had flying cars and butler monkeys, the LAST thing that you would want to do would be to implement a // TODO statement left by a barbaric past self.

It’s my opinion that if you HAVE to write one, you should resolve the issue ASAP. For instance, before you  compile or interpret or “(read)” or whatever your language uses.

But recently, I found an even better TODO method for compiled languages:

 void my_foo() {
     TODO: Implement me! I am a yummy pizza!
 }

In C++, this generates about a trillion compiler errors (more or less). Compiler errors, for whatever reason, put me on a mission to fix a problem, so this is is an easy and helpful motivator.

I call these “Quit your bitchin’” TODO lists: Quit your bitchin’ and implement me! You have to do it sooner or later!

It is important to note that you should NEVER do this in Python. Python is expressive enough that this syntax will likely cause the International Space Station to fall to earth while buttering bread on the wrong side. </bad_joke>

Conclusion

Modern programming languages are designed  with human readability in mind, but there isn’t a “perfect language” in this regard. Best practices develop around programming languages, and is imperative that newbies find out what these are ASAP, because they are only hurting themselves if they do things their own way.

In addition to using best practices, sometimes you can make things easier for yourself with little effort.

Popularity: 9% [?]

Comments

Leave a Reply