CS 257: Software Design

Web application, stage 2: rudimentary UI and database interface

Now that you have chosen data to work with and written a first draft of your feature list, let's put together a skeleton prototype of the code infrastructure your application will use. The goals of this phase are:

  1. Set up skeleton code that controls the flow of information: user → browser → web server → web application → database, and back.
  2. Create a clean interface between the web application and the data source.

0. Some important tools

When you're working on a networked application, it's extremely handy to be comfortable with three basic tools:

If you take time now to learn to use SSH, SFTP, and a terminal-based editor, it will make your work on networked applications and other remote tasks smoother. There's no time like the present!

1. Setting up the skeleton

Since the user, the browser, and the web server (Apache running on cs-research1.mathcs.carleton.edu, for our purposes) already exist, setting up the code infrastructure requires only that you place your rudimentary web application and data in a place where Apache can get at them.

Follow these steps to get started.

2. The database interface

Your web application, whose entry point is webapp.py, will need to access your data to provide the desired services for people. Next week, we will get your PostgreSQL databases set up with your data. Regardless of the PostgreSQL details, in the meantime you're going to create a class to act as an interface between your main application code and the data. This is an important idea, so pay attention.

Suppose, for example, your data is federal election campaign finance data. Then you would create a file called datasource.py, containing a class more or less like this:

class DataSource:
    def __init__(self, ...):
        ...

    def getCandidateList(self):
        ''' Returns a list of the id numbers of all candidates in the
            campaign finance database '''

        # Implementation will eventually go here. In the
        # meantime, just return an object of the right type.

        return []

    def getContributionsForCandidate(self, candidateID):
        ''' What would the return type be here? A list of...what? '''
        ...
        return []

    etc.

The idea is that your application needs to ask certain idiosyncratic questions of your data. This class's methods will be designed to provide answers to those questions, regardless of where and how the data are stored. You could, for example, write one version of DataSource that assumes the data are stored in a CSV file, and another version that assumes the data are stored in a PostgreSQL database. By isolating the main application from the details of the data source, you get all sorts of great benefits, which you can undoubtedly imagine (and which we will discuss in detail in class next week).

Please think carefully about what methods this class should have, and what their signatures should be (i.e. names, parameter lists, and return values). Document these methods in detail in a comment below the "def" line before trying to implement them. Your documentation should succinctly explain the meaning and type of each parameter, the operation of the function, and the meaning and type of the return value. If the method might raise an exception, it's good to document the conditions under which that might happen as well.

As you can see in my example, I have prepared my DataSource class's methods as stubs. That is, they return empty lists or zero or whatever type of "nothing" is appropriate for the method in question. Alternatively, I could return dummy data by just hard-coding it in each stub's return statement.

4. What to hand in, and how

You will hand in your code by making sure http://thacker.mathcs.carleton.edu/cs257/yourusername/webapp.py presents a page with:

webapp.py contains one approach to linking to source files.