What makes a program “good?”

What makes a program “good?”

We started the class by asking “What makes a program good?” Some answers students came up with:

  • readability
  • organization
  • performance

This semester, we’ll learn how to write programs that are “better” in all of these ways. This lecture introduces two of them: organization and performance.

Margaret Hamilton, Software Engineering, and the Moon

Margaret Hamilton was the Director of the Software Engineering Division at MIT’s Draper Laboratory in the ’60s. Among other things, she was in charge of the team that developed the in-flight software that ran on the Apollo 11 mission, which took humans to the Moon. She was also one of the inventors of the term “software engineering.” More on that in a second.

How many lines of code would you guess were in the Apollo in-flight system? The answer is about 145,000.

In CSCI 0111, you mostly wrote programs that were less than 100 lines of code or so (usually much less). When writing a program of that size, you might be able to hold the whole thing in your head at once–the whole thing might even fit on your screen! When you’re writing 145,000 lines of code, that’s probably not possible. The Apollo 11 team had to be able to think about particular pieces of code in isolation, without worrying about the details of other parts of the code. Software engineering is the study of building reliable software, and techniques for developing components in isolation are its bread and butter. An example of this kind of technique: functions! When you write a function that does some particular task, the code you write that calls that function doesn’t need to worry about the function’s body. We’ll be learning several other such techniques in this course.

By the way, here’s a chunk of the Apollo 11 code I grabbed at random (the source code is available here):

SETWO           TC      WOZERO          # GO SET WORD ORDER CODE TO ZERO.
        +1      CA      DNECADR         # RELOAD A WITH THE DNADR.
        +2      AD      MINB1314        # IS THIS A REGULAR DNADR?
                EXTEND
                BZMF    FETCH2WD        # YES.  (A MUST NEVER BE ZERO)
                AD      MINB12          # NO.  IS IT A POINTER (DNPTR) OR A
                EXTEND                  #       CHANNEL(DNCHAN)
                BZMF    DODNPTR         # IT'S A POINTER.  (A MUST NEVER BE ZERO)

DODNCHAN        TC      6               # (EXECUTED AS EXTEND)  IT'S A CHANNEL
                INDEX   DNECADR
                INDEX   0       -4000   # (EXECUTED AS READ)
                TS      L
                TC      6               # (EXECUTED AS EXTEND)
                INDEX   DNECADR
                INDEX   0       -4001   # (EXECUTED AS READ)
                TS      DNECADR         # SET DNECADR
                CA      NEGONE          #       TO MINUS
                XCH     DNECADR         #               WHILE PRESERVING A.
                TCF     DNTMEXIT        # GO SEND CHANNELS

What do we notice about this code? A couple of the things I noticed:

  • Almost every line of code has a comment explaining what it’s doing! (The comments are the bits after the # on each line)
  • Nevertheless, the code is pretty hard to read. It’s written in a very old, very low-level programming language called AGC assembly language.

Luckily, in this class you’ll be working in Python, not AGC assembly language. Python has built-in support for the kinds of software engineering techniques and concepts we’ll learn in the course (like functions!). I want to emphasize, however, that clean code with well-isolated components can be written in any programming language!

As an aside: Apollo 11 had 145,000 lines of code. Google has about 2 billion lines of code. Part of what makes that possible is that Google’s code is mostly written in languages like Python, not in AGC assembly language.

Program performance

Another topic we’ll visit and re-visit in CSCI 0112 is analyzing how fast our programs run. On one level, this is easy–just run your program while looking at your watch! That kind of performance analysis (sometimes called benchmarking) is useful, and it’s often an important step in testing a program. It does have its limitations, though. Programs run at different speeds on different computers (for instance, the computer that ran the Apollo 11 code above was about 60,000 times slower than the computer in my cell phone). Programs also take different amounts of time depending on the data they are processing–think about writing a program to find duplicate elements in a list and then running it on [1, 2, 3, 4] vs. running it on every word from every article on Wikipedia.

To see why this is hard, let’s take a look at these two (admittedly strange) Python programs:

def strange_function_one(l: list):
    total = 0
    for x in l:
        total += x
    for x in l:
        total += x
    for x in l:
        total += x
    for x in l:
        total += x
    for x in l:
        total += x
    for x in l:
        total += x
    for x in l:
        total += x
    for x in l:
        total += x

def strange_function_two(l: list):
    total = 0
    for x in l:
        for x in l:
            total += x
            total += x

Which of these is faster?

We can simulate the “look at your watch” approach in Python like this. The timeit.timeit function will print the time it takes to execute the code one million times:

>>> timeit('strange_function_one([1,2,3])', globals=globals())
0.9604734549999989
>>> timeit('strange_function_two([1,2,3])', globals=globals())
0.6956890860000158
>>> timeit('strange_function_one([1,2,3,4,5,6])', globals=globals())
1.632538684999986
>>> timeit('strange_function_two([1,2,3,4,5,6])', globals=globals())
2.024607646999982

It looks like the runtime depends on the data that are passed in!

Later in the class we’re going to develop a way to reason about the runtime of programs without having to look at our watches. We’ll learn that in a meaningful way, strange_function_one is faster than strange_program_two, and will learn how to describe this distinction.

Logistics

For now, the big thing is to check out the course website. There’s a lot of information there about course policies, plans for assignments, etc. If you have any questions, please email Doug.