CS 250 Computer Programming and Problem Solving - FALL 1998
|
[ Home | Syllabus | Notes | Glossary | CS250 WEB Version Home Page ]
Problem Solving and Software Engineering
Programming in the Large
Construction methods do not "scale up".
E.g., bridge construction
Site |
Construction |
Pedestrian bridges across small streams |
2x4's lashed/nailed to an anchoring post |
Pedestrian bridges across larger streams |
rope bridge with plank flooring |
"country" bridge, light vehicular traffic |
wooden trestle bridge |
suburban overpass, moderate traffic |
concrete and steel arch |
medium width river, heavy traffic |
steel girder and cable suspension bridge |
wide river, heavy traffic |
concrete and steel, pylon support |
Programming methods do not scale up either.
"Toy" programs |
100's of lines |
Small programs |
10,000 lines |
Medium programs |
100,000 lines |
Large programs |
1,000,000 lines |
Very Large programs |
10,000,000 lines |
Small programs are typically implemented by individuals.
Medium and larger programs are implemented by teams.
Scaling in Time
Throwaway programs |
run a few times, discarded within a few weeks |
Personal programs |
kept, run by programmer only |
Local programs |
run under programmer's supervision |
Released programs |
one version, run by "public" |
Supported programs |
multiple versions released to public over months/years |
Software Development
Students |
Professionals |
Get assignment from instructor |
|
Ask clarifying questions |
5% |
Devise an appropriate algorithm |
5% |
Code the algorithm |
20% |
Validation: Testing |
5% |
Debugging |
65% |
Never_look_at_it_again |
|
|
|
|
Get request from user. |
|
Requirements_Analysis |
10% |
|Functional Specifications |
20 % |
Design |
15% |
Implementation |
15% |
Validation: Testing |
30% |
Debugging |
10% |
Maintainence |
100-200% |
|
|
|
("Professional" figures based on successful NASA
projects.)
Software Life Cycle
- Phase 1: Specification
- Phase 2: Design
- Phase 3: Verification
- Phase 4: Coding
- Phase 5: Testing and Validation
- Phase 6: Refining
- Phase 7: Production
- Phase 8: Maintenance
The Importance of Abstraction
- Short Term Memory: 7 + or - 2 "things"
- Difference between expert and novice chess players
In general, experts have a richer "vocabulary"
- Difference in performance between expert and average programmers
is an order of magnitude.
So what's an order of magnitude or two between friends, well
- A car going an order of magnitude faster would break the sound
barrier and be faster than a commerical jetliner
- A jet liner on order of magnitude faster would go around the
world in less than 3 hours
- If I made an order of magnitude more money, well ....
- Physical Science: from quarks to ecosystems to astronomy
Same reality, different abstractions
- Computer Systems: from 0's and 1's to the World Wide Web
what is the vocabulary? what are the building blocks
- What is possible when you stand on the shoulders of giants?
what does that mean?
- Much of what is called knowledge is the invention and use of new
abstractions, new ways of characterizing what we experience.
- Abstraction allows one to know something without knowing all the
details.
- Its a big deal.
Phase 1: Specification: What vs How
- Capture what the user/customer wants
Articulates the problem to be solved
- A good specification tells what a program should do/does but not
how it does it.
- A well thought out specification will capture some compelling
abstraction that makes it easy for the programmer to develop and the user to understand
and use the system
- Specifications apply at many levels of abstraction and can define
the building blocks (the vocabulary) for large systems.
Phase 2: Design: the Software's Architecture
- Divide the solution into separate units or modules (abstraction at work)
- Each module should provide a well-defined task. (Cohesive)
- Modules should be as independent as is practical (Loosely coupled)
This enables higher reuse.
- The ways the modules interact defines the software architecture of the solution.
- The purpose and usage of a module is its specification.
C++ supports the concept of modular programming
through its class and function constructs
- A module's specification should hide the details
of its implementation
(information hiding).
- A specification is a contract defined in terms of
its pre- and post-conditions.
Pre and Post Conditions
float SquareRoot(float x)
// Calculates the square root of a floating point number
// Precondition: x >= 0
// Postcondition: RV * RV = x (where RV is the value returned)
- Notice that the caller of this function has the obligation to
satisfy the Precondition. Otherwise the contract is nullified
- There are an arbitrary number of additional preconditions and
postconditions that could be added. (e.g. no global values are changed, the value of
"x" is not changed) but we will avoid making statements which are normally
considered true (one should not change global values or input variables in a function)
- We will also avoid redundant statements (e.g. "x" is a
floating point number)
- The user of this function does not need to know how (the
algorithm) used to calculate the square root. It could be computed or looked up in a table
(or you could ask a old-timer to calculate it on a slide rule - but then the user might
not be happy about the performance).
- You will be expected to supply pre- and post-conditions on all
the functions you specify
Phase 3: Verification (is it correct?)
- Assertions are statements which are true at certain points in the
program
- Pre and Postconditions are assertions true at the beginning and
end of a module
- Loop invariants are assertions that are true each and every time
a loop is executed.
- They must be true initially (before the loop executes the first
time)
- They must be true after every execution of the loop
- They should capture the essence (correctness) of the loop.
- Example from the book
// Chap 1, p 8
// computes the sum of A[0], A[1], . . ., A[N-1]
// for any N >= 1
int Sum = A[0];
int J = 1;
while (J < N) // loop invariant goes here
{ Sum += A[J];
++J;
}
- What does this loop do?
- Can you make an assertion that is true first time, every time?
// Chap 1, p 8
// computes the sum of A[0], A[1], . . ., A[N-1]
// for any N >= 1
int Sum = A[0];
int J = 1;
while (J < N) // Sum is the sum of the elements A[0] through A[J-1]
{ Sum += A[J];
++J;
}
Phase 4: Coding
Characteristics of Good Programs
- Reliability
- Usability
- Maintainability
- Understandability
- Modifiability
Contributing to Those Characteristics
- Reliability
- Testing & Debugging Technique
- Elegant design.
- Clear implementation.
- Usability
- User interface design.
- Efficiency
- Maintainability
- Elegant design.
- Clear implementation.
Clear Implementation
1. Extensive use of subprograms
2. Avoid global variables in subprograms
3. Proper use of REFERENCE parameters
4. Functions without side-effects
5. Orderly flow of control
6. Error Handling
7. Readability
8. Documentation
Proper use of REFERENCE parameters
If a subprogram needs to return only one value, consider
making it a function.
Procedures normally use REFERENCE for exactly those
parameters where a value is to be sent to the caller.
An exception: REFERENCE parameters may be used when
passing large arrays into a subprogram.
(but you can use the "const" adjective to tell the
compiler that nothing is to be changed)
Functions without side-effects
Side effects are any change to the program status other than
returning a value.
o Changes to global variables.
o REFERENCE parameters in functions.
o I/O
As a rule functions should have no side effects. Procedures
should minimize side-effects, and explicitly document those
that they have.
Orderly flow of control
o The general flow is forward.
o Modules are entered only at their beginning and exited only
at their end.
o Conditions for entering and terminating loops are clear.
o The alternative cases of conditional statements are clear.
Most uses of "goto" violate one or more of the above.
Readability
o Choose meaningful names for variables, subprograms, and
constants.
(Pay special attention to numeric and string constants.
Should they be named?)
o Indentation and Whitespace to make programs readable
Documentation
1. Header comment for program.
(a) Purpose
(b) Author and date
(c) Description of program input and output.
(d) How to use.
(e) Assumptions (what type of data expected, what could go wrong).
(f) Brief description of global algorithms and data structures.
(g) Description of key variables.
2. Header comment for each module.
(a) Description
(b) Pre-condition and Post-condition
3. Comments within body explaining important and confusing parts of code.
Testing & Debugging Technique
Testing is the search to determine if errors exist.
o Test with valid data leading to a known solution.
o Test extreme or boundary cases.
o Test with invalid data to check error-detection capability.
o Test with random data.
o Test with actual data.
Testing & Debugging Technique 2
Debugging is the search for the causes and corrections to an
error.
Effective use of output is the key.
Debug output should indicate the location and the values of
key variables at that location.
User Interface
Interactive programs should provide clear prompts.
"Echo" the input. (i.e., include the input
somewhere within the input)
Make the output easy to read. Try organizing into columns,
labelling output, etc.
Fail-safe programming - program should perform
"reasonably" at all time.
- Errors in input should never cause an abort without explanation.
- Erroneous input should not be accepted as valid.
Copyright chris wild 1998.
For problems or questions regarding this website contact [Chris
Wild (e-mail:wild@cs.odu.edu].
Last updated: August 30, 1998.