|
Re: Const, RTTI, and Efficiency
|
Posted: Dec 19, 2003 9:58 AM
|
|
First of all, I would like to say that in my experience, a consistent use of constness really does bring a lot. It allows to cut out about 80% of the code to consider when searching for bugs that accidentally modify data when they should'nt. But, as Scott has put it out, const usage spreads throughout the code, dividing it into two parts: the 20% that modify some piece of data, and the remaining 80% that just read data and compute something new from it.
Most developpers complain about using consts, because there is an additional problem to consider besides the spread effect.
This has to do with abstraction levels. The C++ const keyword is technical in nature, hence its semantic is also purely technical. It just means that the underlying memory protected by the const is unalterable, nothing more. But the programmer's intention is semantic in essence, or more at a business level. When I say that an object is const, I mean that some strong invariant about its state should be maintained, but not necessarily that no single bit of it can be modified.
A classical example is the correct implementation of caching. When computing some complicated value based on several attributes of an object, the computation itself should obviously be expressed as semantically const, because the computation does not change the attributes it relies on, which are the constituents of the object's internal state. But if caching is added at a later stage, a technical problem makes surface: the internal attribute used for caching is changed the first time the computation is done, as well as some flag saying that the cache is valid, thus avoiding the computation the second time it is invoked. Both the cached value and the flag must be viewed as redundant data not directly contributing to the object state, hence should be modifyable, although the computation method should still remain const.
Fortunately, C++ has a way to allow this: the mutable keyword, that should be used to declare these two special attributes.
Most programmers don't know about it, for several reasons: - the problematic behind (this difference in abstraction levels) is poorly understood. - most books don't speak about that, because it is considered an advanced feature, or their authors did not understand it themselves. - the keyword is relatively new and not considered useful, because most people already have abandoned the const way of splitting the code world in two for the reasons mentioned earlier.
So the correct use of constness implies the correct understanding of abstraction levels and mutability. But even for abstraction lovers, the const - mutable pair is not easy to use correctly. In particular, a correct analysis of the very nature of an attribute, that is does it belong to the intrinsic state of an object, or is it only a redundant piece of information, is difficult. It implies invariant analysis, and hooops, we are back to design by contract.
It is not only necessary to have a clear picture of the methods' responsibilities, but also of the class as a whole, in order to be able to formulate cleary a class invariant. Then to make implementation decisions about the most efficient way to implement the object's state without redundancy in the information theoretical sense, then add peripherical attributes necessary to provide an elegant or efficient implementation (or both) which do not contribute to maintain state. These ones should be declared mutable at first.
Then the methods can be considered, and the ones that do not affect the state (semantically speaking) should be declared const. To go further down these logical considerations, this implies that there could exist methods that do not technically speaking alter the memory representation of the object, but should nonetheless not be declared const if they sematically alter its state (these cases are rare, but exist nonetheless).
Summary: the correct usage of constness (in C++ or potentially every other language) implies to take some distance from the code, i.e. to formalize a design that is distinct from the implementation. Who spoke of modeling ?
|
|