1. Too much low-level grinding.
I have a class with 3 fields. Why do I have to write a class definition, default constructor, constructor taking the 3 fields, destructor (remembering virtual if it's a base class), copy constructor or move constructor? If I want equality on that class, I need to spell out when an object is equal. If I want ordered, I need to tell exactly how to compute order. If a field is a vector, I have to do the above for a vector of things. So that's soon 150-200 lines of code for a class with 3 fields and something basic like order. Why? Yes you could possibly want to do it in that detail in about 1 in a 1000, but for the other 999 classes???
2. Too simple to make a convoluted mess.
Some people completely reject OO, as it is too complicated, and stick with C style coding. While I disagree with their solution, they do have a point, OO makes it extremely simple to merge different but related pieces of code into the same object, or setup references to other objects etc. It's very simple to make a huge mess by connecting stuff that shouldn't be connected in that way, and nothing prevents that from happening. You can see it by the difficulties that beginners have in using inheritance correctly. I recently figured out that getting an object from a collection by equality may be a bad idea too, at least it is from a math point of view.
3. Too many things at the same time.
When we design a program, we use a divide and conqueror approach in the design. Yet when we code, we code all concerns at the same time. How I write a class definition wrt the order of fields has impact on the performance of the system. The type of container affects performance and memory footprint as well.
Why is there no implementation path from logic design to dealing with timing, memory, and performance?