Completely agree. These rules simply do not lead to better outcomes in all cases. Looking at the rules and playing Devil's advocate for fun:
> Prefer polymorphism to “if/else” and “switch”
Algebraic data types and pattern matching (a more general version of switch), make many types of data transformation far easier to understand and maintain (versus e.g. the visitor pattern which uses adhoc polymorphism).
> Code should not know about the internals of objects it’s working with
This is interpreted by many as "don't expose data types". Actually some data types are safe to expose. We have a JSON library at work where the actual JSON data type is kept abstract and pattern matching cannot be used. This is despite the fact that JSON is a published (and stable) spec and therefore already exposed!
> Functions should be small
"Small" is a strange metric to optimise for, which is why I don't like Perl. Functions should be readable and easy to reason about. Let's optimise for "simple" instead.
> Functions should do one thing
This is not always practical or realistic advice. Most functions in OOP languages are procedures that will likely perform side effects in addition to returning a result (e.g. object methods). Should we also not do logging? :)
> “DRY” - Don’t Repeat Yourself
The cost of any abstraction must be weighed up against the repetition on a case-by-case basis. For example, many languages do not abstract the for-loop and effectively encourage users to write it out over and over again, because they have decided that the cost of abstracting it (internal iteration using higher-order functions) is too high.