http://home.earthlink.net/~huston2/books/programming_books.html
The Practice of Programming
Brian Kernighan, Rob Pike
Style
Use descriptive names for globals, short names for locals.
Be consistent.
Use active names for functions.
Be accurate.
Indent to show structure.
Use the natural form for expressions.
Parenthesize to resolve ambiguity.
Break up complex expressions.
Be clear.
Be careful with side effects.
Use a consistent indentation and brace style.
Use idioms for consistency.
Use else-ifs for multi-way decisions.
Avoid function macros.
Parenthesize the macro body and arguments.
Give names to magic numbers.
Define numbers as constants, not macros.
Use character constants, not integers.
Use the language to calculate the size of an object.
Don't belabor the obvious.
Comment functions and global data.
Don't comment bad code, rewrite it.
Don't contradict the code. Clarify, don't confuse.
Interfaces
Hide implementation details.
Choose a small orthogonal set of primitives.
Don't reach behind the user's back.
Do the same thing the same way everywhere.
Free a resource in the same layer that allocated it.
Detect errors at a low level, handle them at a high level.
Use exceptions only for exceptional situations.
Debugging
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.
Make the bug reproducible.
Divide and conquer.
Study the numerology of failures.
Display output to localize your search.
Write self-checking code.
Write a log file.
Draw a picture.
Use tools.
Keep records.
Testing
Test code at its boundaries.
Test pre- and post-conditions.
Use assertions.
Program defensively.
Check error returns.
Test incrementally.
Test simple parts first.
Know what output to expect.
Verify conservation properties.
Compare independent implementations.
Measure test coverage.
Automate regression testing.
Create self-contained tests.
Performance
Automate timing measurements.
Use a profiler.
Concentrate on the hot spots.
Draw a picture.
Use a better algorithm or data structure.
Enable compiler optimizations.
Tune the code.
Don't optimize what doesn't matter.
Collect common subexpressions.
Replace expensive operations by cheap ones.
Unroll or eliminate loops.
Cache frequently-used values.
Write a special-purpose allocator.
Buffer input and output.
Handle special cases separately.
Precompute results.
Use approximate values.
Rewrite in a lower-level language.
Save space by using the smallest possible data type.
Don't store what you can easily recompute.
Portability
Stick to the standard.
Program in the mainstream.
Beware of language trouble spots.
Try several compilers.
Use standard libraries.
Use only features available everywhere.
Avoid conditional compilation.
Localize system dependencies in separate files.
Hide system dependencies behind interfaces.
Use text for data exchange.
Use a fixed byte order for data exchange.
Change the name if you change the specification.
Maintain compatibility with existing programs and data.
Don't assume ASCII.
Don't assume English.
The Elements of Programming Style
Brian Kernighan, P. J. Plauger
Introduction
Write clearly - don't be too clever.
Expression
Say what you mean, simply and directly.
Use library functions.
Avoid temporary variables.
Write clearly - don't sacrifice clarity for "efficiency."
Let the machine do the dirty work.
Replace repetitive expressions by calls to a common function.
Parenthesize to avoid ambiguity.
Choose variable names that won't be confused.
Avoid the Fortran arithmetic IF.
Avoid unnecessary branches.
Use the good features of a language; avoid the bad ones.
Don't use conditional branches as a substitute for a logical expression.
Use the "telephone test" for readability.
Control Structure
Use DO-END and indenting to delimit groups of statements.
Use IF-ELSE to emphasize that only one of two actions is to be performed.
Use DO and DO-WHILE to emphasize the presence of loops.
Make your programs read from top to bottom.
Use IF, ELSE IF, ELSE IF, ELSE to implement multi-way branches.
Use the fundamental control flow constructs.
Write first in an easy-to-understand pseudo-language; then translate into whatever language you have to use.
Avoid THEN-IF and null ELSE.
Avoid ELSE GOTO and ELSE RETURN.
Follow each decision as closely as possible with its associated action.
Use data arrays to avoid repetitive control sequences.
Choose a data representation that makes the program simple.
Don't stop with your first draft.
Program Structure
Modularize. Use subroutines.
Make the coupling between modules visible.
Each module should do one thing well.
Make sure every module hides something.
Let the data structure the program.
Don't patch bad code ?rewrite it.
Write and test a big program in small pieces.
Use recursive procedures for recursively-defined data structures.
Input and Output
Test input for validity and plausibility.
Make sure input cannot violate the limits of the program.
Terminate input by end-of-file or marker, not by count.
Identify bad input; recover if possible.
Treat end of file conditions in a uniform manner.
Make input easy to prepare and output self-explanatory.
Use uniform input formats.
Make input easy to proofread.
Use free-form input when possible.
Use self-identifying input. Allow defaults. Echo both on output.
Localize input and output in subroutines.
Common Blunders
Make sure all variables are initialized before use.
Don't stop at one bug.
Use debugging compilers.
Initialize constants with DATA statements or INITIAL attributes; initialize variables with executable code.
Watch out for off-by-one errors.
Take care to branch the right way on equality.
Avoid multiple exits from loops.
Make sure your code "does nothing" gracefully.
Test programs at their boundary values.
Program defensively.
10.0 times 0.1 is hardly ever 1.0.
Don't compare floating point numbers just for equality.
Efficiency and Instrumentation
Make it right before you make it faster.
Keep it right when you make it faster.
Make it clear before you make it faster.
Don't sacrifice clarity for small gains in "efficiency."
Let your compiler do the simple optimizations.
Don't strain to re-use code; reorganize instead.
Make sure special cases are truly special.
Keep it simple to make it faster.
Don't diddle code to make it faster ?find a better algorithm.
Instrument your programs. Measure before making "efficiency" changes.
Documentation
Make sure comments and code agree.
Don't just echo the code with comments ?make every comment count.
Don't comment bad code ?rewrite it.
Use variable names that mean something.
Use statement labels that mean something.
Format a program to help the reader understand it.
Indent to show the logical structure of a program.
Document your data layouts.
Don't over-comment.
Practical Java
Peter Haggar
General Techniques
Understand that parameters are passed by value, not by reference.
Use final for constant data and constant object references.
Understand that all non-static methods can be overridden by default.
Choose carefully between arrays and Vectors.
Prefer polymorphism to instanceof.
Use instanceof only when you must.
Set object references to null when they are no longer needed.
Objects and Equality
Differentiate between reference and primitive types.
Differentiate between == and equals.
Do not rely on the default implementation of equals.
Implement the equals method judiciously.
Prefer getClass in equals method implementations.
Call super.equals of base classes.
Consider carefully instance of in equals method implementations.
Follow these rules when implementing an equals method.
Exception handling
Know the mechanics of exception control flow.
Never ignore an exception.
Never hide an exception.
Consider the drawback to the throws clause.
Be specific and comprehensive with the throws clause.
Use finally to avoid resource leaks.
Do not return from a try block.
Place try/catch blocks outside of loops.
Do not use exceptions for control flow.
Do not use exceptions for every error condition.
Throw exceptions from constructors.
Return objects to a valid state before throwing an exception.
Performance
Focus initially on design, data structures, and algorithms.
Do not rely on compile-time code optimization.
Understand runtime code optimization.
Use StringBuffer, rather than String, for concatenation.
Minimize the cost of object creation.
Guard against unused objects.
Minimize synchronization.
Use stack variables whenever possible.
Use static, final, and private methods to allow in lining.
Initialize instance variables only once.
Use primitive types for faster and smaller code.
Do not use an Enumeration or an Iterator to traverse a Vector.
Use System array copy for copying arrays.
Prefer an array to a Vector or ArrayList.
Reuse objects whenever possible.
Use lazy evaluation.
Optimize source code by hand.
Compile to native code.
Multithreading
Understand that for instance methods, synchronized locks objects, not methods or code.
Distinguish between synchronized statics and synchronized instance methods.
Use private data with an accessor method instead of public or protected data.
Avoid unnecessary synchronization.
Use synchronized or volatile when accessing shared variables.
Lock all objects involved in a single operation.
Acquire multiple locks in a fixed, global order to avoid deadlock.
Prefer notifyAll to notify.
Use spin locks for wait and notifyAll.
Use wait and notifyAll instead of polling loops.
Do not reassign the object reference of a locked object.
Do not invoke the stop or suspend methods.
Terminate threads through thread cooperation.
Classes and Interfaces
Use interfaces to support multiple inheritance.
Avoid method clashes in interfaces.
Use abstract classes when it makes sense to provide a partial implementation.
Differentiate between an interface, abstract class, and concrete class.
Define and implement immutable classes judiciously.
Use clone for immutable objects when passing or receiving object references to mutable objects.
Use inheritance or delegation to define immutable classes.
Call super.clone when implementing a clone method.
Do not rely on finalize methods for non-memory resource cleanup.
Use care when calling non-final methods from constructors.
Effective Java
Joshua Bloch
Creating and Destroying Objects
Consider providing static factory methods instead of constructors
Enforce the singleton property with a private constructor
Enforce noninstantiability with a private constructor
Avoid creating duplicate objects
Eliminate obsolete object references
Avoid finalizers
Methods Common to All Objects
Obey the general contract when overriding equals
Always override hashCode when you override equals
Always override toString
Override clone judiciously
Consider implementing Comparable
Classes and Interfaces
Minimize the accessibility of classes and members
Favor immutability
Favor composition over inheritance
Design and document for inheritance or else prohibit it
Prefer interfaces to abstract classes
Use interfaces only to define types
Favor static member classes over nonstatic
Substitutes for C Constructs
Replace structures with classes
Replace unions with class hierarchies
Replace enum constructs with classes
Replace function pointers with classes and interfaces
Methods
Check parameters for validity
Make defensive copies when needed
Design method signatures carefully
Use overloading judiciously
Return zero-length arrays, not nulls
Write doc comments for all exposed API elements
General Programming
Minimize the scope of local variables
Know and use the libraries
Avoid float and double if exact answers are required
Avoid strings where other types are more appropriate
Beware the performance of string concatenation
Refer to objects by their interfaces
Prefer interfaces to reflection
Use native methods judiciously
Optimize judiciously
Adhere to generally accepted naming conventions
Exceptions
Use exceptions only for exceptional conditions
Use checked exceptions for recoverable conditions and run-time exceptions for programming errors
Avoid unnecessary use of checked exceptions
Favor the use of standard exceptions
Throw exceptions appropriate to the abstraction
Document all exceptions thrown by each method
Include failure-capture information in detail messages
Strive for failure atomicity
Don't ignore exceptions
Threads
Synchronize access to shared mutable data
Avoid excessive synchronization
Never invoke wait outside a loop
Don't depend on the thread scheduler
Document thread safety
Avoid thread groups
Serialization
Implement Serializable judiciously
Consider using a custom serialized form
Write readObject methods defensively
Provide a readResolve method when necessary