Slashdot Mirror


How to Keep Your Code From Destroying You

An anonymous reader writes "IBM DeveloperWorks has a few quick tips on how to write maintainable code that won't leech your most valuable resource — time. These six tips on how to write maintainable code are guaranteed to save you time and frustration: one minute spent writing comments can save you an hour of anguish. Bad code gets written all the time. But it doesn't have to be that way. Its time to ask yourself if its time for you to convert to the clean code religion."

4 of 486 comments (clear)

  1. Re:That was just terrible... by Sax+Maniac · · Score: 4, Interesting
    Right, I laughed at that #define remark, it's so green.

    The real thing is to used named constants where it makes sense. #define is the crudest approximation of that, C can use enums, C++ can use "const" for compile-time values, etc.

    In a real project, you have to scope your constants otherwise you'll have a billion of them in "everything.h" and every time you touch it, the world will rebuild. So nix the "centrally located" file theory.

    In a real project, your constants will often have interdepedencies on other bits of code, so changing one will frequently affect the others. Heck, maybe changing one will cause it not to compile. This example makes them all trivial to the point of uselessness. Shuttling it off miles away in an #include file, can frequently give the impression this than can be changed with no effect on anything else.

    --
    I can explanate how to administrate your network. You must configurate and segmentate it, so it can computate.
  2. Re:Who wrote that article? by Enselic · · Score: 4, Interesting

    I wonder what mushrooms he were on when he came up with that coding style... (yes, this is the actual indentation he used):

    Void change_score(short num_points)
    {
        if (num_points < 0)
    {
    // maybe some error message
            return;
    }

        score += num_points;

        if (num_points > 0)
    make_sparkles_on_score();
    }

  3. Re:That was just terrible... by Coryoth · · Score: 3, Interesting

    1.) Use test driven development I'll go you one better. Use specification driven development. That is, use a combination of contracts an unit tests. If your method has general constraints, or your object has an invariant, write it into the code using contracts (and ideally use a system that will let your subclasses inherit contracts, and allow contracts to be sucked up and included in the API documentation); if your methods specification is only easily expressed as a set of mappings from input to expected output, write a unit test instead. When you run your unit tests the contracts will automatically get tested too. Better yet, by using contracts you can help yourself on:

    2.) Write complete unit tests, including bad input by using the contracts as a test oracle and passing in randomly generated data to really flesh out the corner cases. In some cases you can do this in a purely automated fashion at the push of a button. Contracts also have the benefit of: (1) not requiring the biolerplate code of unit tests, so they're faster to write; (2) respecting inheritance which can save you a lot of extra test writing. You can't always easily write contracts for methods, and in those cases unit tests make sense, but you may as well take full advantage of contracts for the parts that can be handled in that manner.
  4. Re:That was just terrible... by swillden · · Score: 3, Interesting

    The real thing is to used named constants where it makes sense. #define is the crudest approximation of that, C can use enums, C++ can use "const" for compile-time values, etc.

    That was my thought, too. When writing C++, you should *avoid* #define like the plague. In fact, avoid using the preprocessor for anything except including (and guarding) headers and, occasionally, conditional compilation. One of the best things about enums is that they create not just values, but *types*. So, if you define:

    enum AlienCount { MAX_NUM_ALIENS = 20 };
    enum PointValue { POINT_VALUE_FOR_ALIEN = 10, POINT_VALUE_FOR_SPACESHIP = 30 };

    void givePlayerSomePoints(PointValue points);

    The compiler will barf if you accidentally type:

    givePlayerSomePoints(MAX_NUM_ALIENS)

    ... or something equally silly, but perhaps less obviously wrong.

    Smart C++ programmers find ways to get the compiler to point out their mistakes. One of the most powerful (and most clever) examples of this is in Barton and Nackman's book on C++ for scientists and engineers. They make use of templates to define types for representing physical values that not only have units attached, but which allow the compiler to statically check the units. Given:

    Mass m = 4 * kg;
    Acceleration g = 9.8 * meter / (second * second);
    Force f;
    f = m; // Generates a compile error!
    f = m * g; // No error here

    The compiler would take care of all of the unit checking at compile time, and, assuming we got rid of the erroneous line, generate machine code equivalent to:

    double m = 4;
    double g = 9.8;
    double f = 39.2; // No need to delay the multiplication to runtime.

    And if m or g aren't actually used except to calculate f, the compiler will optimize them away completely.

    I used the verbose version of their syntax, BTW. You can also write:

    Mass m(4);
    Acceleration g(9.8);
    Force f = m*g;

    which will apply default units to the numeric values. Of course, good code would also define a "const Acceleration g(9.8)" in a header somewhere, etc., rather than using numeric constants directly in the code, and it would use better variable names.

    Of course, such usage is well beyond the "Introductory" level of this article, but I think even an introductory article on C++ should recommend using enums to define constants, not #define. More advanced C++ users should devote a little time to writing classes that idiot-proof the code (because we're *all* idiots, at least some of the time), ideally without sacrificing performance.

    --
    Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.