On projects ranging from very small (10K lines of OO/C++) to very large systems (millions of lines of OO/C++) our experience has shown that this is a solvable problem. Here are some guidelines.
It is possible to keep the specification synchronized with the code because of the nature of specifications. Since specifications describe behavior in terms that are observable to the user, rather than in terms of the implementation, specifications tend to be relatively stable compared with the implementation. Furthermore, since all the other software components of the system are built by relying on the specification rather than the implementation (see FAQ 6.09), the specifications tend to stabilize fairly early in the product life cycle. So as a practical matter, the problem isn't keeping the specification synchronized with the code but the reverse: making sure the code is synchronized with the specification. In other words, once a lot of software has been written based on a particular specification, that specification is more stable than the underlying code that implements the specification, so the issue is making sure the code faithfully implements the specification rather than the other way around. Remember: specifications are prescriptive rather than descriptive. Specifications prescribe what the code must do rather than describe what the code already does. If the implementation of a member function and the member function's specification disagree, and if a lot of software was already built based on the specification, it is often easier to change the implementation to be consistent with the specification rather than the other way around. In contrast, when there is no explicit specification that programmers can rely on, the implementation ends up being the de facto specification. Once that happens any change to the implementation (including fixing bugs in some cases!) can break the user code. In those cases it is trivial to keep the specification and the implementation in sync (the implementation is the specification), but it makes the whole application brittle any change anywhere can trigger dozens of other changes. |