Rants on software, computing, and any other topic I feel like.

Friday, June 22, 2007

My Confession

I have a confession to make. Forgive me. Wait, don't forgive me. I'm completely unapologetic. I am a programmer, and I don't write comments. I just needed to get that off my chest.

I don't believe in comments.

I have been writing a lot of fairly complex code lately. And all the while, the voices of dead Computer Science professors have been speaking to me. They repeat the mantra of good code commenting. I feel guilt, like when I go to church. Or when I don't make my bed in the morning. Of course, not one of them is able to give me any good suggestion of what a good set of comments is. They just tell me what isn't a good comment. So does that mean that anything else is a good comment? Like lots of swear words in the code. That's probably more useful than real comments, because they make me laugh and keep me from falling asleep at the keyboard.

Good comments, I'm told, are not just a rehash of what is already in the code. Well, if it isn't already in the code, then it isn't much use to the program is it? I don't believe in comments. I think they are mostly a waste of time. Maybe not for you, but for me they just make my life difficult. I have to make a context switch to English in order to write them. That takes time and just serves to confuse me.

Whenever I write English, I take the audience of my writing into account. Who is the audience for my comments? Some moron with a basic C++ book on his desk? Or the great man himself, Bjarne Stroustrup? Bjarne is pretty smart and will probably be able to figure out my code just fine without me, or my comments. Because he speaks C++. I speak C++ too, so that's how I like to communicate with computers and other people who speak the same language.

So I don't write comments. I'm one of those people who likes to use good variable names, good function names, and good file names. When I look at others' comments, I don't usually trust them, because they often don't make any sense. Or they are just plain wrong. That's just awesome. Like the time I first starting programming and I spent two days wondering why the second member of a pair of ints (pair) was always zero, even though the comments said it should contain some valuable piece of information. Actually, it was the first member, not the second one, which I finally figured out by actually looking at the damn code. Wonder of wonders, the code actually told me what the code did. Amazing.

I think that instead of comments we should put quotes of great authors at the top of all our code. That way, when people read our code, they will think that our code is profound, because we quote the greats of our time like, Dostoevsky, Helen Keller, or Dave Barry. And the best thing would be to just randomly pick those quotes so that when people try to make some connection between the code and the quote, they'll spend lots of time trying to figure out. Then they'll feel stupid, but won't want to admit it and we can fun of them when they can't explain the connection. And we won't have had to be smart at all, because all those people that we referred to are smart.

Have I even written comments? Of course, I slap all my comments in the headers, when I don't feel like writing documentation. Or when the function name is getting too long. Or when some fellow programmer makes me feel guilty for not following the religion of comments. What is the point of writing commments if the function name tells the whole story? Take vector for example, the size() function returns, guess what, the size of the vector. I know what you're thinking, that is completely non-intuitive. It's got to be commented. Look, if the function name can't tell you what the function does, then maybe you should change the function name. And if your function name gets too long, then maybe your function is doing too much.

Good, maintainable programs are easy to understand not because they have lots of comments explaining their complex structure, but because they are straightforward, not complex. Complex is a synonym for spaghetti. Code should be more like ravioli. Good ravioli, not that crap they give you in restaurants. Chef Boyardee is delicious. The mental model of a good program is easily understood by normal humans. And if that mental model is nice and straightforward, then the functions that act on it should also be straightforward. A function called get_ the_ thing_ and_ reroute_ the_ other_ thing_ with_ the_ thing_ you_ have_ from_ before() doesn't need to commented, it needs to be thrown out. The class it lives in probably does too. It's doing too much.

I'm religious, but not about programming. In religion, there are things that you believe just because they seem right. Code comments may feel right, but they just don't prove their value outside of giving people a good feeling. I'm going to love my enemy for no good reason, because that sounds like a good idea. But I'm not going to type any more comments until I have a mathematical proof that it's good for me, like ravioli.

Tuesday, January 10, 2006

C++ is not dead.

There has been some recent speculation about the death of C++, since the C/C++ Users Journal has ceased publication. So is C++ dying?

Maybe.

