7401ICT: Web application development


(Under construction)

These notes are based in part on my more detailed 2503ICT Web Programming notes.

Summary

Requirements analysis depends on the context:

Design: Textual interface design, graphical interaction design using transition diagrams.

Implementation: URL design, model design, view design, template design, form design.

Software engineering: prepare for modification and extension.

Initial notes

First, recognise that the best Web applications are personalised (page views are tailored to individual users), collaborative (users provide much of the content), and community-based (users with common interests may collaborate independently of other users).

Second, recognise that for any Web application to survive, it will need to be modified and extended continually over time. The ability to do this requires planning in the design and implementation stages.

Third, almost no-one is good at organisational analysis, programming and graphics design, so Web application development must be a team effort.

Design (the "hard" part)

Implemention (the "easy" part)

Transition diagrams

Transitions diagrams (sometimes called interaction diagrams) are important for both specification and design. A transition diagram is a directed graph with annotations on (some) edges. The nodes of the diagram describe page views and actions (that do not correspond to page views) in the application. Nodes should be labelled by verbs, e.g., show all users, enter new user details, add new user. The edges describe transitions between nodes. The start or home node should be identified.

Transition diagrams are important for specification. Developers can use a diagram to check that all requirements have been considered and that all required transactions have been identified, and that all transitions are appropriate.

A transition diagram may be implemented (using Django) either (1) with a separate view for each node or (2) by a single (large) view (with parameters) that implements all nodes. Each approach has its pros and cons, but personally I find an implementation with many small views easier to manage. To support the design, nodes may be annotated with their URL pattern (and corresponding view). Edges may be annotated with the variables whose values are passed in the corresponding page transition. Other annotations may also be useful. Developers can use the annotated diagram as a guide to the actual implementation.

If a template system is used, a separate template file will probably be associated with each page view in the diagram.

It's important to distinguish between nodes that describe page views and nodes that describe actions only. Django views that implement action nodes must perform an HTTP redirection after each database update to avoid the reload-redo problem.

Examples of transition diagrams are shown below.

Transition diagram examples

You can read more about these examples in the 2503ICT Web Programming lectures.

  1. Guestbook
  2. Discussion forum
  3. Library
  4. Online banking

Obviously, these examples have not (yet) been adapted to a Django context.

User interface design

See the 2503ICT Web Programming lectures for some basic principles of user interface design and implementation.

Implementation notes

(These notes did not need to be changed much in adapting them from PHP to Django.)

Testing

Python (and hence Django) provides a powerful framework for writing and running unit tests. See Testing Django applications.

The advantage of writing a comprehensive suite of unit tests for each app is that the tests can easily be run as a group after every change to the app to ensure that the app still behaves as required. It is normal to write one or more unit tests for each view in an app.

The file tests.py created in each app includes a very simple unit test example.

The Django testing framework allows developers to perform the following tests in each project:

Other "in-browser" test frameworks such as Twill and Selenium must be use to test rendered HTML and the behaviour (using JavaScript) of Web pages.

Django tests are performed on a temporary database (not the working database), which can easily be populated with initial data stored in an app's fixtures directory.

An initial set of unit tests are provided in the files entries/tests.py of the initial guestbook application and items/tests.py of the list-detail application. Both applications use fixtures for initialising the database (for production and testing).

One test case in the file items/tests.py is the following.

from django.test import TestCase

# Assumes the database contains an item with id=1 and title="Catch 22".

class DetailTest(TestCase):
    def test_detail(self):
        """Tests that get requests for the URL /items/n/ behave correctly."""
        response = self.client.get('/items/1/')
        self.assertTemplateUsed(response, 'detail.html')
        self.assertEqual(response.status_code, 200)
	item = response.context['item']
        self.assertEqual(item.id, 1)
        self.assertEqual(item.title, "Catch 22")
        self.assertTrue(len(response.content) > 0)

Generally, it seems to be convenient to write a test case for each URL pattern. See Assertions for a useful list of tests that can be performed.

To be extended...?

General debugging notes

Suggestions for design, implementation, testing and debugging techniques are invited.