When discussing principles Fowler argued that a good principle should be universal: other than a few extremely rare cases, a good principle should hold for all kinds of programs, domains and languages. That is why good principles are hard to find.
Side note: After this talk I realized that many of the "principles" for producing high-quality code are conditioned by a trade-off and thus should be considered as Practices rather Principles. A quick example for such a trade-off is cohesion vs. coupling: if your class is doing too many things you can refactor some of its functionality into other classes. The refactored class will be more coherent, but also more coupled: its sensitivity to changes in other classes has increased.
If I recall correctly, Fowler mentioned two example principles: (1) Eliminate Code Duplication and (2) Separate User Interface Code.
Below are two additional notions ideas, which should qualify as principles:
- Abstract your Operations as Values - Your program should be structured such that its operations can be abstracted over. This abstract-ability means that operations can be stored in variables, polymorphic-ally executed, rolled-back, or composed. Applying this principle is trivial in Functional Programming (where every function is also a value). In the OO world you will usually need the Command pattern to achieve this type of abstraction.
Once the operations are represented as run-time values it can easily support features such as: access control, redo/undo, filtering, monitoring, automation and even transaction safety.
- POJO: Plain Old Java Objects - Sophisticated OO framework give rise to complex classes which cannot be easily used by the programmer. For example, although writing a servlet class is a fairly simple task (you just need to subclass Servlet and overrride its doGet() method) creating a fully working instance of this class is practically impossible: your code needs to create many other objects (ServletRequest, ServletContext, ...) and feed these into the Servlet object. The cost - in programming time - of writing the code for creating these additional objects is usually overwhelming.
Of course, the servlet container (Tomcat) can do this for you when the servlet is deployed, but there are other scenarios where you may want to instantiate a servlet: How can you test a servlet if you can't create one? How can a stand-alone application reuse the servlet's code?
This principles states that you should place the vast majority of your code in POJO classes (If you do have to use some framework-managed class just write a very simple class that delegates to a POJO). In other words: always prefer the design with more POJO code.