Re-use is now an established trend. And that's a good thing.
But we go about it in a very back-to-front way.
Primarily, code re-use tends to be a very code-oriented practice. We look at a piece of code, its functionality, performance and other characteristics and decide it makes a good candidate for re-use. And so, it gets re-used. And we find that in the re-use, it didn't quite do what we wanted. We then have to spend a lot of effort re-engineering it towards our needs. We bang a lot of square pegs into round holes.
What went wrong? We put the cart before the horse. We attempted to re-use code, a derived artefact of the software engineering process without considering the original, motivating cause of that engineering effort - the requirements.
Written, implemented code is a concrete solution to some specified problem. The requirements for the code are a pure expression of the problem we need to solve. In attempting to directly re-use code without comparison or consideration of the requirements that led to that code, we're hoping that one solution solves two problems. We're hoping that a given solution can solve problems that were not known, or at least addressed during implementation.
More explicit consideration of the requirements in the re-use process has potential benefits for all parties. For the client code, wishing to re-use some candidate piece of code, we can ensure that it is a good fit for our requirements. If there is a mismatch between requirements, this clearly identifies where work is needed. These conflicting requirements can now inform the design process, to ensure that the any modifications to the re-used code are implemented appropriately, and not simply bolted on, polluting the code. We can more accurately estimate the work required, rather than attempting to untangle the specifics of implementation, piece, by piece, by piece.