C++ as the one and only language for application development died a long time ago. Java has taken over what once was COBOL's place as the language of business logic. If you're writing straightforward code that is going to be used by the five other people in your company, then Java is for you. It holds your hand and doesn't let you make many mistakes. It has lots of libraries for those who have no desire or brains enough to write their own. Not that I think Java programmers are stupid, some of them aren't. I think that Java, like many other scripting languages, allows you to be stupid, and still write code that works ... mostly.

But yes, Java should take over the role of "Business Language for Dummies". C++ was never good at that. But since there wasn't anything else around at the time, that didn't stop people from trying. Which is why we have so much C++ code that sucks. A lot of stupid people tried to use a language that requires some brains. C++ isn't for dummies. It's for people willing to take the time to learn the language. And as I've said before, that requires understanding of C++, not just C. So C++ gets a bad rap.

Some people say that C++ is dying because C does everything that systems developers need to do. Well, so does assembly, but they only use that when they have to. C++ adds a lot of features that most systems developers don't even know about, let alone know how to use. Real programmers only need while loops, but that doesn't mean that for loops aren't useful. How about template metaprogramming? How about virtual functions instead of function pointers? How about references instead of pointers? Can you create a new numeric type in C and have it act natively? And get the compiler to optimize and inline all of that code? Can you write recursive algorithms that can get inlined completely?

All the excuses claimed by C wielding systems developers come down to two basic problems:

1. There isn't a C++ compiler for my platform.

2. C++ is hard to learn. All them fancy templates and classes are just too complicated.

Ok, some systems developers may have an excuse on number one, but since g++, one of the most standards-conforming compilers out there is available on like 20 platforms, chances are your processor is supported. So it's less of an excuse than you think. It's probably going to optimize your code a whole hell of a lot better than the craptacular C compiler that came from the vendor that barely compiles to correct assembly half the time. I love to hear the words, "But C is faster than C++.", coming from someone who is knowingly using a substandard C compiler. If your compiler sucks, then does it really
matter what language you use?

Number two is just ridiculous. Anyone who has learned about C, pointers and recursion, should be able to learn the features of C++ with some effort. Will it take a little work? Yes. But learning C took some work too, didn't it? C++ is the next step. Really learning C++ is going to take as much effort as learning C did, even with your C knowledge.

So C++ is dying because Java is better for writing code to organize your CD collection on the one end and C is better from writing systems code on the other end. In the middle we have real application development, which C++, turns out, is pretty good at. How do I know this? Because as a manager from Microsoft once told me, 90% of code at Microsoft is written in C++.

No, actually, I don’t think that C++ is dying. Spare me.

Wednesday, September 07, 2005

CSS is Crap

Ok, so I think it's fairly obvious that I am big fat C++ bigot. That's probably because I've programmed in C++ more than any other language. So I'm a little biased. That's okay because C++ actually is better in many cases.

But because I'm the resident "computer guy" for various groups, like my family and friends, I regularly step out of the C++ realm and try other things. Take for example, web pages. I've done my share of JavaScript and PHP generated pages. But most of that was years ago before what I have been told is now the golden age of web development. Life was hard then, but back then we only had IE and Netscape. But a new day has dawned. A great leap has been made on the Interweb. With technologies like XML, CSS, XHTML, PHP, and the vast Java pile of beans, cheese, and who knows what, developing web pages is supposed to just be a piece of cake.

Recently, I tried to actually create one of these fantastic web pages using one or more of these technologies. After about a week of just trying to format a page without using those evil nested tables and using the magic of CSS, I started to cry for my mommy, the only person who might care about my personal hell.

Why in heaven's name does this have to be so damn complicated? I've learned numerous languages and file formats over the years, so I think I have an idea of how to go about reading a language spec and understanding what it does, and then how to use it effectively. Has anyone actually tried to use the CSS spec or any of the docs out there to get anything done? No wonder there isn't a browser out there that actually implements it properly. It is so generic as to be completely useless.

