I’m required to teach DSA in Java, so I lay down a couple rules early in the course that prohibit 95% of the nonsense garbage that unconstrained OOP allows. Granted, neither of these rules is original or novel, but they are rarely acknowledged in educational settings:
1. All public methods must implement an interface, no exceptions. 2. The super implementation must be called if overriding a non-abstract method.
The end result of strict adherence to these rules is basically that every feature will look like a GoF design pattern. True creative freedom emerges through constraints, because the only allowable designs are the ones that are proven to be maximally extensible and composable.
but sometimes that is not worth it... IOW, it optimizes only to a couple of variables.
it's important not to lose sight of the ultimate goal: to get the machine to do what we want with the least amount of total human attention throughout the entire lifetime of the software.
it's a typical trap for good/idealist programmers to spend too much time on code that should already have been re-written, or not even written to begin with (because faster iteration can help refining the model/understanding, which in turn may lead to abandoning bad paths whose implementation should never have been refined to a better quality implementation).
i think it's a more important principle to always mark kludges and punts in the code and the design.
IOW sloppiness is allowed, but only when it's explicitly marked formally in code, and when not possible, then informally in comments and docs.
but then this entire discussion highly depends on the problem domain (e.g. on the cost of the various failures, etc).