CS 228 meeting -*- Outline -*- * top down design (HR 1.3) ** context using a computer to solve a problem can be thought of as follows (for small to medium sized problems, when change isn't too important) ---------------------- STEPS IN WRITING A PROGRAM 1. Decide what is to be done (requirements) 2. Design a program to do that (specification) 3. Implement the design (development or coding) 4. Validate the implementation (testing and verification) ---------------------- in this section we'll study the design process most important is requirements ** stepwise refinement note: this section is presented top-down (examples follow) ------------------------------ DESIGN STRATEGIES def: a *top-down design* proceeds by breaking a large problem into smaller ones, each of which is again broken down until each bit is easy to code. --------------------- note it's recursive --------------------- def: *stepwise refinement* involves concentrating on one subproblem at a time. SLOGANS: Divide and conquer. Separate concerns. Postpone details. Don't keep everything in your head at once. Debug at each level of refinement. ------------------------------ *** example (HR pp. 37-46) --------------------------- EXAMPLE PROBLEM Sort up to 100 integer inputs in ascending order. ---------------------------- **** requirements ---------------------------- REQUIREMENTS ANALYSIS --------------------------- Q: Where do the inputs come from? let's make it standard input (cin) Q: Where to place the answer? let's make it standard output (cout) Q: What if less than 100 values? How does input end? let's use EOF, also stop input when get 100 (no error) Q: Should we prompt? yes Q: Anything else? maybe.. SNAPSHOT 0 // selsort.C int main() // MODIFIES: cin, cout // POST: cout has a prompt written to it, // and cin has up to 100 integers read from it (up to EOF, or the 100th) // and cout has the integers written to it in ascending order. { } **** top-level design edit a file with these in it (as comments) talk through the steps, noting this is a pretty common outline also draw a hierarchy (structure) chart showing the functions SNAPSHOT 1 // selsort.C int main() // MODIFIES: cin, cout // POST: cout has a prompt written to it, // and cin has up to 100 integers read from it (up to EOF, or the 100th) // and cout has the integers written to it in ascending order. { // prompt user // input the data // sort the data // output the data } Q: how shall we store the data? use an array (of 100 elements) for debugging at each level of refinement Q: does that seem to work? **** first refinement we already have a prompt function, to refine these steps, we'll make the other steps into functions first add the prompt, then start to call InputVec, then decide what to pass it, then call Sort, note need to pass number of items (say why) then OutputVec then add the header includes then return 0 (a detail) SNAPSHOT 2 // selsort.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include "prompt.h" #include "IOVec.h" #include "Sort.h" int main() // MODIFIES: cin, cout // POST: cout has a prompt written to it, // and cin has up to 100 integers read from it (up to EOF, or the 100th) // and cout has the integers written to it in ascending order. { // prompt user prompt("This program sorts up to 100 input integers.\n" "Use end-of-file to terminate the input early.\n" "\n" "Begin input:\n"); int vec[100]; // input data int numItems; // number of items input // input the data InputVec(vec, numItems, 100); // sort the data Sort(vec, numItems); // output the data OutputVec(vec, numItems); return 0; } improvement: don't have 100 scattered throughout the code redundacies make it hard to change. note: use const, note change to prompting. ///////////////////////////// SNAPSHOT 3 // selsort.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include #include "prompt.h" #include "IOVec.h" #include "Sort.h" const int MAX = 100; int main() // MODIFIES: cin, cout // POST: cout has a prompt written to it, // and cin has up to MAX integers read from it (up to EOF, or the MAXth) // and cout has the integers written to it in ascending order. { // prompt user cout << "This program sorts up to " << MAX << " input integers.\n"; prompt("Use end-of-file to terminate the input early.\n" "\n" "Begin input:\n"); int vec[MAX]; // input data int numItems; // number of items input // input the data InputVec(vec, numItems, MAX); // sort the data Sort(vec, numItems); // output the data OutputVec(vec, numItems); return 0; } **** recording design decisions about helping functions SNAPSHOT 4 // IOVec.h // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 extern void InputVec( int vec[], int& size, int max ); // PRE: max >= 0 // MODIFIES: cin, size // POST: 0 <= size <= max, size integers have been read from cin, and // for each 0 <= i < size, vec[i] contains the (i+1)th value read from cin. extern void OutputVec( const int vec[], int size ); // PRE: 0 <= size // MODIFIES: cout // POST: for each 0 <= i < size, vec[i] is added to cout followed by // a newline, and if i+1 < size, then vec[i] preceeds vec[i+1] ///////////////////////////////////////////// // Sort.h // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 extern void Sort( int vec[], int size ); // PRE: 0 <= size // MODIFIES: vec[i], for each i // POST: vec[0..size-1] contains the same values // as vec[0..size-1], and vec[0..size-1] is in ascending order **** top-down testing (using stubs) instead of implementing the helping functions, test the logic by using stubs for them. Mention the idea of code coverage: want tests to exercise all code. SNAPSHOT 3 // IOVec.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include void InputVec( int vec[], int& size, int max ) { // ****** STUB ******** cout << "*** InputVec routine entered ***\n"; size = 3; vec[0] = 25; vec[1] = 10; vec[2] = 30; } void OutputVec( const int vec[], int size ) { // ****** STUB ******** cout << "*** OutputVec routine entered ***\n"; cout << vec[0] << '\n'; cout << vec[1] << '\n'; cout << vec[2] << '\n'; } // Sort.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include #include "swap.h" void Sort( int vec[], int size ) { // ****** STUB ******** cout << "*** Sort routine entered ***\n"; swap(vec[0], vec[1]); } **** refinement steps for each function at this point, refine each function. Q: can you write InputVec and OutputVec? note: declaring i in OutputVec outside the loop so can refer to it in asserstions void OutputVec( const int vec[], int size ) { int i; // INV: vec[0..i-1] have been output && i <= size for (i = 0; i < size; i++) { cout << vec[i] << '\n'; } // ASSERT: i >= size && vec[0..i-1] have been output && i <= size /* hence */ // ASSERT: vec[0..size-1] have been output } void InputVec( int vec[], int& size, int max ) { int i = 0; // INV: vec[0..i-1] have been read from cin && i <= max while (i < max && cin) { cin >> vec[i]; i += 1; } // ASSERT: not(i < max && cin) // && vec[0..i-1] have been read from cin && i <= max /* hence */ // ASSERT: either i <= max or cin is at EOF // && vec[0..i-1] have been read from cin size = i-1; } Tell them to see the book for selection sort. *** exercise (if time) Have students do a first-cut design on some problem.