Correctness
Code that is “practically correct” is code that has been tested. Only the most trivial of programs is “obviously correct,” and formal verification is not yet practical for non-trivial programs. Testing is the only practical tool available for evaluating correctness. Code review (including pair programming) is also valuable, but it is not a substitute for testing the executable code against expected results.
Maintainability
Maintainable code is readable and testable. Without readability, code cannot easily be modified because it is hard to determine what the code is actually doing in the first place. Without testability, code cannot be modified because it is impossible to determine whether changes have the intended consequences.
Readability
Readable code is divided into chunks that are small enough to be easily described, because the human brain has a limited capacity for complexity and detail. “The competent programmer is fully aware of the strictly limited size of his own skull … .” [Dijkstra 1972]
Readable code must also be transparent: it says what it does and does what it says. The essential character of readable code is that it reduces the cognitive load on the reader, so the reader can easily see what the code is doing—without being faced with unnecessary detail. Code described as “clever” or “tricky” is rarely transparent; code that can be described as “elegant,” however, does not suffer that problem.
Another characteristic of readable code is good locality: all the code that manipulates some state is gathered together (conceptually, if not physically). This allows the reader to see what state transitions are possible and to confirm invariants.
Readability and Testability
Separation of concerns is vital for code to be readable and testable. Code that is concerned with one aspect of a problem should not be entangled with code that is concerned with another aspect of the problem. Such entanglement impairs both readability and testability: readability is impaired because the reader must think about two separate problems at the same time, and testability is impaired because the test harness has to deal with two sets of behaviors.Testability
For code to be testable, it should be structured to allow testing in isolation (unit testing). Unit testing allows explicit, executable specification of behavior. Unit testing also allows small changes to be tested, and small changes are much easier to make correctly because they minimize the cognitive burden on the maintainer.Performance
I mention performance last not because it is less important, but because it is notoriously seductive. “Premature optimization is the root of all evil.” [Knuth 1974] Measured performance and intuition often disagree, and time spent on optimization before the code is correct is almost always time better spent on getting an adequate solution sooner.And …
Finally, good programming is hard, and any strategy that makes it easier is valuable. One such strategy is to use existing software instead of creating new, when there is adequate confidence in the existing software’s suitability.
I’ve avoided using “object-oriented” or even “abstraction” in the above. That is because I am trying to identify the first principles of my design values, and these terms describe approaches that derive from those principles.