The practice of programming
Chapter 4 Interfaces
A good programmer should always be good at designing. The essence of design is to balance competing goals and constraints. When we do programming, we need to design a friendly, portable and flexible interface.
Among the issues to be worked out in a design are:
interfaces, information hiding, resource management, error handling
These factors are not separated, but combined.
So, how to do a good designer? On the other word, how to handle the issues above perfectly?
The first step is to construct a general frame, leaving out the details. Then we need to test it by thinking of every possible situation, and improve it. By the way, it is essential for our frame to work in changeable environments. In this circumstance, we need specifications to constraint our work. Generally speaking, specifications had better be worked out in advance.
To prosper an interface must be well suited for its task-simple, general, regular,predictable, robust-and it must adapt gracefully as its users and its implementation change.
- Hide implementation details
- Avoid global variables
- Don‘t reach behind the user‘s back
- Do the same thing the same way everywhere
About Resource Management:
- Initializationma
- Maintaining state
- Sharing and copying
- Cleaning up (Free a resource in the same layer that allocated it)
To avoid problems, it is necessary to write code that is reentrant, which means that it works regardless of the number of simultaneous executions.
The text of error messages, prompts, and dialog boxes should state the form of valid input.
Charpter 5 Debugging
- Good Clues
- Look for familiar patterns
- Examine the most recent change
- Don‘t make the same mistake twice
- Debug it now, not later
- Get a stack trace
- Read before typing
- Explain your code to someone else
No Clues
- Make the bug reproducible
- Divide and conquer
- Study the numerology of failures
- Display output to localize your search
- Write self-checking code
- Write a logfile
- Draw a picture
- Use tools
- Keep records
- Last Resorts
This may be the time to use a good debugger to step through the program.
Non-reproducible Bugs
- Check whether all variables have been initialized
If the bug changes behavior or even disappears when debugging code is added, it may be a memory allocation error
Chapter 6 Testing
Test as You Write the Code
- Test code at its boundaries
- Test pre- and post-conditions
- Use assertions
- Program defensively
- Check error returns
- Systematic Testing
- Test incrementally
- Test simple parts first
- Know what output to expect
- Verify conservation properties
- Compare independent implementations
- Measure test coverage
Test Automation
- Automate regression testing
- Create self-contained tests
Test Scaffolds
Stress Tests
Tips for Testing
- Programs should check array bounds (if the language doesn‘t do it for them), but the checking code might not be tested if the array sizes are large compared to typical input.
- Make the hash function return a constant, so every elemen1 gets installed in the same hash bucket.
- Write a version of your storage allocator that intentionally fails early, to test your code for recovering from out-of-memory errors.
- Before you ship your code. disable testing limitations that will affect performance.
- Initialize arrays and variables with some distinctive value, rather than the usual default of zero; then if you access out of bounds or pick up an uninitialized variable, you are more likely to notice it.
- Vary your test cases
- Provide ways to make the amount and type of output controllable when a program is run; extra output can help during testing.
- Test on multiple machines, compilers, and operating systems.
Book Review of “The practice of programming” (Ⅳ)
原文:http://www.cnblogs.com/Christen/p/5043778.html