Componentization is a seductive software development practice. Simply put, software componentization is when you break your software system down into smaller easily identifiable pieces that have well-defined interfaces – and you do this in a specific way (i.e. by following a component model).
The promise of software componentization is five-fold:
- Complexity Management: having a manageable unit of software functionality enables design time tools and run time tools to help developers divide and conquer their increasingly unwieldy device software.
- Product Flexibility: the ability to easily replace a component when product requirements change provides product flexibility.
- Product Reliability: matured components that meet well-defined specifications and get re-used increases product reliability.
- Time-to-Market: re-use of components in new products accelerates product development and lowers cost
- Collaboration: a common format for software implementations helps multiple companies collaborate more easily.
A software component must satisfy these conditions: 1) it is a unit of functionality with a well-defined interface; 2) it is a unit of composition in a larger system; and 3) it conforms to some known component model. A component model must prescribe a) how a component is described and what the description contains; and b) how components bind to each other at design time and/or at runtime.
Most software developers already create products or subsystems out of multiple pieces of previously written code – often augmented with something new – and they usually know how to replace those pieces with alternate implementations. Sometimes it is easy to replace an implementation, sometimes not. I have found that when a piece of software enforces a strict interface (preferably as small as possible) and keeps as much of the implementation as possible private then it gets easier (cheaper) to maintain that piece of software over time. And, as a bonus it often gets easier to reuse that piece of software since you can look at the interface and understand what you are getting. If you know what components it uses directly or indirectly, you can easily know if it can be quickly ported to a new environment or not.
So if we have been doing this all along, why don’t we have a huge Chinese menus of well-defined components to choose from when we build reliable device software? I think this is because the traditional development process is to break down a large problem into sub-problems and solve those. We call that decomposition. To benefit from software componentization we need to have a paradigm shift from decomposition-based thinking to composition-based thinking. Design by composition starts by putting existing components together towards the product requirements. And by investing in successive refinement in the components (through component parameterization or component reimplementation while maintaining its same interface) we will in the long run end up with an arsenal of componentry that can be used to build products more cheaply and faster.
This is a short-term vs. long-term issue in many cases. By implementing exactly what is needed we can make that short-term product and then evolve its implementation. However by investing in a component-based approach to build components that are well-defined and flexible we get the payoff when we re-use it – the next time around – and component evolution (including bug fixes) will payoff multiplicatively.