Concepts in Computing
CS4 - Winter 2007
Instructor: Fabio Pellacini

Lecture 12: Programs

Example:sorting

Writing complex web sites and programs takes more than knowledge of HTML and JavaScript; you also need to understand how to organize your code so that you can keep track of what needs to be done, and fix any problems which may occur. The topic of "software engineering" is a big and important one (to avoid serious software bugs). The following is just some discussion from one point of view about the process.

Designing a complex program consists of the following steps:

  1. Specification: Say what the program should do.
  2. Design: Figure out how the program will operate.
  3. Implementation: Write the code.
  4. Testing: Make sure the program works as specified.
  5. Debugging: Fix "bugs" (errors) in the code.

In a typical project, these steps are repeated over and over again until you are satisfied (or until you run out of time). Part of the engineering reality of program design is that you often don't have as much time as you would like to make everything perfect.

Specification

The specification is usually provided by the eventual user of your program. In the case of CS 4 homework assignments, that's me, as the instructor. In general, you may think up programs you want for yourself, or you might build them for other people. In either case, it is important to write down what the program should do, both in general terms and specific terms. Initially, the specification may be a bit vague, and you may need to do a little design, implementation, and testing to help figure out what exactly it is you want to do (or someone wants you to do). This results in iterative, incremental "loops" of software development.

Design

Once you know what the program should do, your next task is to figure out how you will do it. This includes questions like:

  • How will the interface look?
  • How does the user operate the program?
  • How will the program take input from the user, and how will it give output to the user?
  • What will happen in case of errors (e.g., bad input)?

Sometimes, the design is constrained by the specification -- for instance, the homeworks have had specific requirements as to how pages should look and what they should do. But the design should be as complete as possible, even where the specification is silent.

A good technique for design is to make simple mock-ups, either in HTML or as sketches on paper, of how the final result will look.

Try to design programs "from the top down". In other words, design the big pieces first, before focusing on the small details. This helps you keep your eye on the ball, and not lose track of the big picture.

Design is also where you should start thinking about how your code will be organized: What functions do you need? What kinds of data do you need to remember? What variables will you need? Give names to each of the functions and variables you will eventually want to write. That way, you will not lose track of what you called something.

Implementation

Once you have designed your program, you can start to build it. If you have designed it carefully, you should have a kind of an outline as to what has to be written, and how it all fits together.

For HTML and JavaScript pages, I recommend you do things in this order:

  1. Write the HTML and any CSS you need to make the site look as you want it to. As you are doing this, include any form and input tags you will need to implement the rest of the program, and give them suitable names and values, but do not yet worry about attaching any code to them.
  2. Write any "generic" JavaScript functions you will need, to do the various tasks your program requires. For instance, if you need a function to find all the checked checkboxes in a form, you should write that first.
  3. Finally, write any "program-specific" functions and code you will need, such as onClick to handle button presses in your input tags.

Two important principles: modularity and incremental development. Do not write everything all at once. Break it into bite-sized pieces, and work on them in relative isolation. Test as you go along. This makes it much easier to find problems when they occur.

If, as you are writing code, you suddenly remember something you have to do later, write it down. You can always look at your notes again once you are finished.

Code libraries and APIs

Regardless of the complexity of your program, you should write all the code yourself. For many problems, there are free implementation available that you can use. These collections of implementations are often called libraries or APIs, that stands for "application programming interfaces". While there are differences between APIs and code libraries, for the purpose of this course we'll simply assume that they are mostly equivalent, but APIs are a bit more rigorous code libraries

In many cases, APIs are part of the language itself. For example, we have seen and used the DOM which is an API to read and write values of a webpage from the Javascript language. Other APIs or code libraries exists for sorting numbers, searching arrays, writing to computer disk, looking up a webpage from the web. Other examples of functions we used from the Javascript API are alert and events that are implemented in the API.

Overall, you should remember that it would be impossible to write programs of any size without using APIs. Think for example how powerful the command alert. It performs a ton of really complex operations, such as open a window, printing text into it in the right location, giving you a button that when click closes the window. For you, this is all but one simple function!

APIs and modularity go together. In writing large programs, you'll often see that you'll start writing "biulding" blocks (either youeself or throught an API/library) that you "assemble" together in more complex things. Breaking up your code in simple function is one way to achieve this. The more your library grows, the quicker it will take you to write new programs. This is very reasons why languages, like Javascript, offer you APIs directly. Without them you simply would not even start.

Other than the DOM we already saw, here are a few more examples of APIs or libraries using them:

Debugging

It is a sad fact that virtually no code is ever right the first time it is written. The art of locating and removing errors from computer programs is called "debugging".

There is no magic formula for how to debug programs, however, there are several common techniques that are helpful. I like to look at debugging as consisting of five stages:

  1. Identify the bug ("What's wrong?")
  2. Characterize the bug ("When does it happen, and what happens?")
  3. Localize the bug ("Where is the error?")
  4. Fix the bug
  5. Verify your fix ("How do I know it's gone?")

Localizing bugs is sometimes the hardest step -- once you know what is wrong, you have to find where in the code is causing the trouble. A few useful techniques include:

  • Output: Use the built-in alert() function to display a message about the state of the program. Make sure the state is what you think it should be.
  • Isolate: Write a simple test page that isolates the suspect code. If your code is modular, you can pluck out just a chunk of code, and focus on making it work correctly, independent of everything else that's going on.
  • Console: Use the "JavaScript console" to get diagnostic messages. (There is also a "JavaScript debugger", which has even more firepower, but I won't be covering that.)

Good incremental development practices make it much easier to isolate and remove bugs from programs, but there is no silver bullet.