100% agree. The worst offenders imho are DRY and inheritance. In most cases it causes garbage code that adheres to some lofty goals but sucks to be maintained. We actually do the opposite of DRY: isolate behaviour, even when shared. If complex enough and shared: build a lib. But one use case = one app functionality. We are so happy and productive with that. Throw in ports + adapters and use cases (= one feature) and you're set.
You know what sucks more than fixing problems with inheritance? Fixing 20 different copies of the same bug, or just having to copy over dozens of methods in the first place. If you feel like inheritance is wrong, it's probably because you've got too many corner cases and too many responsibilities shoved into a class. Composition can help in such cases, but there's maybe no magic pattern if each object is too different from the rest.