CS 210 – Fundamentals of Programming I An Analysis and Design Style Guideline The purpose of the analysis and design is to outline a program before it is implemented. There are several reasons why this required. First, spending time writing out the analysis and design can greatly decrease the time it takes to implement a solution to a problem. The programmer is able to concentrate on what needs to be done to solve the problem rather than on the intricacies of the compiler or the syntax of the language of implementation. Second, often the person who designs the program is not the person who implements the program. As such, the analysis and design clearly documents what is needed to solve the problem without using code­specific jargon that the programmer may not be familiar with. In some cases, the implementation language is chosen after the analysis and design is completed. For this course, the analysis and design phase functions primarily as specifications for assignments and documentation of the student's design efforts on assignments. As such, the instructor uses a formal notation when specifying programs, but the student is to embedded their analysis and design in the comments as shown. An analysis describes the data objects needed to solve the problem. It includes a description of the object, its type, whether it is a constant or a variable, and its name in the program. The analysis corresponds to the variable and constant declarations of a program. The analysis also describes the interfaces (the types of the argument and returned objects) of the functions used in the program (called function prototypes in C++), as well as the variables and constants that must be declared within the function. A design is the "outline" of the computational steps. It is often used synonymously with the term algorithm. There is a design for each function in a program as well as the main program itself. When implementing a function, the design corresponds to the executable statements needed to compute the result. The analysis and design format in this document is a shortened and modified version of the Object­Centered Design approach used in Adams, Leestma, and Nyhoff, C++: An Introduction to Computing, 2/e. Analysis for Main Programs and Functions The main purpose of the analysis is to specify the objects that the program uses. Objects are data items that have values. They usually correspond to the nouns in the problem statement. For each object, we need to specify a description (what it is), its type (the class of values it might be), how its value is obtained or transmitted (its movement), and perhaps a name. Movement specifications include: ● ● ● ● ● ● ● input ­ value obtained outside the program from the user or a file output ­ value displayed to the user or written to a file received ­ value passed into a function passed back ­ value transmitted out of a function via an argument returned ­ value transmitted out of a function via a return computed ­ value computed locally (i.e., no movement). constant ­ value is a constant 09/01/2011 Page 1 of 8 D. Hwang Objects may "move" in more than one way. For example, a function argument could be both received and passed back when a function both uses its passed in value and changes it for transmission back to the caller. Another example would be a function that outputs results that are passed into it. In this case, the result objects are both received and output. There should an analysis for the main program, and each subprogram (function). Formally, analysis in in the form of a table. For the main program all objects are constant, input, output, or computed even if the actual input or output happens in a function. Most constants should be listed in the main program analysis unless they are being defined in a library. For example, an analysis for a main program that computes the area of two circles given their radii might look like: Objects Type Movement Name Mathematical p (3.14159) double constant PI Radius of first circle double input radius1 Radius of second circle double input radius2 Area of first circle double output area1 Area of second circle double output area2 The corresponding implementation comments would look like: #define PI 3.14159 int main () { double radius1, radius2, area1, area2; ... } /* Mathematical constant */ /* /* /* /* Input - radius of first circle Input - radius of second circle Output - area of first circle Output - area of second circle */ */ */ */ For a function analysis the order of the received arguments in the analysis is the order expected in the implementation. An analysis for the function that actually computes the area of a circle might look like: Objects Type Movement Name Radius of a circle double received radius Area of a circle double returned area The corresponding implementation comments would look like: double compute_circle_area (double radius) /* REC'D: radius of circle { double area; /* RET'D - area of a circle */ ... } 09/01/2011 Page 2 of 8 D. Hwang Design for Main Programs and Functions A design should list the main steps needed to solve the problem at hand. The steps should be numbered and the substeps should be subnumbered. Each step should be explained in the language of the problem. For the main function, this means that the steps are in the language of the original problem statement. For other functions, the steps are in the language of the subproblem being solved which is at a more detailed level than at the main program level. That is, we start describing how to compute the data item in question. But at the same time, if at this level, a step is better described abstractly rather than concretely, one would use a function to compute it and say so accordingly. The format for various design constructs are as follows: ● Input from keyboard 1. Read in list of objects Input from a file 1. Read in list of objects from the input file ● Output to screen 1. Display/print list of objects Output to a file ● 1. Display/print list of objects to the output file. ● Initialization 1. Initialize/set object to initial value. ● Computation 1. Compute object [as expression] The explanation is optional depending on whether the computation is straightforward or not. Computation should be expressed in English or standard mathematical notation, not in programming language notation. In particular, the use of C operators like ++ or *= is not appropriate. Instead, these computations might be expressed as 1. Increment object 2. Multiply object by some value Computation that will be done using a function should be indicated 09/01/2011 Page 3 of 8 D. Hwang 1. Compute object using a function. ● Function return 1. Return object or expression ● Branching selection. The condition and else bodies are subnumbered consecutively. 1. If condition then 1.1. Do something Else 1.2. Do something else Note that the condition can be any expression resulting in a boolean value. Also note that the else portion is optional. ● Multi­way branch selection ­ each branch is subnumbered consecutively. 1. If condition1 then 1.1. Do something1 Else if condition2 then 1.2. Do something2 Else 1.3. Do something else ● Case selection ­ each case is subnumbered consecutively with case actions just listed under each case 1. Select on expression 1.1. Case case1value Do case 1 1.2. Case case2value Do case 2 ● Counted repetition ­ header indicates loop control variable, starting value, stopping value, and step size (assumed to be 1 if omitted). Body is subnumbered. 1. For lcv from initial value to final value [by step size] 1.1. Do something Note that the construct implies that the loop control variable is automatically initialized and updated for each iteration. ● Pre­test conditional repetition (including loop control variable initialization and update). Body is subnumbered. 09/01/2011 Page 4 of 8 D. Hwang 1. Initialize lcv 2. While test lcv do 2.1. Do something 2.2. ... 2.3. Update lcv ● Post­test conditional repetition. The do and while are numbered consecutively. Body is subnumbered 1. Do 1.1. Do something 1.2. ... 2. while test lcv Example Analysis and Design for Simple Program Problem Statement The New Telephone Company has the following rate structure for long­distance calls: The regular rate for a call is $0.40 per minute. Any call started at or after 6:00pm (1800 hours) but before 8:00am (0800 hours) is discounted 50 percent. ● Any call longer than 60 minutes receives a 15 percent discount on its cost (after any other discount is subtracted). ● All calls are subject to a 4 percent federal tax on their final cost. ● ● Write a program that reads the start time for a call based on a 24­hour clock and the length of the call. The gross cost (before any discounts or tax) should be printed, followed by the net cost (after discounts are deducted and tax is added). For the purposes of this example, we will break this program up into two pieces, the main program and a function that computes the net cost of the phone call. Main Program Analysis Objects Type Movement Name regular call rate (.40) double constant REGULAR_RATE night discount (.50) double constant NIGHT_DISCOUNT length discount (.15) double constant LENGTH_DISCOUNT federal tax rate (.04) double constant FEDERAL_TAX_RATE start of night time (1800) int constant NIGHT_START end of night time (800) int constant NIGHT_END 09/01/2011 Page 5 of 8 D. Hwang Objects Type Movement Name long call length (60) int constant LONG_CALL_LENGTH time of day the call started in military time int input start_time number of minutes the call lasted int input call_length cost of call before discounts and tax double output gross_cost cost of call after discounts and tax double output net_cost Main Program Design 1. 2. 3. 4. Read in start time and call length Compute gross cost Compute net cost using a function Display gross cost and net cost Function compute_net_cost Analysis We specified in the main program design that we would use a function to compute the net cost of a call. Here is a possible analysis of this function: Objects Type Movement Name time call started int received start number of minutes the call lasted int received length gross cost of the call double received gross net cost of the call double returned net amount of tax double computed tax Function compute_net_cost Design 1. If the call is at night then 1.1. Compute net cost after applying the night discount Else 1.2. Net cost is the gross cost 2. If the call is long then 2.1. Compute net cost after subtracting the long call discount 3. Compute federal tax 4. Add the tax to the net cost 5. Return net cost A complete program file with corresponding analysis and design comments might look like: /* File: design.c * Example program for A&D guideline */ 09/01/2011 Page 6 of 8 D. Hwang #include <stdio.h> #define #define #define #define #define #define #define REGULAR_RATE 0.40 NIGHT_DISCOUNT 0.50 LENGTH_DISCOUNT 0.15 FEDERAL_TAX_RATE 0.04 NIGHT_START 1800 NIGHT_END 800 LONG_CALL_LENGTH 60 /* /* /* /* /* /* /* Regular call rate Discount for night calls Discount for long calls Federal tax rate Start of night rate, 6pm End of night rate, 8am Long calls are > 60 min. */ */ */ */ */ */ */ double compute_net_cost (int start, int length, double gross); int main () { int start_time, call_length; double gross_cost, net_cost; /* /* /* /* Input - time call started in military time Input - length of call in minutes Output - cost of call before discounts Output - cost of call after discounts & taxes */ */ */ */ /* 1. Read in start time and call length */ printf ("Enter the start time of your call in military format: "); scanf ("%d", &start_time); printf ("Enter the length of your call in minutes: "); scanf ("%d", &call_length); /* 2. Compute gross cost */ gross_cost = call_length * REGULAR_RATE; /* 3. Compute net cost using a function */ net_cost = compute_net_cost (start_time, call_length, gross_cost); /* 4. Display results */ printf ("The gross cost of this call is $%.2lf.\n", gross_cost); printf ("After discounts and taxes, the net cost is $%.2lf.\n", net_cost); return 0; } double compute_net_cost (int start, /* REC'D - time call started */ int length, /* REC'D - length of call */ double gross) /* REC'D - gross cost of this call */ { double net, /* RET'D - net cost for this call */ tax; /* Computed - federal taxes for this call */ /* 1. Check if the call is at night */ if ((start >= NIGHT_START) || (start < NIGHT_END)) /* 1.1 Apply the night discount */ net = gross * NIGHT_DISCOUNT; else /* 1.2 Net is same as gross */ net = gross; 09/01/2011 Page 7 of 8 D. Hwang /* 2. Check if call is long */ if (length >= LONG_CALL_LENGTH) /* 2.1 Deduct long call discount */ net = net - (net * LENGTH_DISCOUNT); /* 3. Compute federal tax */ tax = net * FEDERAL_TAX_RATE; /* 4. Add tax to the net cost */ net = net + tax; /* 5. Return net cost */ return net; } 09/01/2011 Page 8 of 8 D. Hwang