Week 7: Top down design, File I/O, and CSV files

Week 7 Goals

  • Learn to read data from files

  • Learn Top Down Design

  • Learn how to write function stub

  • Learn how implement a design bottom-up

Get Week 7 In-class Code

To copy over the week 7 in-class example programs, do the following (If you have trouble with either of these steps, ask a Ninja or your professor for help):

  1. Create a w07-tdd subdirectory in your cs21/inclass directory, and cd into it:

    $ cd ~/cs21/inclass
    $ mkdir w07-tdd
    $ cd w07-tdd
    $ pwd
    /home/yourusername/cs21/inclass/w07-tdd
  2. Copy over the week 7 files into your w07-tdd subdirectory (check that they copied successfully copied by running ls:

    $ cp ~admin21/public/w07-tdd/* ./
    $ ls
    catfile.py design_wheel.py  german.csv  spanish.csv design_flashcards.py  french.csv       names.txt

Week 7 Code

  • catfile.py: Basic File I/O, open, strip, close

  • design_flashcards.py: Practice with top-down design

  • design_wheel.py: more TDD practice

Top Down Design

One of the primary topics in this class is Top Down Design (TDD), a problem solving technique that computer scientists use to solve larger problems. It is a technique that is done before coding where we:

  • Start with general description of problem

  • Break it into several high-level steps

  • Iteratively break the steps into smaller steps until you have steps that are easier to solve

Top-down design is a lot like creating a paper outline for a large paper where you start with the main sections, and iteratively refine each part with more and more detail until you are ready to start writing the paper.

When you use top-down design, your resulting program’s structure will match the above idea of an outline: the main function should have calls to a few high-level functions, one for each high-level step; high-level functions have calls to medium-level functions that implement sub-steps of the high-level steps; and so on.

Iterative Refinement

When writing a large program, programmers use iterative refinement: do some top-down design, write function stubs for this part of code and maybe some implementation, then test. Iteratively, add more functions to accomplish sub-problems, and perhaps refine some of the steps using top-down design, and test, and so on. The idea is to write some code, test it, then write a little more code, and test it before writing even more. Usually, I write a function, then test it, write another function, test it, …​ This way if I’m careful about testing, I know that if there is a bug in my program it is with the new code I’ve just added.

Function Prototyping

We often use prototyping to just put in function stubs so we can test the whole program’s flow of control without having to have a full implementation. For example, here is a stub for a function to compute square root (it doesn’t actually do anything related to the task, but we can call it from other parts of our program to see if the program’s flow matches the design):

def main():

    # a sample call to our function to see if it works
    test = squareRoot(16)

    # for now, the program doesn't crash, but returns an incorrect result
    # of the correct type. We can now go back an refine our function
    print("Answer is: %.2f " % (test))

def squareRoot(num):
    """
    This function computes the square root of a number.
      num: the number
      returns: the square root of num
    """

    print("inside squareRoot")

    # TODO: implement this function

    return 1  # a bogus return value, but it lets me run the program
              # and make calls to this function stub to "see" program flow

main()