When C++ was first introduced many benefits such as code reuse, portability and scalability were promised, but somehow these benefits failed to eventuate. It didn’t take too long before most people in the embedded world decided that the promises were just hype, and settled down to using C++ as a slightly better version of C.
However, the failure of C++ to deliver the promised benefits didn’t happen because C++ was inadequate. It happened because people didn’t adjust their approach to software design. The continued use of old approaches to software design resulted in the old problems of non-reusable, non-portable and non-scalable software.
By itself, using C++ doesn’t make code reusable, and it doesn’t even make a design object-oriented. The object-oriented features of C++ only provide the promised benefits if they’re coupled with an object-oriented design.
The same techniques which make code reusable also bring other benefits. Bad design results in a death spiral which causes large projects to become unexpectedly difficult to enhance or even debug.
But the type of object-oriented design that will be described here produces a virtuous spiral with significant benefits, some of which are totally unanticipated when you start down this path:
1. fewer bugs;
2. bugs are fixed more easily;
3. products are completed more quickly;
4. large systems can be created which would otherwise fail because of their complexity;
5. software can be written when hardware is unavailable;
6. product requirements are communicated more easily and accurately between customers and engineers;
7. greater agility to deal with changing requirements;
8. better documentation.
Achieving these benefits requires a change in thinking about design, not just a change of language from C to C++. The Object-Oriented C++ described here rests on three simple principles:
1. The design is structured in terms of things rather than in terms of functionality;
2. The design should model the problem domain, not the implementation domain;
3. Elements within the design are massively decoupled from each other.
OO-based design versus functional decomposition: Isn’t it obvious?
The most obvious and intuitive aspect of object-oriented design is also the one which is least understood: an object-oriented design is organized around objects.
In contrast, the traditional design by functional decomposition which still dominates the embedded world is organized around functionality.
Here is another definition which might make this distinction clearer: object-oriented designs are organized around nouns, functional designs are organized around verbs.
A designer doing a functional decomposition asks “what does this system do?”, but an object-oriented designer asks “what things are in this system?”. This simple change of perspective is the single greatest reason why object-oriented designs can achieve greater reuse than functional decompositions. Code reuse is one thing that drives the virtuous spiral, resulting in faster development cycles, fewer bugs in the resulting code, and better documentation.
I’m using the phrase “code reuse” not to mean the “cut and paste” reuse which is as much as most companies ever achieve. Instead, “code reuse” means the ability to use the same source files across multiple projects with no