Design Descriptions

What is the design of a program?

For the purpose of this course, the design of a program describes the computational steps that help developers implement (or code) the solution to a computational problem.

Why do we care about developing a design before we write the code?

The design helps us devise a plan of the problem solving process. See Polya’s Problem Sovling Techniques resources on under Resources.

If we start coding directly

  • We focus more on syntax instead of the semantics or the meaning of the implementation
  • Or we miss having a plan or a strategy that will guide us to think through the implementation steps

How are computational steps DIFFERENT from coding or Python statements?

  • Also known as pseudocode, computational steps are higher-level, more abstract concepts than the actual code.
  • A good design can easily guide us to write an implementation in ANY general-purpose programming language.
  • Think of computational steps as patterns you can apply and customize to what’s needed to explain design decisions.

How are computational steps SIMILAR to coding or to Python statements?

Computational steps correspond to the following 4 control structures that any high-level programming language has:

  • Assignment
  • Conditional
  • Loop
  • Function/method call

Note that the assignment and function/method call are simple steps.

Conditional and loop are composite (or compound) steps because they include other steps.

Assignment-based computational step

  • Purpose: Why do we need to create or change a variable? This is the very first infomration that a computational step that uses an assignment MUST explain.
  • Variable name: What name is suggestive of the purpose of the variable?
  • Variable data type: What data type does the variable have? The data type is particularly important when it’s not a built-in atomic type (int, float, boolean), although it’s always good practice to indicate those, as well.

Conditional-based computational step

  • Purpose: Why do we need to make a decision? What is the decision about? How does the decision relate to the problem solving plan and logic?
  • Conditional type: What type of decision is it? One-alternative, two-alternatives, multiple-alternative decision? Note that the alternatives in a conditional may also be known as conditional branches.
  • Alternative condition(s) and behavior: What condition(s) does the alternative(s) have? And what behavior do the condition trigger if true? For two- or multiple-alternative conditionls, answer the same questions: what the condition and behavior they have and why we need to take them into account, too.

Loop-based computational step

  • Purpose: Why do we need to use a loop? What does the iteration do? How does the loop (or iteratino) relate to the problem solving plan and logic?
  • Number of iterations and loop type:
    • Number of iterations: how many iteration steps?
      • Known at the start of the iteration:
        • counted loop: for loop_variable in range(…):`
        • iterating over a collection: for loop_variable in collection:
      • Not knownn at the start of the iteration:
        • condition-based loop: while condition:
  • Loop variable name and data type (if counted loop or iterating over a collection):
    • What name is suggestive of the loop variable?
    • What’s the data type of the loop variable?
  • Iteration termination** condition**:
    • If counted loop or condition-based loop: what condition stops the iteration?
  • Behavior of each iteration step: What happens at each iteration step?
  • Loop advancing to the next iteration step: What ensures that with each iteration step the termination condition will

Function/method call-based computational step

  • Purpose: Why do we need to make a call? What does it resolve or waht need in the problem solving plan does it address?
  • Function/method name and location: What function/method do we call?
    • Own code? Built-in (default) library? Python library?
  • Call arguments: How do we call it? What input data do we pass to the call? What’s the data type of the values that the arguments yield?
  • Return value: Does the call return anything? If yes, what does it mean? What’s the data type? What do we do with it?

Example

Computational problem statement

  • Input: sequence of integers and a threshold value
  • Output: sequence of integers from the input that satisfy the condition of being smaller than the threshold value

Starter code

Use modularity and encapsulation when solving problems. Always encapsulate the computational steps in a function or in a method in a class.

  • The design of the input are the parameters of the function/ method
    • Give suggestive names to the parameters
  • The design of the output is what the function/ method returns
  • Write the docstring of the function/ method to describe:
    • What problem the function/ method solves
    • What the problem input is
    • What the problem output is
    • What exceptions an incorrect will produce

smaller_than() function design

def smaller_than(num_lst, limit):
    """
    Create and return a list of integers from num_lst that are smaller than limit
    :param num_lst: list of integers
    :param limit: integer
    :returns: list of integers
    :raise TypeError: if argument is not a list
    :raise ValueError: if there is no argument. 
    """

Note how the statement of the problem is expressed using the names of the parameters.

Design

What the design is for

Always include the function/ method header and docstring in the design document DESIGN.md. This is to confirm our understanding of WHAT the problem is.

  • Use Markdown tag # or ## to create separate sections for separate classes, methods, etc.
  • Use Markdown .... for the function/ method header and its docstring

In Markdown, our example is:

**`smaller_than()` function design**

```python
def smaller_than(num_lst, limit):
    """
    Creates and returns a list of integers from num_lst that are smaller than limit
    :param num_lst: list of integers
    :param limit: integer
    :returns: list of integers
    :raise TypeError: if argument is not a list
    :raise ValueError: if there is no argument. 
    """
```

Computational steps descriptions

Use Markdown tag * to present the computational steps as an itemized list.

If a computational step corresponds to a composite computational step it’s helpful to use nested itemized list: indent the Markdown tab * by one level.

Other useful Markdown tags are **bold** and *emphasize*.

The computational steps for smaller_than() use the accumulation pattern as shown below, in Markdown.

### "Happy Path" Design Descriptions
To create the output list of integers from the input list of integers we use the *accumulation pattern*. This means that we create the output iteratively, by going through the input, one item at a time. 

* Define an accumulator variable, `lesser_nums` of data type **list** of integers, in which we accumulate the output.  
* Initialize `lesser_nums` with empty list using an assignment.
* Iterate through `num_lst` with loop variable `a_num` of type integer to get hold of each item in `num_lst` at each iteration through the loop. Thus, at each iteration we use a conditional to decide whether each item is smaller than the threshold:
  * Check each element in `num_lst` referenced by loop variable `a_num` against the threshold `limit
  * Verify that `a_num` is less than `limit`, in which case append `a_num` to `lesser_nums`
  * To append `a_num` to `lesser_nums` we call Python **list** method `append().`
* Return output `lesser_nums`

### Illegal Argument Cases
* If `num_lst` parameter does not receive an argument of type list, 
  * Raise the exception TypeError with the message "Arguemnt must be of type list".
* If `num_lst` parameter doesn't receive any argument at all, 
  * Raise the exception ValueError with the message "Argument must exist, cannot be Non".

While it’s helpful to identify the type of computational step (assignment, conditional, loop), it’s even more important to justify their use, and provide critical information for the implementer to write a good coding solution.