Blog

Joe Useless Writes A Program: An Everyday Person’s Guide to Software Development

Writing computer programs to distribute is a process, but it can be a simple one. This article follows our hero Joe Useless on his journey from wanting a simple problem solved to giving his friends the answer in a program they can use over and over. This article is a work in progress, and helpful suggestions are welcome.


Step 1: Have a problem to solve.
(You can also think of this step as “Think of something you want to do.”)

Joe Useless has taken a job working as a clerk at ACME, and enjoys his job for the most part. But clerks in his department have to do a lot of something that Joe hates. They have to compare obscure lines of text, and his supervisor insists that there is no room for error.

Fortunately for Joe, ACME takes the enlightened approach of allowing him to run Python on his PC. “Whatever gets the job done right,” insists his supervisor.


Step 2: Find a way to do it at all.

Joe has used Python before and feels certain he remembers a simple way to do comparisons, so after spending a few minutes with the Library Reference, he turns on IDLE and tries out the cmp() built-in function:

>>> cmp('Harrelson, Adrienne', 'Harrelson, Adrianne')
1
>>>

It looks like this might do the trick for some of their more common and tedious comparisons. Joe gets into the habit of keeping IDLE running in the background to double-check some of his work for a while just to make sure.


Step 3: Tweak it until you have code that consistently does it the way you like.

This little trick works well enough that Joe finds he has largely automated the most annoying part of his job, to the envy of his co-workers. But Joe isn’t a Computer Scientist, and he finds that the “1/0/-1” values returned by cmp() leave him feeling nervous that he might make accidentally mistake “1” for “-1” and mess up the job. He doesn’t want to have to look up the meaning of the values cmp() returns, so he decides to write a function to dress-up the output.

>>> def compare(firstArg, secondArg):

    if cmp(firstArg, secondArg) == -1:
        print str(firstArg) + " is less than " + str(secondArg)

    elif cmp(firstArg, secondArg) == 0:
        print str(firstArg) + " is equal to " + str(secondArg)

    else:
        print str(firstArg) + " is greater than " + str(secondArg)

This is much better. Joe’s function takes the output from cmp() and displays the result in plain English (by clerk standards, anyway), like so:

>>> compare('Harrelson, Adrienne', 'Harrelson, Adrianne')
Harrelson, Adrienne is greater than Harrelson, Adrianne
>>>

Joe decided to use terms like “greater than” and “less than” in the program’s output, because this seemed like a familiar way of thinking about it, especially since the same function can be used to compare the values of numbers.

Step 4: Package it to be used repeatedly.

Joe’s co-workers are beginning to take notice now, especially since the management is becoming less tolerant of mistakes. Joe decides to make the function into a module that other workers can run on their own workstations. (By this point, Joe is also becoming something of a Python zealot and wants to see more people using it.) He adds a few lines of code to the text file where he keeps his comparison function, turning it into a program the clerks can start from the command line.

def compare(firstArg, secondArg):

    if cmp(firstArg, secondArg) == -1:
        print str(firstArg) + " is less than " + str(secondArg)

    elif cmp(firstArg, secondArg) == 0:
        print str(firstArg) + " is equal to " + str(secondArg)

    else:
        print str(firstArg) + " is greater than " + str(secondArg)

if __name__ == '__main__':
    import sys
    compare(sys.argv[1], sys.argv[2])

Joe was surprised to discover how little effort he had to put into making his handy little function into a full-fledged program. In Programming Python by Mark Lutz, he found out that if a Python script is run as a program, a built-in variable called “__name__” is assigned a special string called “__main__”, and that you can check for this with a simple “if” statement like the one he added. (He even thinks he half-way understands what this means!).

Now if his file is started from the command line as a program instead of imported into an interactive interpreter such as IDLE, the clerk who starts the program can enter the two strings needing to be compared after the program name. (This is sometimes referred to as “calling a program with arguments”. The first of the two strings entered is the first argument, which the program sees as sys.argv[1], and the second string is the second argument, or sys.argv[2].)


