Reusability is a word we bandy around when we're talking about creating good software. I don't think many of us sit down to get clear about exactly what we mean by it.
It might be helpful to look at the different scopes you see re-usable software in real life:
- Component level - a reusable chunk of code made for reuse within a named group of statements (class, function, closure, module, whatever you like). An example of this is that little private method you defined to reduce code duplication inside a class.
- Project level - a named chunk of code or component designed for reuse accross a codebase. This could be a utility function, a more complex piece of functionality or indeed your core domain model.
- Ecosystem level - Code designed for reuse in different projects. In Ruby we have gems, other languages have their own package managers.
The scope starts out small at the top of that list (reusable within a single file) and progresses to large at the bottom (reusable accross all projects).
For component level reusable code, you won't need much documentation and can change the API at will. With a smaller reusability scope, your code is more amenable to change. It's not very easy to reuse however: you'll likely have to read the code line for line to reapply it elsewhere at this stage.
As you progress up to project level reusable code, you start having to maintain a stable API. The more your code gets reused, the further locked in you are. The developers that have to use your code would also appreciate not having to actually read it, so you'll have to write some documentation. The code at this stage will handle a wider variety of use cases.
At ecosystem level reusable code, if you're doing it right you're using semantic versioning, which requires a re-release and version bump of your library at every change that breaks the API. You'll need extensive documentation, in some cases within the source code itself. The code here though is no longer tied into the details of your project, it's reusable across a much larger variety of domains. The code is less amenable to change at this scope level, but it applies to many more situations and is easier to reuse.
Your approach to building and working with a component will be different based on where in that scope your code sits. You can think less about neat abstractions and how the code will interact with other parts of your system if it's just a private method sitting in a class somewhere. You'll need more thought and effort to build something more generally re-usable.