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.