The two command-line argument strings are passed to the compare function in the last line of the program. So compare() starts up with sys.argv[1] as firstArg and sys.argv[2] as secondArg. It then calls cmp() and passes firstArg and secondArg to it, then prints a statement to the screen about how the two strings compared.

Step 5: Make it bullet-proof.

Joe’s fellow clerks keep making minor mistakes when running the program, and the department uses a lot of temporary workers. Joe doesn’t want to spend too much time showing people how to use the program, so he decides to have the program itself remind the user of the right way to use it when the most common mistakes are made.

def compare(firstArg, secondArg):

    if cmp(firstArg, secondArg) == -1:
        print str(firstArg) + " is less than " + str(secondArg)

    elif cmp(firstArg, secondArg) == 0:
        print str(firstArg) + " is equal to " + str(secondArg)

    else:
        print str(firstArg) + " is greater than " + str(secondArg)

if __name__ == '__main__':
    import sys
    if len(sys.argv) != 3:
        print '''********************\n
Usage suggestion:\n
python comparison.py argument1 argument2\n
\n
For example:\n
C:\Python22\python comparison.py "Jolie, Angelina" "Useless, Joe"\n
********************'''
    else:
        compare(sys.argv[1], sys.argv[2])

Now, if a user gives the program too many or too few arguments, the program suggests an example of correct usage instead of producing an error message. For example, if the user enters only one name to compare:

C:\Python22>python comparison.py "Stallman, Richard"
********************
Usage suggestion:
python comparison.py argument1 argument2


For example:
C:\Python22\python comparison.py "Jolie, Angelina" "Useless, Joe"
********************

Joe hopes that this will be enough of a reminder for people that he will only be have to spend a few minutes with them at first to train them in how to use the program meaningfully.

Step 6: If you haven’t already done it, comment your code.

Useless Joe’s supervisor is happy, as is the supervisor’s manager. The clerks are happy. And Joe wants this trend to continue, so he takes a little time to sit down and add comments to the source code of the program he has written. Even though this is a simple program, it would not make a lot of sense to someone who has never seen source code. If someone needs to change the code later (maybe even himself), he wants the code to look good and make sense without anyone having to waste much time figuring it out. Joe decides to add some comments describing what the different parts of the program are instead of describing every little technical detail. He also comments the date the program was last edited, so if the program is updated at some point, it will be easy to tell which version is in use on any given clerk’s PC.

#!/usr/bin/python
#
# comparison.py by Joe Useless for ACME clerks

# This is the function that does all the work.
# Arguments sent to the program are compared with the
# Python built-in function cmp()
def compare(firstArg, secondArg):

    # This if/elif/else block reformats cmp() output
    # so clerks can make out the meaning with fewer mistakes
    if cmp(firstArg, secondArg) == -1:
        print str(firstArg) + " is less than " + str(secondArg)

    elif cmp(firstArg, secondArg) == 0:
        print str(firstArg) + " is equal to " + str(secondArg)

    else:
        print str(firstArg) + " is greater than " + str(secondArg)

# This is the main method, which makes it possible to run the
# comparison as a top-level program instead of just by calling
# the compare function from within another program, such as
# a python interactive interpreter.
if __name__ == '__main__':
    import sys

    # If a clerk calls the program with the wrong number of
    # arguments, print an example of correct usage.
    if len(sys.argv) != 3:
        print '''********************\n
Usage suggestion:\n
python comparison.py argument1 argument2\n
\n
For example:\n
C:\Python22\python comparison.py "Jolie, Angelina" "Useless, Joe"\n
********************'''

    # If the clerk calls the program correctly, perform the
    # compare function with the arguments provided by the clerk.
    else:
        compare(sys.argv[1], sys.argv[2])

Now Joe Useless feels satisfied with the program. He feels the comments are okay for a program this small, and by putting his program in the hands of other clerks, he is beginning to get an idea of how the program can be improved some more.