I am afraid that for the time being the answer to these questions is "No".
Sure, we have all sorts of practices (e.g.: test as you write), principles (avoid duplicated code), and suggestions (e.g.: try to make your classes loosely coupled), but these are merely operational directives which are believed to produce a "good" program. The nature of a "good" program is still largely undefined.
Actually what we (software engineers) look for is some set of ''target functions'' which can be quantitatively measure the quality of the program. With such functions the task of making a better program boils down to maximizing the values reported by these functions for that program.
In the world of algorithms we already have two dominant target functions: speed and memory consumption. These functions can be easily measured if we have a concrete implementation of the algorithm. Moreover, in many cases we can even express these functions as a simple mathematical expression, known as "time complexity" or "space complexity".
On the other hand, in the world of software engineering things are much more fluid. To see that let's try to think of such target functions that can describe a program's quality: development time till first release; development time till second release; number of bugs; time needed to introduce a new developer to the code; time for solving a bug; time for replacing a certain part with another; etc.
These functions cannot be easily measured. We don't have a device that can measure the number of bugs in the program, the same way a simple stop-watch can measure the execution time of an algorithm.
In addition there is also the problem of inverse correlation. For example, it is reasonable to expect that a design that minimzes the development time might lead to an increased number of bugs. This means that even if we had devices for measuring these functions, program's quality would still be a relative concept: A program that is "good" in one sense is likely to be "bad" in another.
My point is that there is no such thing as an absolutely good program. When we programmers argue about design we tend to use absolute terms, such as: "this design is better than the other one". We allow ourselves do that because we have an implicit assumption about the target function that is appropriate for the project we are working on.
Personally, I adopted the following practice, in order to expose this subliminal assumption- When I evaluate a design decision I try answer these two questions: (1) Which target functions am I improving? (2) Which target functions will get worse as a result of this decision?
These questions are not as easy as they look. Providing intelligent answers to these questions requires good design skills.