CIT 591: Tips for Good Programming
Fall 2012, David Matuszek

Functions should be short and single-purpose

Short, single-purpose functions are easier to write, easier to test, easier to debug, and easier to reuse.

To give you some idea of what is meant by "short": I counted lines and functions in a previous weekly assignment that I wrote. It had 13 functions. The average length of a function, not counting comments, was 5.23 lines. The two longest functions were each 14 lines, so most of the functions were 5 lines or fewer.

If you have a function that works and does something useful, don't add more code to it; write another function.

Use Test-Driven Design

Seriously. It works.

Make an initial guess as to what functions you will need (you can add and discard functions later). Write a test for the most basic function, one that doesn't depend on anything else. Then get that function working. Do this for the most basic functions. Avoid writing functions or tests that depend on other, untested functions. Work your way up to the top-level functions.

For example, suppose you have a program that is supposed to do something with a string, and in that string you have to ignore whitespace, punctuation, digits, and everything but letters. Why not write a function that takes any string and returns a string containing only the letters from the given string? It's really easy to write a test for this function. Then you can write the function. Then you can go on to another function. You won't be tempted to "bury" the code for deleting non-alphabetic characters in some big function to create the code array.

One of the really nice things about TDD is that it lets you make steady, continuous progress. The next time you spend an hour trying to debug a 25-line function, think about this.

Here's a really short summary of TDD you should look at.

Avoid magic numbers

A magic number is a number that occurs in your program without any obvious meaning. Seriously, are you going to remember next week why you are comparing against 97? If someone else looks at your program, will they know? It's really easy to assign the number to a meaningfully named variable, and use that variable in your program.

It's pretty much always okay to use the numbers 0 and 1. A chessboard is 8 by 8, and if you're writing a chess program, probably using the number 8 directly in your program is okay--unless it's being used for some other purpose, when the 8 will be exceptionally confusing.

For example: If you really need the ASCII value of a character, don't look it up and use that value in your program. Use ord('a') instead of 97.

Programming hints

Communicate with your partner! Email, instant messaging, phone calls, whatever. Sitting together at one computer is best, but I realize you can't always do that. Come as close as you can.

Also, remember that the best way to learn is to teach.

The more you can rely on built-in methods, like lower() and isalpha(), the less code you have to write and debug. The Python Standard Library is your friend.

You can pass as many parameters as you like into a function, but a function can only return one value. Right? Right. But that value can be a tuple! For example,

    def chopTwoCharacters(message):
        return (message[:2], message[2:])
This can be called as
    (twoLetters, restOfMessage) = chopTwoCharacters(message)
or even as
    twoLetters, restOfMessage = chopTwoCharacters(message)

This is a very useful feature in Python!

Here's a Really Bad Idea: One partner writes the tests and the other partner writes the functions. I know this is a bad idea because some of my past students have tried it, and it was a disaster. Besides, it completely negates the value of TDD.

Do not make a last-minute change to your program--not even adding a comment!--just before you submit it. If you change even a single character, test it again before you submit it.