CSci 435/535 Software Engineering
Outline
Review Software Quality Strategies for Writing Good Code Common Errors Good Books Summary
Lecture 10 Implementation
3/3/2004
3/3/2004
Review: Object-Oriented Design
Three types of design
System: hardware-software interaction High-level: architecture, interfaces and interactions Low-level: Data structures, method type signatures, algorithm descriptions
Some Characteristics of Quality
Correctness Functionality Efficiency Usability Maintainability Flexibility Testability Portability Reusability Interoperability Supportability Dependability
Reliability, security, safety, availability, more
Object-oriented design extends analysis by developing implementation-oriented classes, and instantiated objects and their interactions Watch out for: fragile base classes, subclass coupling, important yet implicit domain concepts
3/3/2004 3
Writing code that gives the right answer is only part of our job Think about quality when coding and testing
3/3/2004 4
Writing Quality Software Is Hard
Writing solid code is hard, and requires diligence Goals:
Write code that works on the first try Write code that is correct, and has all the -ilities
Good/Bad News: We Are In Total Control
It is a painful thing To look at your own trouble and know That you yourself and no one else made it
Sophocles, Ajax
never finding the first error gives more confidence than finding the last error Harlan Mills
Dont code by accident Recurring theme: A little effort pays off
3/3/2004 5
QQ: Should you be more confident in the reliability of your program after finding and fixing lots of bugs?
3/3/2004 6
Choose an Appropriate Language
Rapid prototyping: interpreted (e.g. VB) Tight content-code coupling: PHP Safety critical: Strongly typed, analyzable AI: inference language (e.g. Prolog)
Syntax Tips
{} are really for scoping
{ bool scoped_variable = true; }
Dont be afraid to use blank lines Example: I write the prototype in Perl, then convert to C++ for speed. Use indentation (2 spaces vs 8-space tab?) Dont be afraid of _: APIConst/A_PI_Const/API_Const Use long names (i.e. get a good editor)
3/3/2004 7 3/3/2004 8
Coding Standards
Must be programmer-developed
Must get buy-inimposed standards will be ignored
Minimize Complexity
Keep modules small and understandable Avoid complex control structure (Goto Considered Harmful [Dijkstra]) Optimize last (measure, plan, change, check) Rewrite if neededdont just apply band-aids Dont leave modified code in worse shape Avoid unnecessary inter-module dependencies QQ: Examples of dependencies?
9 3/3/2004 10
Must allow for exceptions Examples
3-deep nested if-statements No default in switch Function length Magic values (e.g. error codes for return values) Dangerous constructs (e.g. #define, void*, downcasts, RTTI, strcpy())
3/3/2004
Comments
Opinions differ
If you need lots of comments, you need to rethink it
Do It Now or Never
A real comment in my code:
/* NOTE: THE SPEC DOESN'T TAKE COVERED/SINGLE POINT FAILURES INTO ACCOUNT LIKE IT SHOULD. HECK, IT DOESN'T EVEN SEEM TO COMPUTE THE NONDETERMINISTIC TRANSITIONS CORRECTLY */
Strive for self-documenting code. Use comments for nonobvious bits you cant make simpler Add comments to explain the big picture. What does this module do? How do I use it? Remember more comments = more maintenance
e.g. Instead of change log, rely on CVS
3/3/2004 11
Comment as you go (as necessary) Make sub-modules as you go Write error cases as you go Implement the better design youre thinking of
It really is worth the effort!
3/3/2004 12
Remember the Cost of Maintenance
Short-term thinking:
Names like snglptflr. (learn a good editor) Unnecessary coupling via int i Functions 500+ lines
Say What You Really Mean
Learn to use constthe compiler can help catch errors as it does with type checking typedefdont just use int everywhere Use the right names: variables are nouns, functions are verbs or adjectives. Avoid negative adjectives
the_variable (unique), variables (more than one), a_variable (an iterator), in_variable (input argument) sorted_list = sort(unsorted_list) vs my_list = sort(my_list) if (is_sorted(a_list)) vs if (!not_sort(a_list))
13 3/3/2004 14
Use a common subset of the language
if (foo(), bar()) ; var = condition ? 1 : 0;
Avoid creating system dependencies which hurt portability. (And try 2 different compilers) Code for the maintainer, not the computer
3/3/2004
Think Abstractly
Use the right abstractions. They:
Clarify your thinking Provide the functions you need Let you work at a higher level
Egoless Programming
Always assume your code has unknown bugs Remember you are not your code Do code reviews often Remember theres always someone who can do it better. Maybe its the future you Use objective measurementsrun automatic tests often, do analysis often (purify, gcc Wall) Solutions, not excuses. (And avoid blame) Find a good mentor
15 3/3/2004 16
Example:
int coefficients[10];
oops More than 10? Really ordered? How to add a new coefficient to coefficients?
set<int> coefficients; coefficients.insert(3);
3/3/2004
Implementation Strategies
Grow, dont build. Always a working system [QQ: Who said that?]
Make sure it can always compile, run, and test Make sure defects are fixed immediately
Top-Down Vs. Bottom-Up
Modules
Low-level: usually data, simple functions High-level: contain control
Bottom-up
Easier because less dependencies, more parallelism Danger: design problems found late
Use uses and implements relations to identify module relationships
Uses: The correct operation of module A depends on the correct operation of module B
Top-down development
Can check interfaces. Stub-out implementations Danger: modules arent unit-tested well
QQ: Example of A uses B, but A doesnt call B?
3/3/2004 17
Answer: Sandwich the modules
3/3/2004 18
Testing
Write tests first, or you wont at all Add testing code to modules to ease unit testing Build test cases from:
Requirements Features Previous bugs
Common Errors
Unhandled error conditions Buffer overflow Type casts Memory leaks Pointer abuse Unnecessary dependencies Leaving a function without cleaning up
3/3/2004 20
Always testit aint done until it passes Consider how a bug could have been prevented
3/3/2004 19
Books to Read
Meyers, Effective C++, More Effective C++ McConnell, Code Complete, Writing Solid Code Gamma, et al., Design Patterns Hunt and Thomas, The Pragmatic Programmer:
Summary
Writing quality software is hard
Partly because we have the freedom to do anything including shoot ourselves in the foot
Fight complexity
Simple designs, only necessary dependencies
From Journeyman to Master
The expectations of life depend upon diligence;
Kaner, Testing Computer Software
3/3/2004 21
the mechanic that would perfect his work must first sharpen his tools. Confucious
3/3/2004
22