I work primarily on lower level components in biotech and I see this whenever I start to dig into the "Enterprise" code base. It takes me _far_ too much time to find the code that, you know... actually does something. While searching I'm just wading through file after file which contains nothing more than types and small wrappers around other small wrappers (around other small wrappers...) It drives me nuts. So much code and so little actually happening.
But how much of that is small functions, and how much is just people blindly applying pattern after pattern while optimizing for business use-cases that are unlikely to ever emerge?
That doesn't mean the patterns are bad, it doesn't mean small functions are bad, it just means the person who implemented them lacked good judgement. Good judgement is somewhat subjective. Fortunately, we can combat this subjectivity by looking at what the long term $ of a decision (programmer time, onboarding time, resources used...), how a particular decision advances an organization's objectives, etc.
We need functionality, not code. That functionality exists to support (what should be) clearly defined interests and goals. "Right" code is code that serves the functionality, and therefore the goals, best.
It's the latter. Too much abstraction for no good reason because it's "what you do". I wasn't throwing out an opinion on the primary concern of the topic. In my experience, good devs write good code.
The author disagrees. She's saying people tend to use too much abstraction, so the DRY principle (not principal) is actively harmful as it encourages more of a bad thing. The trouble with abstraction is it hides things from view.
To make this concrete consider a codebase with lots of 1-10 line functions spread amongst lots of files, vs one with half the functions in half the files which are 10-20 lines instead. The work has to get done somewhere, and lots of shorter functions of just a few lines and keeping it dry (no repetition) tends to lead to lots of classes/files/modules which don't do much alone calling each other, making it much harder to reason about execution or read the code.
Rather than functions with just a few lines or with hundreds of lines, I imagine she's talking about functions 10-100 lines long on average, with exceptions where reasonable. There is a middle ground here where a function is more readable and crucially doesn't force you to jump around much to find out what work it does.
There's a good quote from Sandi Metz in the article: "duplication is far cheaper than the wrong abstraction"