Bad Code Examples Promote Bad Habits


Image source: http://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Ugly.svg/120px-Ugly.svg.png

Why is there so much bad code? Developers offer myriad excuses:

  • We just have to ship (i.e. we don’t have enough time to do it right).
  • We disagree as to what “bad” is.
  • We know the code is not clean but we don’t think that it’s a real problem (i.e. we don’t care).
  • The existing design makes it tough to do the right thing.
  • We don’t have enough tests to clean the code up safely (“if it ain’t broke don’t fix it”).

Missing from that list is inadequate education. Most programmers learn from looking at other peoples’ code–whether in delivered systems, open source, internet examples, or book examples. A quick probe of the beginner’s forum at JavaRanch demonstrates how horribly constructed novice programs can get. Many novices simply won’t know better–they copy working code snippets from elsewhere and modify it to their needs.

Let’s shift at least part of the blame where it belongs–to the author of the bad code that the novice copied. Most beginning programming language tutorials and books don’t discuss or teach proper design. Examples frequently demonstrate rampant duplication, intertwining of console output with business logic, clever constructs, and cryptic naming.

Even authors who should know better present examples with severe design flaws. They could at least caveat them (“cleaning up the obvious duplication in this example is an exercise left to the reader”). The better solution would be to find a way to code it properly and not show the bad code at all.

I’ve been working through examples in a couple Erlang books. Here’s a paraphrasing of one unfortunate theme presented in both:

loop() ->
    receive
        {Client, "smelt"} ->
            Client ! "a small silvery fish",
            loop();
        {Client, "agile"} ->
            Client ! "lithe",
            loop();
        {Client, "lean"} ->
            Client ! "trim",
            loop();
        {Client, _} ->
            Client ! "no definition found",
            loop()
     end.

You don’t have to know Erlang to see the obvious duplication in this short example. Sure, it’s just an example, designed to show a construct, don’t worry about the design, yadda yadda. Yet it’s at the heart of why most of our code sucks. I know little about Erlang so far, but it sure makes a lot more sense to separate handling a server request from domain logic:

loop() ->
   receive
      {Client, Word} ->
           Client ! definition(Word),
           loop()
 end.

(If we’ve gotten far enough to learn about spawning processes, we’ve certainly learned how to build a clean definition function.) By presenting it properly, the duplication gets eliminated, and the example may more readily suggest that the server loop is a potentially reusable construct, or at least a common idiom.

By presenting it poorly, I can bet you a large amount of Erlang code out there is similarly difficult.

Why allow beginners to learn poor coding practice, then have to re-train them?

Atom