This site will look much better in a browser that supports web standards, but is accessible to any browser or Internet device.

Anomaly ~ G. Wade Johnson Anomaly Home G. Wade Home

August 31, 2006

Programming for Other Programmers

One of the odd things about programming is that you are writing for two different audiences. One is the dumbest device ever invented (it does exactly what you tell it to do) and the other is a (hopefully) intelligent programmer who will need to read this code later. We spend a fair amount of time figuring out how to make the computer understand what we write. I'm not so sure that we spend as much time on the other part. In fact, the only advice I have ever seen for writing for the next programmer is the admonishment not to write advanced code because later programmers won't understand it.

I think it is time to challenge that advice. I'm not going to advise that we don't take the other programmer into account when writing code. (After all, you may be that programmer someday.) I challenge the fact that we should write code to the lowest common denominator. Code should be written to a level appropriate to the job at hand. For example, third party library code is often written using more advanced idioms. This often results in more power per line of code. Since it will not be modified by novice programmers, there is no need to make it overly simple. Code that is expected to be used and maintained by entry-level programmers should be written using much simpler idioms.

If we don't allow more advanced idioms in a code base, the code never progresses beyond what would be written be an entry-level programmer. This will make retaining programmers who want to improve their skills harder. No one wants to spend their entire career maintaining entry-level code. If you are forced only to use entry-level idioms, that also makes it harder to keep up with advances in the the state of the art. After all, what's the point of learning cool new approaches, if you will never get a chance to use them.

Just about every advanced technique I've ever seen has been avoided by people because it is too hard (objects, exceptions, templates, operator overloading, STL, table-driven code, patterns, etc.). When the technique is new, that is probably a valid comment. But, as the community develops experience with the technique, we discover both its weak points and strong points. When the strengths outweigh the weaknesses, we should really begin developing our own experience with a technique.

A well-written piece of advanced code can also convey more information in a small space. Some really good examples of this are the algorithms from the C++ standard library. Which would you rather maintain in code:


    if(vec.end() != std::find( vec.begin(), vec.end(), 42 ))
    {
        std::out << "Found" << std::endl;
    }
or

    for(std::vector::iterator it = vec.begin();
         it != vec.end();
         ++it)
    {
        if(42 == *it)
        {
            std::out << "Found" << std::endl;
            break;
        }
    }
or

    for(int i = 0;i < vec.size();++i)
    {
        if(42 == vec[i])
        {
            std::out << "Found" << std::endl;
            break;
        }
    }

Although the last is easiest to understand for someone who has never seen the STL algorithms, You still need to read quite a bit of code to figure out what it is doing. The condition is buried inside the loop. There are also several places where a coding error is possible. Accessing the element is slower (because we have to index and dereference each time). The second drops the speed penalty for indexing, but is even more complex to read. Once you get used to the first approach, it is smaller, faster, and harder to get wrong.

Should we avoid the first approach because an entry-level programmer might not understand it?

Some people will think this is a silly example. After all, the first is officially supported by the C++ standard and STL algorithms are no longer considered advanced by most C++ programmers. But I still remember when this was considered beyond the cutting edge. Following a mandate to not use this approach would result in doubling the size of this code and requiring more reading for everyone who maintains the code from now on.

Although I am advocating the use of advanced techniques, I am not suggesting that we use them indiscriminately. If the argument that entry-level programmers won't understand it isn't enough to prevent the use of a technique, the argument that it is new or advanced isn't enough to make you use it. Every new technique requires some learning time. A technique or idiom has to prove that it gives enough benefit to overcome this learning cost. The important point that many people seem to forget is that the more of these techniques you learn, the easier it becomes to learn the next one.

Posted by GWade at August 31, 2006 10:12 PM. Email comments