T B H P N

Design Concept - Top-Down Design

Build Application Language

Top-down design starts by decomposing project requirements into tasks, with an executive task that is responsible for meeting all requirements for the application. It uses a number of helper tasks that are each responsible for some partitioning of the requirements. Packages that grow out of top-down design are seldom reusable as they focus on meeting requirements for this specific application.

Tasks are the major steps an implementation must carry out to complete its mission. These usually involve assembling inputs, carrying out a number of computational steps, and displaying results. Each of these tasks are candidates to become packages.

We want each package to be cohesive, that is, focused on a single activity or a few intimately related activities. That means that the abstraction the package implements is simple, even if the processing within the package is not.

  1. Most designs start with a top-down phase since that makes us focus on meeting all the requirements of the application.
  2. Top-down design builds an application language that allows us to reason about the application and its affect on users.
  3. Usually there is an executive that creates essential objects and directs their activities to complete each task. The text of the executive should, by the choices of object names and their member function names, make it clear what is going on at each step. This makes understanding the design and carrying out maintenance activities easier than it might otherwise be.
  4. The text of all packages, developed during top-down design, describes application-side entities and actions, things that application users will care about, e.g., orders, invoices, payments, status, etc.
  5. For most interesting designs users supply information about the inputs on which the implementation acts. This may come from the command line, or from data entered on a form, or from XML encodings in a file. So there is often an input package responsible for acquiring information about what is to be processed and then acquiring references to those inputs, e.g., path of a file to load or lines of a file to interpret.
  6. As the implementation processes its input items there is often the need to store intermediate results for further analysis or transformation. For this, the design allocates one or more solution-side packages to define data structures for that storage. Their implementation follows the bottom-up strategy, discussed in Design Note #6.
  7. Once data structures are available, packages are defined to fill them and to interpret their contents. This may happen in several passes, e.g., Some data is extracted from the inputs and stored, then that is processed, perhaps in conjunction with processing of additional inputs, then the final outputs are generated. These packages, their classes, and member functions should all have names that help a reader understand what is happening at each stage.
  8. Finally, the results need to be presented to a user in some meaningful way. It's important that the design is carried out so as to provide the user with information, not just data. That is, the output package(s) need to define categories of output, label them, and add any commentary necessary for the user to understand what the implementation produces.
  9. One sensible way to orchestrate all this is to:
    • think about the high level tasks, create an initially empty or sparse package for each. Then add enough functionality and placeholders so you can see how the implementation will operate, e.g., you get it up and cycling, perhaps just enumerating each task: "assembling inputs", "building tables", "assembling outputs", and "displaying outputs".
    • Then you add code to assemble and display inputs, build that and run to see that it works.
    • You continue on with each succeeding task filling in code with temporary display so you can see that everything appears to work.
    • When you believe that everything is working in accord with the design, you remove the temporary outputs and have a working implementation.
  10. It is rare that we complete a design with a top-down process. After defining application-side responsibilities of the executive and a layer or two of its helpers we can't see clearly how to proceed to lower level package definitions.
  11. When the top-down process stalls because we don't know what to do next, we select a package and begin a bottom-up design for that package.
  12. The bottom-up process deals with things the user should not have to know about. Things that simply support each of the activities of the application side. We think of the packages that result from bottom-up design as the solution-side of the implementation.
  13. If we do a good job partitioning new code into application-side and solution-side packages, our reusable code base grows as the business executes its project activities. This allows us to progressively implement projects with fewer new packages as the solution-side disappears into libraries and archives of existing code resources.

Conclusions for Top-Down Design:

Start a design by enumerating all major obligations of the application and:
  1. Configure obligations into tasks. Each task becomes a candidate application-side package.
  2. The first "Executive" task is responsible for all obligations and it carries them out with the help of lower-level tasks.
  3. The text of each task-based package should make clear its responsiblities and actions.
  4. You then start implementing small parts of a package, building many times as you proceed, to make sure that what you've done so far works as you intend. Build small and often with enough testing to make you confident that what you've implemented works.
  5. You may discover that as you begin implementating a package there are package tasks that could or should be implemented as lower level packages, so the process becomes recursive.
  6. Also, on rare occasions, you will find that the processing in a package is so small and simple that you may decide to merge that with some other related package. Do this only if the merger results in a cohesive package.
  7. Eventually this process may stall, and we then turn to bottom-up design to build solution-side packages.
We will start this process in class for the first couple of projects so you can see how this is done.

CST strip