Ah yes my greatest sympathies. I have struggled long with these problems.
I would often sketch out solutions and draw diagrams. Try to identify common abstractions and then code something.
My solutions would usually rely on some abstract concepts which I would document, as they would be important to understand the overal solution.
Abstractions often allow you to reduce code duplication right, because you see similar patterns repeated. You extract that commonality as something abstract, which you can reuse.
But the problem I found was that people would not get this code. They would not be able to extend and use it. Trying to understand why, I realized it was because nobody ever bothered to read the documentation I wrote in the code. I would document my interfaces extensively, so you would get the concepts I used.
However documentation has become a sort of swearword in this industry it seems. "Code smell" they like to call it now. So people almost seem to make a point of not reading it.
The end result is that you cannot work with abstractions. People seems to handle lots of code duplication and very concrete objects. You need less documentation for this, because there isn't much abstract to document. Each object is just one obvious and concrete thing.
The problem is of course that now you can do minimal of reuse.
While this may seem a bit different than what you describe, I think it fundamentally points to the same underlying problem. People don't care to think about the abstract. To draw diagrams and relations.
Not quite sure how encourage this. I would not say I really learned it at universtiy. I don't think I was quite ready to think in terms of diagrams while a student.