I really feel for the children of those wrote that stinking pile of MIT-grad generated uselessness. I'll bet they tell their kids when they ask for math help, "Okay, I'm not going to actually tell you how to do that math problem, I'm just going to give you these advanced level calculus books and let you figure it out yourself. It's all very clear once you understand the analysis of infinite-dimensional ring theory."

Yes, I understand that there should be many ways to skin a cat, but CSS gives you about seven hundred. And that is just the number of ways to tell it how big to make your fonts. Not that any of them actually allow you to do that. They all just give the browser a suggestion. And since we really do need 17 browsers out there (for competition right?), there are 17 different ways to interpret what I put in my CSS. In other words, my page looks like crap on anything but Opera version 6.6.6.

I missed the dot com boom. I was working. Is this the nonsense that they spewed out with all those billions? Look folks, this is what you get when let philosophy and foreign film majors get into engineering. Heaven forbid that someone disagree with someone else and the person with the better solution actually win the argument. That would be solutionism. Almost as bad as racism, ideaism, or using your brain. They put everyone's solution in there. Just in case people want to use CSS to teach their dog to hate kids with green eyes.

All those spare web developers are "rethinking their careers" because they sucked at them. No wonder they didn't get a lot of fulfillment from their jobs as web lackeys. If I sucked at something, I don't think I would like doing it either.

Some people just need to say, "That sucks. Really it does, and here is why." They want to think that everything has a meaning and value. News flash, some things just suck. They're crap. They should be thrown out. Figure out the right way to do the job, and leave everything else behind. Like 90% of CSS.

And your little dog too.

Sunday, June 26, 2005

Java is the worst of both worlds

Unless you were sleeping on the first day of your programming languages class, then you know that there are two kinds of programming languages, compiled and interpreted. Compiled languages are those that are routinely converted to some other language (usually assembly/machine code) for execution. Interpreted languages aren’t. Another program interprets the code on the fly and makes the program work. And no, pseudo code is not a programming language, it’s a human language. Don’t even dare confuse the two. See the entry titled “Humans are not Computers” if you disagree with me. You will realize the error of your ways.

Both types of languages have their advantages. Compiled languages tend to be able to squeeze the most out of their host platform because there is no interpreter to slow things down. However, much of the “information” about what the program is supposed to do is lost since we’re converting from one language to another. You always lose some insight when you convert from one language to another.

Interpreted languages on the other hand tend to be more flexible and easy to use. Because interpreted languages don’t have to worry about what the code actually does until it has to do it, it can allow a lot of ambiguity. The interpreter can figure out a lot more things by itself if it has the data that needs to be processed at hand when it interprets the code. A lot of flexibility comes from the ability of the interpreter to interpret any code given it, even if that code didn’t exist until runtime. The PERL eval() function takes PERL code as a string and can interpret it on the fly. Also, interpreted languages are executed on the fly, the interpreter has more information about what the programmer meant to do, so it can optimize many things that a compiled language can’t. This capability hasn’t been exploited as much as it might be. The Java folks have done some work with just-in-time compilation. I suspect this is where they get ability to hit benchmarks as well or better than C++ code.

Ah, Java; the savior of all of use who are trying to write software for everything from mainframes to calculators to cheese slicers and unmanned exercise machines. Java is the worst of both of these types of languages. It isn’t an interpreted language, it’s compiled. But it isn’t compiled to machine code to take advantage of native code, it’s compiled to Java byte code, which is then interpreted. “But byte code interpreters are really fast!” they say. I don’t care how fast they are, unless they’re so fast they don’t actually run, I don’t much care. If they take time, they take time. You just can’t get around that.

Now I have nothing against interpreted languages. PERL is one of my favorite tools. But look, Java just doesn’t give you any of the flexibility of an interpreted language. Once you’ve compiled to byte code, you’ve gotten rid of all that semantic goodness that is found in the original program. So you’re interpreting without any of the benefits of interpreting, and compiling without any of the benefits of compiling.

