Reuse Implies Coupling
Most of the Big Topics (with a capital b and t) in the discussion about software engineering and practices are about improving productivity, and avoiding mistakes. Reuse has the potential to address both dimensions. It can improve your productivity since you needn't write that code yourself that you reuse from elsewhere. And after code has been employed (reused) many times, it can safety be considered tested and proven more than your average piece of code.
No surprise that reuse, and all the debate on how to achieve it, is around for decades. Object oriented programming was about reuse, component ware, parts of open source development, and model driven architecture with all possibilities for variation.
At the same time, software reuse has hardly lived up to its promises. I think this has multiple causes:
- it is hard to write reusable code;
- it is hard to reuse code;
- reuse implies coupling.
The first topic has to do with interface design, negotiations with many customers, and marketing - and is covered by other aticles here that give sound advice how to design good interfaces.
The second has two aspects: it is mentally hart to want to reuse, and often technically hard to do so then. It works fine with operating systems, libraries, middleware. And we have enjoyed some components from the open source projects. However, we often fail to reuse software from our colleagues or from unrelated projects within our company. Not only is it way more sexy to design something yourself, and you are surely way better at design than any of your peers. It also makes you depend on somebody else.
This dependency is the first aspect of coupling introduced by reuse. You are not the smith of your own luck any longer. You will be fine as long as the code you reuse is considered a commodity, something you really really don't want to do yourself. Otherwise, you will find good reasons why this code shouldn't be reused, including that you depend on something that you don't own and can't maintain, and that is not reliably maintained by somebody else. Your peers project manager will hardly agree to spending additional effort in supporting an unrelated team. Yes, most companies work this way.
The other facette of coupling comes when you actually implement reuse within your company. All of a sudden, the provider and all of the reusers are coupled to each other. Each feature or change needs debates about its relevance and priority, when it shall be introduced, and which interfaces will be affected. All the reuser project struggle with each other and with the provider to have their expectation covered first.
Looking at reuse endeavors at different cmpanies, these concerns are real. Successfully reused software typically brings a tremendous amount of management and overhead.
Alternatively, it requires a contemplative mindset of all involved parties. The other scenario to cope with reuse is to allow for deviations of the reused code for different projects. The projects evolve their own variant, reducing their coupling on the expenses of having less quality for free. This is not yet reuse, though. It becomes reuse when some developer is responible to integrate all variants every once in a while, and to evolve a baseline that becomes more stable over the months and years. With this mindset of sustainability over accountability, your company might be able to achieve the prerequisite for successful reuse: software that is considered a commodity.
BACKUP - to be deleted sometime...
There are many items that we just reuse, and have reused for decades without much thought: operating systems, libraries, middleware. And we have enjoyed some components from the open source projects. So, did we create our own software, reusable among our own projects? We did, but with limited success. Here is some of the reason:
- reuse requires a first user. Attempts to create a library for common use, without having a real need in some real project that spends real time and money, remaing pointless.
- reuse requires a second user. Once used, most of the code is not reused in a different project.
Resaons against reuse:
- not invented here
- crappy quality: interfaces
- crappy quality: dependencies
- crappy quality: performance (in the 2nd users scenarios)
Even if you have overcoem all this, and started to develop reusable components in-house. You will find that sooner or later you have three different parties. (1) the creators and maintainers of the reused component; (2) the projects that already use the component; (3) the projects that are about to reuse that component.
The different groups have strongly opposing desires. Completed projects strive to avoid any changes to the once published component, since each change introduces some risk and some work. Starting projects strive to adapt the component also to their needs, i.e. they long for changes. Unless you have reached a very stable state (see ->library), you will have some debate here. Not just about interfaces and technology. You'll be surprised to find that now different projects are influencing the same code base, and people, and their schedules suddenly are coupled since some action for one of them causes work in the other one.
Do not make your code depend on some file that is intended to change as the project progresses.
It is very convenient to have a global file that lists all error codes in the system. When starting the new component, you proudly add a handful: look, I am a part of this! Only to find your colleagues moan about the extra build time. How dare you change this file?
Couldn't you just do what everybody does:
- reuse some error codes that are already in there.
- when existing codes don't match the intended meaning, document their specific meaning in your component documentation.
error.h file was intended to provide a great place to look for the meaning of codes. At the same time, it is a central component that is intended to change as the project proceeds. So it is your base, but it is quicksand.
How to get out? Consider this:
- real generic error messages (in the style of STL exceptions)
- a distinct
error.hfile per component