How do you (individuals and organisations) manage your source to make
it easier to reuse? Do you specifically maintain a reuse library? And
if so, how do you index it to maximise your hit rate?
I don't and I have an admittedly controversial opinion here but I find the idea of maximizing code reuse counter-productive (I'm interpreting "maximizing" as prioritizing it above all other things rather than considering it as having both pros and cons to balance in consideration). I prefer instead to allow a healthy amount of redundant efforts in teams to slide in favor of decoupling and isolating each developer's module better. First before everyone starts disagreeing with me left and right, I think we can agree upon some things:
- Reusing buggy code that will have you spending hours debugging other people's code is not desirable.
- Reusing code that balances such a wide range of disparate needs that it barely satisfies your own needs and requires you to jump through a lot of hoops to ultimately get an awkward and inefficient solution is undesirable.
- Reusing code that constantly requires design changes and goes through deprecations of a kind which will require you to rewrite the code using it every 6 months is undesirable if you could have just implemented the solution yourself in half an hour in ways that don't need design changes in the future since it's only serving your precise needs.
- A codebase filled with alien-looking code is undesirable over one that uses more of the language and standard library in idiomatic and familiar ways, even if that requires slightly more code.
- Developers stepping all over each other's toes because both of them want to make incompatible changes to the same design while fighting and arguing and making changes which cause bugs in each other's implementations is undesirable.
- Throwing a boatload of dependencies to immature designs that have not proven themselves (not had thorough test coverage, not had the time to really soundproof the design and make sure it effectively satisfies user-end needs without requiring further design changes) is undesirable.
- Having to include/import/link a boatload of libraries and classes/functions with the most complex build script to write something simple is undesirable.
- Most of all, reusing code in a way that costs far more time both in the short and long run than not reusing it is undesirable.
Hopefully we can at least agree on these points. The problem I've found with maximizing code reuse from overly-enthusiastic colleagues was that it often lead to one or more of the problems above. It wasn't directly the enthusiasm for code reuse that was the fundamental problem but that the priorities were skewed towards code reuse rather than test coverage, soundproofing designs, making sure things are mature enough before we reuse them like crazy, and so forth.
Naturally if all the code we reused worked beautifully, had thorough test coverage, was proven to fulfill the needs of everything using it in ways that were far more productive than not reusing it, and didn't have to go through any design changes for years on end, I would be ecstatic about code reuse. But my experiences often found things falling far short of this ideal in ways where code reuse was arguably becoming the maintenance problem rather than the solution.
How do you (individuals and organisations) manage your source to make
it easier to reuse? Do you specifically maintain a reuse library? And
if so, how do you index it to maximise your hit rate?
So, again I don't seek to "maximize" code reuse among proprietary code written internally among the team. I seek to make sure the team doesn't spend enormous amount of time on redundant effort, but I let things slide quite a bit if both the physicists and the rendering guys both implement their own axis-aligned bounding box class, e.g. It's not necessarily even that redundant, since the physicist might use min/max representations which are more efficient for his purpose while the rendering developer might use center/half-size representations. I do try to make sure we reuse as much of the standard library when possible, because that's code reuse of a kind that is practically guaranteed to be solid, ultra well-tested, and not require further design changes (other teams are spending a boatload of their time to make sure of that).
Instead I shift the focus on testing. A module duplicating a little bit of code here and there is totally fine if you ask me if it's working beautifully in ways that make users really happy, has thorough test coverage, and doesn't warrant endless changes. We accept such duplication all the time when we use third party libraries who likely duplicate some code that we also have in our internal codebase. It's not an issue there when the redundancy doesn't lead to redundant maintenance efforts.
So I suggest just relaxing the idea of maximizing code reuse just a little bit. But if you want to make it easy as possible to reuse the really solid, well-tested, non-trivial code, then I've found it far more helpful to organize very singular-purpose libraries, like a "math" library, an "image" processing library, etc. -- instead of trying to fuse them all together into something like "core" or "common". The latter types tend to tempt developers to throw in all kinds of eclectic utility functions which barely benefit the team using them, and mostly it tends to become messy in ways where it starts to become difficult to find anything of interest.