I hear folks saying, “what about the platform independence? Isn’t that a great thing?” Yes, yes it is. But there a lot better ways to solve that problem. On the compiled end of things, you can use platform specific code wrapped by platform independent APIs like STL, Boost, Qt and wxWindows. Or just write platform independent code with conditional compilation (#ifdef’s for the buzzword impaired).

On the interpreted end, things are even easier. Just write platform specific interpreters. This is probably the way to go when performance isn’t an issue. And even if it is, then JIT techniques might help your cause.

Java just isn’t the answer.

Tuesday, May 17, 2005

Writing C in C++

I’m sure that you’ve heard of the term C/C++ as if somehow they are so interrelated that they can combined into a single term. C and C++ are about as close as a lilac bush and George Bush. Sure they share some of the same terminology but you wouldn’t want to meet one of them in a dark alley at night.

C is good for one thing, being one step above assembly code. Anyone who tells you otherwise is lying to themselves. Everything about C is about making things you do in assembly easier. The perfect example is the switch statement. There is no rational reason to force the programmer to put break statements at the end of every case. It doesn’t make any sense unless you know that the switch statement is likely to be implemented using jump opcodes. Also, who in their right mind uses up an entire operator to implement bit shifting?! Unless you’re some sort of divide-with-shifts freak, then you’re just not going to use them very often.

And why do they call them function pointers? There’s no reason that the user should have any idea how functions are implemented, let alone knowing that they can be pointed to. The syntax for function pointers is bad enough.

C is a great language for compiler writers. For every construct in C, there is a fairly straightforward translation to assembly. This is of course the main issue behind all the complaints about C. It wasn’t designed to be a language, it was designed to easily translated. So it shouldn’t come as much of a surprise to learn that the guys who came up with templates never wrote a compiler. Sure, they took a class on compilers, but that doesn’t mean that learned to love their local compiler guy. Really, who complains the loudest about how hard it is to implement templates in C++? Compiler writers. More specifically, Microsoft’s compiler writers who proved that templates are hard by producing Visual C++ 6.0 where using templates is like trying to teach your dog new tricks only to find out that it is an armadillo. Sure an armadillo looks like a dog, but partial function template specialization looks likes it might work. But it just doesn’t. Whether you like it or not.

C++ is a boon to the programming world. It took C places way beyond where the compiler writers wanted to go, which is a good thing. When people start complaining about something, it’s usually a good sign that something is getting done. C++ doesn’t make any effort to be nice to compiler writers. This made getting Visual C++ done take way longer than Microsoft Bob, but it sure makes for a flexible language. Compiler writers don’t like that word, flexible. It means that they have to work. They have to work to take all the flexibility into account. But I don’t care, I’m not a compiler writer.

Someone invented C so they wouldn’t have to code in assembly, and someone invented C++ so they wouldn’t have to code in C. So if you’re a C programmer writing C in C++, then you’re basically installing an automatic garage door opener and then opening the door by driving into it. You’re not using the features of the language that you claim to embrace. Here are some of the features that C in C++ programmers tend to continue to use even thought C++ has surmounted their craziness.

First, function pointers. Virtual functions were invented so you freaks using function pointers could stop the madness. If you’re using a function pointer as a callback, then use virtual functions. They’re easier to use, more flexible and the syntax doesn’t look like monkey spew. There are numerous other reasons to use virtual functions beyond callbacks, so for those of you who think that function pointers are God’s gift, they’re more like Satan’s spawn.

Second, typedef’ed structs. Newsflash, typedef’ed structs are no longer necessary. You wouldn’t be using them in C++ if you knew why you had to use them in the first place. A struct is now an actual type. That was the whole point of C++. Making classes and structs act like native types. Along with this is the flawed belief in the difference between structs and classes. Repeat this mantra every morning in the shower if you still think that stucts and classes have some fundamental difference, “A class is just a struct where the default is private versus public.” There isn’t any other difference. No way, no how. Most compilers don’t even remember which is which.

Third, void pointers. They were a bad idea in C, but perhaps a necessary evil. But in C++, they’re just not at all necessary. Void pointers are not the tool of the super-hacker, they are the last resort of the design-impaired. Just because you don’t know of any other way to do what you’re trying to do with void pointers, doesn’t mean that using them is OK. It’s not OK. C++ provides so many ways to not use void pointers, that using them is a sign of your C++ ignorance. Go back ten spaces and read your beginning C++ book again.

Finally, using pointers to pass things by reference. I don’t care that you’re used to doing it this way. We just don’t pass things by pointer anymore. We pass them by reference. References are an improvement over pointers. Get over that they can’t be NULL. This is a good thing. 90% of crashes in C programs are NULL pointer dereferences. So it makes sense (yes, it actually does) that you should want to minimize the use of pointers. They don’t make you cool or more of a super-hacker because you use pointers for everything. They just make you reckless. References are safer than pointers. You don’t drive around your car without a hood just so you can have easy access to the innards when you need them. You open it as needed. Adding pointers is just like putting hood pins on a Pinto. Same goes for pointers. Use them as needed.

So what is the message here? If you’re using extern “C” at the beginning of your C++ code and telling your boss that you’re writing in C++, for all the rest of us who didn’t sleep through the nineties and have to read your over-syntaxed code, please go read a beginning C++ book and join the 21st century.

Monday, March 28, 2005

Humans are not Computers

I read an article today about a program that is supposed to turn English language into code. Many folks thought that this was a great thing in that people would become more precise in their use of English as a way of describing what a program does. This is wrong and a complete misunderstanding of language, both computer and human.

Here's a news flash, just because PHP and Swahili are both called "languages" doesn't mean that they really have much to do with each other. The reason that they are both called languages is because they both express something to something else. They're completely different beasts. Computer languages are for talking to computers. Human languages are for talking to humans.

Computer programmers are fairly antisocial, and so don't have a lot of experience actually talking to real people. They spend a lot of time expressing themselves to the little boxes on their desks. These boxes are not human beings. Humans don't work like computers. They don't do what you tell them to do most of the time. They won't always like you. They might just up and leave if you don't treat them right. And the biggest thing of all, they have brains. No really, your computer doesn't have a brain and that annoying marketing guy does.

This means that no matter how many times you snicker or roll your eyes behind their back about their lack of knowledge of Excel macro programming, humans are smarter than computers. They might actually be smarter than you in some area other than computers. For example, they might know more about something important, like how to make money, or why you should take a shower, or how to talk to girls.

Back to the main point, which is that there is and should be a difference between human and computer languages. Forcing people to be more precise in their use of human languages only forces them to think like a computer. Why should they think like a computer? They're not computers, they're people, and people are smarter than computers.

Your job as a computer programmer is as a translator between human language and computer language. Anyone familiar with translation of human languages knows that it takes some brains to do it. You have to be familiar with the idea of context, idioms, etc. of both languages in order to translate well. To be a very good translator, you also have to be familiar with the cultures that you're dealing with. Something a computer will likely never do.

The same goes for computer programming. Computer programming isn't simply about translating word for word the human spec to code. You must interpret the human language by using your brain, and convert it to computer language. A spec is written by a human is meant to be read and understood by a human. The spec writer isn't there to do your job. That *is* your job, translation. Programmers who don't understand this concept should be beaten and have the word "Spec Freak" tattooed to their forehead. If you are a "Spec Freak" and no one knows about it yet, then take this opportunity to stop. People might actually start to like you. They might not run away as you approach the water cooler. And if you combine it with regular showering, then you might even be able to start talking to girls.

I'm going to tell you a story about UML. If you're not familiar with it, it is a way of describing the design of code using pretty pictures so that PHB's can understand it. It actually turns out that when used properly, it can be an effective tool to communicate to other humans about the design of your code. It's a human language.

The problem came about when some lazy "Spec Freak" was annoyed that after he spent all this time creating a pretty UML picture that he had to then translate the picture into code. He thought, "I should write a program to do this for me." He thus sealed his status as a "Spec-Freak". He then found that there were ambiguities in his UML that couldn't be translated into code. He found that they were things in his code that he couldn't translate into UML. So he "fixed" UML to be more precise, and more useless. UML is a human language. Human language has a lot of ambiguity, because humans are smarter than computers, and can deal with it. Adding precision and getting rid of ambiguity in human language turns it into computer language and thus gets rid of all its usefulness as a way to communicate with other humans.

Humans aren’t computers and computers aren’t human. Humans communicate well with humans. Computers communicate well with computers. Programmers are needed to translate between the two. No computer will even be able to do it. At least not until strong AI gets invented.

Tuesday, February 22, 2005

Optimization

I don't think that I would make a good game programmer.

A former coworker's life dream was to become a game programmer. Well it came true and I found myself wondering why someone actually hired him. Look, I've seen his code and have to work with it every day. Or more accurately, I play chicken with his code every day. I poke at it in some soft spot hoping that it will give way, only to find myself being thrown off in some other unforeseen direction. His code can't be modified without breaking at least 2 other things. It's like wack-a-mole. You pound down one of the little buggers only to have two more pop up.

So I assume that they took a look at his code at some point during the interview process. They must have seen the consistent use of sweet optimizations, like bit-shifting instead of dividing, reuse of variables because they cost so much you don't want to waste them, and using C arrays instead of std::vector because, well, C arrays just gotta be faster, because they're C. Being game programmers themselves, they probably saw the incredible value of all this. They also saw that he refused to cave into the C++ madness and still coded in C, using a C++ compiler. Because, it's just faster you know. All those objects are just too useful to be efficient.

In game programming, it is apparently a good idea to make calls to your database in an inner loop. My coworker did this all the time so it must be a good idea. I think I’m just uninformed, because last time I checked, database calls are pretty slow. I guess if you wrap them in a function that doesn’t *look* like a database call, then it’s okay. Or maybe simply putting them in an inner loop magically makes them faster. I wish I knew more about game programming. Maybe I can buy a "Game Programming for Morons" book at the mall and start working on becoming the next John Carmack.

Okay, so seriously, this coworker of mine actually got in an argument with me over the value of using bit shifting over a simple divide for integer division. Yes, I know everyone is taught that bit-shifting is really fast, but while I understand that no official announcement was made, compilers are now pretty good. They’ll recognize your divide by a power-of-two and convert it to a shift while you retain the readability of a divide. They’ll even make sure that it works for signed and unsigned numbers correctly. I even proved this to my coworker by showing him that the disassembly from even the MSVC++ non-optimizing compiler optimized this correctly. His response was something along the lines of, "oh, well, right, yea, but, well, what about pipelining?" Huh? Pulling out the technology of the week doesn't help you win the argument. I wish I mean enough to explain to him how stupid he sounds.

This is of course the same guy who doesn’t see a problem with casting to integer what should be simply left as floating point, because you know, integers are faster. We’ll just ignore the fact that casting from floating point to integer and back takes *forever*. And in the same code as he does his cast to integer, shift to divide (because it’s faster), and cast back to floating point, he makes one of the biggest game programmer gaffes, he writes:

pow(x, 2.0);

I mean, come on! This is why this blog is called Mad Software. This stuff just makes me want to scream. This isn’t just a game programmer thing, this is something that no one does. They just don’t. It’s far faster and just as readable to write:

x*x;

Now, this whole rant brings us to one of the first lessons of optimizing your code. Don’t optimize prematurely. All the above nasty is a perfect example of this: lots of optimizations at code level, without ever thinking of the global optimization problem.

You probably didn’t believe me when I said this guy was putting database calls into tight inner loops. Well, you’d be wrong. It was cleverly hidden in a conversion function, but it was a database call all the same. He never bothered to optimize it, or even did he recognize the fact that it was slowing the whole program down. That’s because he never did what a good programmer should do, profile his code. That is to find out what parts of the code actually are taking all the time. Guess what, it probably isn’t that really slow divide by two. It’s the database call hidden by a few layers of indirection that you’ll never see because you didn’t write the database code and didn’t realize that the guy that did is an idiot.

I assume that my coworker’s new employers saw these kind of things in his code because game programmers are the cream of the crop and don’t miss anything.

I just wouldn’t make a good game programmer, my code doesn’t suck enough.

This page is powered by Blogger. Isn't yours?