What is the purpose of object orientation?
If you, like me, first encountered the term in the popular working programmer literature of the '90s (or if you've read Microserfs), you might have heard that the purpose of OO is to enable the deliberate reuse of unique and well-defined software components.
If you learned structured programming, whether earlier in the history of programming language development or because objects were a fad until Sun's marketing budget displaced IBM's marketing budget, you might have heard that the purpose of functions is to enable the deliberate reuse of unique and well-defined software components.
I write this knowing full well that in a few minutes I need to modify a piece of code which uses multiple CPAN modules, many of them defined, tested, deployed, and loved very well. With that in mind, I still believe that reuse as a primary design principle is often a fool's goal.
Last week's example of abstraction versus mock objects elicited thoughtful comments from Zbigniew Lukasiak and Andreas Mock relating to the single responsibility principle, design patterns, and dependency injection. These concerns are important in the sense that contrast and shading and hue are important concerns in creating great artwork.
Yet somehow the false notion that design is primarily an exercise in identifying, codifying, and extracting reusable components is pervasive, especially in literature intended for novices. (Perhaps novices sigh with relief when they finally get a single function or class working correctly, thinking to themselves "Thank goodness I shall never do this again!")
In 1999 I might not have created a helper class to solve my testing problem from last week. (Why multiply entities unnecessarily? I'm not writing ravioli code here!) I might have struggled through mocking DBIC row objects and priding myself on the thoroughness of my testing of all of the picky little details.
In 2011 I congratulate myself more on the code I don't have to write—not because I'm reusing implementation details but because I've minimized the details any particular piece of code has to understand.
That's why the Modern Perl book explains functions primarily as a way of naming and encapsulating discrete units of behavior and objects as discrete identities with single, well-defined responsibilities.
Reuse is well and good when it happens, but reuse happens best because of sensible design. It's not the primary goal of software design. Nor should it be. It's a serendipity born of the fundamental design concerns of naming and encapsulation.
Let us teach these useful truths to novices instead of the airy lies they will waste their time pursuing.
On the other hand, these issues are very related. A good, concrete test for "good" software (or classes, or functions, etc) is "how hard would this be to use in some context other than this one?". Not because you'd necessarily ever want to do that, but because it's a lot easier of a concept to grasp than "has a single, well-defined responsibility" (which, to a new programmer, can be very vague), but tends to at least come close to that goal (through a similar serendipity to what you were talking about, just in the opposite direction). Eventually they should learn how to use encapsulation and abstraction for their own sake, but I don't think that reuse is a bad way to introduce the concepts.
Code is not reusable until it is reused. Planning for reuse is practically difficult because reuse patterns are hard to predict with precision. And it's hard enough to solve the problems at hand, let along future problems that may never arise.
cf Fred Brooks: "... such advances [in OOP] can do no more than to remove all the accidental difficulties from the expression of the design. The complexity of the design itself is essential, and such attacks make no change whatever in that." http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.6363&rep=rep1&type=pdf
In the third paragraph remove the word "often". No wiggle room is needed.