1
|
- Richard C. Davis
UW CSE – 12/4/2006
- Lecture 23 –
Readability and Robustness
|
2
|
- Final Exam in just over a week
- Most similar to cse303 Spring 2006 exam
- This is the only quarter that uses C++ heavily
- Use ".cpp" instead of ".cc"
- Use Subversion/svn instead of CVS/cvs
- Ignore problems 10 and 11 (concurrency)
- Unless we fit this in on the last day
- Also similar to finals from other quarters
- HW7 Due Wednesday, 2PM
- Late Days now visible in MyUW (up to HW4)
|
3
|
|
4
|
- No easy answers, but there is a direction
- Code should be Readable
- It's more than just adding comments
- It's about making program logic easy to follow
- Code should be Robust
- Gracefully reacts to unforseen usage
- Gracefully handles various error conditions
- Code should be Maintainable
- Well defined components, loose coupling
- Readability and Robustness also help
|
5
|
- What does the following code snipped do?
- int main(int argc, char** argv) {
- int i[argc-1];<=
/li>
- for (int j=3D0;
j<argc-1; i[j]=3Datoi(argv[++j]));
- cout <<
((argc-1) % 2 ? 'y' : 'n') << endl;
- // ...
- }
- See if you can tell in 10 seconds
|
6
|
- int main(int argc, char** argv) {
- // Store all
arguments in an array
- int size =3D ar=
gc - 1;
- int numbers[siz=
e];
- for ( int i =3D=
0; i
< size; i++ ) {
-
numbers[i] =3D atoi(argv[i+1]);
- }
- // Print a mess=
age to
stdout about the arguments
- if ( (size % 2)=
=3D=3D 0
) {
-
cout << "Number of elements is even" <<
endl;
- } else {
-
cout << "Number of elements is odd" <<
endl;
- }
- // ...
- }
|
7
|
- Better names for variables
- Reflect their content/meaning
- Added Comments
- Describe the purpose of each section of code
- More detailed output
- Better spacing
- Visually separate parts of complex expressions
- Visually separate sections of code
|
8
|
- Your code is part of your documentation
- Others need to understand it
- You'll need to understand it when you forget
- Maintenance: fixing bugs is easier
- Adding new features is easier
- Clear code helps clear thinking
- Unreadable code tends to get thrown out
|
9
|
- Add comments, but don't stop there
- Good levels of abstraction
- Clear expressions and statements
- Make program logic easy to follow
- Each function has a single specific goal
- Some small things that help
- Good variable/class/method names
- Good indentation
- Follow a coding standard
|
10
|
- Defensive Programming
- Check your function inputs
- Check buffer boundaries
- Check for errors, catch/handle exceptions
- Enforce encapsulation (data hiding)
- Important software engineering principle
- Other general practices
- Strive for simplicity, perform code reviews
- Check invariants (helps testing/debugging)
- Reuse well-tested code (like standard libraries)
|
11
|
- Famous last words:
- "No one would pass a NULL argument here"
- "No one will ever enter a name longer than X"
- "I'll make it work first, then add error handling"
- Golden rule
- Assume callers don't know what they're doing
|
12
|
- Asserts convenient for checking inputs/bounds
- Fail precondition? à Crash program
- Use when you don't have time to do better
- Example from Polygon.cpp (HW6)
- #include <cassert>
- // ...
- Point Polygon::GetPoint(int index) const {
- assert(index >=3D 0
&& index < NumPoints());
- return(pts[index]);=
li>
- }
|
13
|
- Every time you invoke a function
- Check if the function can return an error
- Read the specification for that function
- One reason why good specifications are important
- Assume it will sometimes return that error
- Handle the error properly
- Examples
- Opening a file can fail (fopen)
- Reading data from a stream can fail (fscanf)
|
14
|
- Key concept in OO programming
- A class encapsulates attributes and funcs.
- Classes correspond to "abstract data types"
- A class "exports" an interface
- All communication goes through interface
- No one is allowed to manipulate data directly
- Information Hiding
- Don't reveal details about implementation
- Don't reveal details about representation
|
15
|
- Example of an invariant (HW4)
- "Allocreclist is always in sorted order"
- Add a function: CheckOrderInvariant
- Returns true if list is in order
- Returns false otherwise
- Inside function ARLInsert
- Add: assert(CheckOrderInvariant(head));
- This practice helps early bug detection
|
16
|
- Easy to break encapsulation by accident
- Example:
- Caller and callee have pointer to same object
- Caller can change callee internal rep. BAD!
- A very common source of errors
|
17
|
- Example 1: Error when handling inputs
- void insert (Node **head, char *original) {
- Node node =3D
(Node*)malloc(sizeof(Node));
- // ...
- node->origin=
al =3D
original;
- }
|
18
|
- Example 2: Error when handling outputs
- Node *lookup (Node *head, char *original) {
- Node *element =
=3D head;
- // Iterate thro=
ugh
list and find string
- return element;=
- }
|
19
|
- Solution 1: Copying
- Copy data before integrating into internal rep.
- Return copies of data in internal rep.
- Solution 2: Immutable Objects
- Immutable objects can never be changed
- Solution 3: Using const
- Good idea, but be careful
|
20
|
- Example 1: "const" when handling inputs
- void insert (Node **head, const char *original) {
- Node node =3D
(Node*)malloc(sizeof(Node));
- // The following
causes compile-time error
- node->origin=
al =3D
original;
- }
|
21
|
- Example 2: "const" when handling outputs
- const Node *lookup (Node *head, char *original) {
- Node *element =
=3D head;
- // Iterate thro=
ugh
list and find string
- return element;=
- }
- // Caller cannot change the element returned
- const Node *element =3D lookup(head, my_string);
- // The following causes compile-time error
- Node->original[0] =3D 'a';
|
22
|
- In the lookup example, caller cannot change the element returned: GO=
OD
- However, caller has a pointer to an element that someone else can fr=
ee
by removing the string from the list: BAD
|
23
|
- Non-constant pointer to constant data
- const char *ptr
- Cannot change the content of these locations
- Can make ptr point to different mem. locations
- Constant pointer to non-constant data
- char * const ptr =3D …;
- Cannot change what ptr is pointing to
- Can change the content of pointer to location
- Can also have const char * const ptr
|
24
|
- Principle of least privilege
- Give a function enough access to data to accomplish task. Not more.
- C++ Notes
- "Accessors" work on const objects
- You can have both accessors and mutators
- Class &GetElement(int idx);
- const Class &GetElement(int idx) const;
|
25
|
- Robust software can protect against
- Buffer overflow attacks
- Crashes caused by invalid inputs
- But security is much harder than that
- Example: Denial of service attack
- Send huge numbers of requests to a server
- Example: Keep adding elements to a list
|
26
|
- You now know some basic software eng.
- Software development process
- Main steps involved in building a software system
- Specifications
- Why we need them and how to write simple ones
- We talked about informal specifications only
- Testing: Why and How
- Writing Robust and readable code
- There's much more to software engineering
- The examples in this class may not be the best
|
27
|
|