When I just joined Microsoft in 1998, they had a very cool development career ladder document that explained how a level maps to technical (and leadership) capabilities, and what are the attributes of a developer on each level.
One of the entries for level 62 (college graduate starts at level 59; 95% of all developers peak at 63 or 64) was "Does not create unnecessary abstractions". I think the person who wrote it was a very, very good engineer.
A central promise of an Object Oriented Programming (OOP) is that code written in an object oriented way can be more easily reused. If you look at the history, however, there are very few OO libraries that achieved this status - iostream, STL, WTL, and, if you hold your nose, ATL, and MFC. Not too many for close to 20 years of C++ being in mainstream.
Why is that?
I think this is because truly reusable code is amazingly hard to write, and requires very, very smart people for very, very long time.
For starters, to write something reusable one must know quite a bit of what other developers want. This requires a lot of experience, a lot of research, and a lot of reflection.
Second, it requires a lot of verification - if you think that your code satisfies a requirement, but have never actually tried it, good chances are it will fail because you have forgotten an important detail.
Most people who write code they expect would be "reusable" never commit enough time and intelligence to do it for real. Instead, they write something that is designed to be "reusable", then hammer it into their subsystem, and declare a victory.
The cost - bulkier code that has a lot of never tested paths, potentially exploitable by an attacker, and is usually slower (if you want to know why it might be slower, think about how to make code more extendable by using virtual functions; then think about the cost of a virtual function call). To top it off, it took longer to develop.
My philosophy is to recognise that whenever you code for something you do not test, it will not work, no matter how hard you try. So don't even attempt it. Don't expect that other people will be using your code. Have it do exactly what is necessary for your current project, and no more. If indeed there comes an opportunity for reuse, you will change it then, when all requirements are clear.
Today though focus on task at hand and do it in a minimalistic and most efficient way. And if you do need a paradigm to rally around, let it be maintainability, not code reuse.