1. C++ Hints
1.1 The Golden Rules of Programming
1.2 General Design Tips
- Worry about correctness first, and efficiency later.
- Premature optimization is the root of all evil. (Knuth, et al)
- But don't make bad designs that preclude efficiency.
- Write code that is easy to understand and debug.
- Write Small, Testable pieces of code.
- Write as little code as possible. Reuse wherever you can.
1.3 Design for robustness and debuggability
- Yes, you can design your code so that it is easier to debug! Its a
conscious choice, and you might need to make tradeoffs.
- Check for errors before they occur
- Avoid objects that can be in invalid states
- Failure of a constructor can cause problems - no way to signal an
error, might return an invalid object.
- Error check before constructors
- Use factories rather than constructors (for heap objects)
- Document (and have tests for) preconditions and invariants.
1.4 Class Design and Object Oriented Programming
- Group Data that Goes Together
- Make classes minimal
- Functions that use objects rather than methods (better preserve
privacy issues, keep classes clean, ...). Big Java vs. C++ thing.
- Less to understand at core - keep independent pieces independent.
- Write accessors if they are clearer, or if you really want read-only
data.
- Choose data structures wisely.
- Be careful about automatic copying and conversion - the compiler
might not do what you want!
1.5 Let the Compiler Catch your Bugs!
- No warnings - ''your code should always compile with no
warnings.'' Even if you know it isn't a problem, some new warning
might get lost in the middle. Somethings that seem inoccuous might
really be a problem
- Let the type checker catch your bugs whenever possible! This
usually means thinking about your code to make the type system be
more helpful.
- Use
const whenever it is possible, as much as possible, and
correctly. If nothing else, it is good documentation!
- Avoid casts as much as possible
- Use classes to pass long argument lists
- Default constructors can be helpful here
1.6 Memory Management
- Understand the different types of memory
- Automatics
- Heap Allocated
- Know who is responsible for memory - make good comments about this!
- Avoid copying heavy objects
- Efficiency in parameter passing
- Slicing and aliases
- Declare variables when they are used, in the tightest scope
possible.
- Use auto variables for short lived objects only. (should not want to
survive the scope)
- Understand how vectors work, and why/when to use them
1.7 C++ isms
- Avoid fancy language features unless you understand them, and really
need them.
- Avoid macros.
- Prefer new/delete to malloc/free
- be careful returning &
1.8 Debugging and Testing
- Design good test cases
- simple examples that are easy to see what is going on
- things with known answers
- excersize all code paths - get coverage
- consider boundary conditions - and make examples that test them
- try the easy cases first - if your program doesn't work on these,
there's no point going on to the harder cases
- Understand what your program should be doing - and devise checks to
make sure it is working as you expect.
- Avoid the "million monkey" style of debugging (randomly permute code
until it works).
2. TargeImage
A wrapper around the C I/O library (we're stuck with its design) that
tries to only handle the most common and important case.
Designed to avoid "accidents":
- You always will have a pointer to one - not a constructor
- Avoids object copies (what does it mean to copy the image? deep or
shallow?)
- Avoids failures in the constructors
- If you have a valid pointer to one, you should have a valid image
- just check for a NULL pointer - you don't need to check inside
Very Minimalist class - just provides the storage. All operations on
it should be "external" (functions that use it).
Always has an alpha channel
- you'll learn about alpha later
- its premultiplied alpha (again, you'll learn about it later)
3. PictureProcessor
Challenges:
- need to have an extensible set of functions. don't want to have a
big long list (a case statement, or lots of ifs)
- want to keep functions independent
- want to have common parsing code
The Command concept:
- want a unified interface to all commands
- each takes different arguments
- pass the entire command line (or a list of the arguments)
- do some of the parsing work ahead of time. (this is a place where
the design is a bit weak - too much of the parsing happens in the
commands themselves)
- why not just functions? (why the command class)
- don't want to keep a table (which you'd have to manually update)
- don't want 2 versions of the code (give away version, and complete
answer version)
- Command class gives a way of automatically creating the list using
global constructors and a linked list
The Context class:
- concept from programming languages
- environment - probably the more correct term
- table of the local variables (or everything in scope)
- probably more like a register file
- store the values of the variables
- 26 of them
- each can store an image (but may have no image in it)
- memory management on read/write