An adage in Software Engineering goes like
Before software can be reusable it first has to be usable.
— Ralph Johnson
Reusability is a highly desirable attribute in Software Engineering. It is known to save time (at times) and it makes robust software. It’s the magic bullet! There are various levels at which reusability can be achieved in both ‘the what’ and ‘the how’ aspects in software. Achieving high degree of reusability is hard, it takes effort in that direction. For any enterprise the relevant questions will be what is the cost of making software highly reusable, next is when to put in the effort to build reusability into software, and how much would be gained in return.
Let us take these questions one by one.
What is the cost of building in reusability?
For the uninitiated, the cost seems to be negligible. It is often underestimated and taken for granted that if good design principles / coding practices are followed, it will result into good amount of reusability. In theory, following good design practices will make code more readable and do what it is supposed to in an elegant, efficient and sophisticated way. It will not however, always make it reusable. Maintainability is the quality which should be at the centre of concern, maintainability and reuse are related in a vague way. If the software is dominating or even surviving well for over 5 or more years that means it is maintainable and a lot of code base / components are being reused, it is serving the requirements for a long duration.
Generality (spectrum of reuse) and abstractness are directly related, the more generic it is, the more abstract it becomes.
If software requirements are being thought of from a generic perspective in order to serve a wider audience, they will be more abstract and disconnected from the direct user requirements. That means the drive for developing is not coming from the core business it is something which has to be… invented. As an example, consider computer games, an engine is something which is reusable, while a game may not be. Building an engine without real requirements, trying to imagine what future games might need is a tough ask, and a bit academic in nature. It needs time and expertise to know the domain before something like this can be done. Building an engine however, is for a very high level of reuse, probably considering 100s of games being churned out using it. It is a complete software in itself whose core requirement is being reusable and doing everything what a game needs. The customers are developers. As one can observe, the scope of building an engine is exponentially growing and so it’s cost! It would be a big decision to invest into building something like this upfront.
Next level (lower) would be frameworks, then services, libraries, components and then code. The cost involved would go up as the generality increases. Building new languages, database engines, frameworks involve a huge cost. Sometimes the business might want to build engines or invent things to be ahead of the competition and maybe forecast returns in future, for that the other side of business needs to sustain the cost of building reusability.
When to put in the effort to make it reusable?
In case if someone else is waiting in the wings for a software requirement similar to the one which is being developed, then it makes sense to put in effort to make the code reusable or build components. However, prioritising reusability over fulfiling the core requirements of software is a recipe for disaster. It has to do one / few things right, rather than be an allrounder which can do a bit of everything but can’t completely do one thing. Perhaps, an analysis should be done for why there are similar requirements in different softwares. Sometimes there might be business reasons for having similar softwares. Sometimes less is more…
Form follows function
Emergence principle: Let the modules emerge
While the business requirements are being satisfied by the software a vigilant eye can always spot the components emerge from within software solutions. The components will sprout from the main features of the software and when the start to ripen on the functional software they can be easily plucked and groomed into proper shape.
There is another train of thought, to build everything in a Service Oriented Architecture (microservices). That means everything is like building blocks (lego) you can plug in anything. It sounds good in theory, however software components are not exactly plug and play, they have different interfaces - which often need customisation (adapters). Every pluggable piece has its own specifications and quirks. Not everything will be factory made. This is a reasonably good strategy however, attention should be paid to how much of code is actually consumed in the application. All code should have a purpose. There is a tendency of over engineer in case of service oriented architecture.
From a domain driven design, the focus is on accurately modelling the domain and solving the core business problem.
As long as there is loose coupling in the code, it is a conducive environment to sprout reusable components or services. This can be part of the main design principles while building the core software. Services based on contracts can always be provided on top of the core components once they are ready.
Core software will have schedules, reusability will not.
How much would be gained in return?
In theory reusable components are expected to work straight off the shelf. Realistically, there is an effort required to consume the reusable components or services to build software solutions. More out of the box’d ness the solution has the more narrow its applicability and the vice versa.
Another interesting saying in software engineering goes like:
“Telling a programmer there’s already a library to do X is like telling a songwriter there’s already a song about love.” - Pete Cordell
It’s so true, as there are so many subtle differences yet, it depends on how deep one wants to go.