Artima.com has published Part IV of an interview with Scott Meyers in which he discusses the utility of const, the appropriate time to use RTTI, a good attitude about efficiency, and his current quest for general programming principles.

I have a two-pronged approach to efficiency. First, when you're designing the application, you have to consider efficiency. I'm assuming that you, as the designer, are designing something you know something about. You must make some educated guesses about where you think performance bottlenecks will and will not exist. That means efficiency might appear early in the design, just because you know certain things about the application in general. I don't think it's inappropriate to keep efficiency in mind when you design. You don't want to design something that will be inherently inefficient.

The first prong of my two-pronged approach, then, is to keep efficiency in mind from the beginning. Don't completely ignore efficiency up front in favor of fine tuning later. You shouldn't bend over backwards for efficiency up front. Design so things will be efficient enough most of the time. Shoot for clear, straightforward, and maintainable code, but try to avoid introducing gratuitous inefficiencies.

The second prong is fine tune later with profiling. If you find some bottlenecks in the program by running it and profiling, then go back and rewrite the presumably localized parts of the code to improve efficiency.

Serious efficiency problems arise when people design systems with the attitude that, "We're just going to worry about correctness first. We won't even think about efficiency until later." The results have been pretty disastrous.

I think const makes it easy to have read-only object references in C++, and the lack of a corresponding language feature in Java makes trying to have read-only object references pretty much infeasible. Which is a shame because I think read-only object references are tremendously valuable.

> I think const makes it easy to have read-only> object references in C++, and the lack of a corresponding> language feature in Java makes trying to have read-only> object references pretty much infeasible.> Which is a shame because I think read-only object> t references are tremendously valuable.

I remember back in 1996, I got the sense that everyone who came to Java from C++ had one big complaint. Everybody had some pet feature of C++ that they really missed in Java. But there wasn't one thing, there were many. Different people had different complaints, but everybody seemed to have at least one main complaint.

Oddly enough, my complaint--the one main feature of C++ I missed in Java--was the use of const to make read-only object references. C++ has the ability to mark methods const and the compiler will ensure they don't change the state of the object. The compiler makes sure you only call const methods from const references. I really liked that about C++, and I was bummed it didn't exist in Java. But after perhaps 6 months of programming in Java, I realized I was doing just fine without it. I haven't really thought about it much since then.

> after perhaps 6 months of programming in Java, I realized> I was doing just fine without it. I haven't really thought> about it much since then.

I think part of it is that Java uses different patterns to achieve the same thing.Immutable objects are much more common in Java, and they attempt to solve the same problem. You don't need to declare that your String is const - it's always const.

However, Collections tend to break that, and while Collections.unmodifiableList() is the solution, people tend not to use it enough.

And the reason goes back to Scott's last point, components should be easy to use correctly and hard to use incorrectly.

Having to use blah.doSomething( Collections.unmodifiableList(myList) ) places the onus back onto the user to enforce a constraint on the component. The user is saying "I'm not going to let you modify this list", but often that's the wrong thing. The component either needs to modify the list or it doesn't. If it needs to modify it, then calling it with an unmodifiable list is wrong (but the java compiler can't stop you) and if it doesn't modify it then it should declare that it won't modify it (but java doesn't really let you do that), and accept the responsibility itself (with help from the compiler)

UnmodifableLists are a great way to enforce const'ness on poorly designed components (ones that don't declare their parameters as const, but in theory shouldn't be modifying them), but it's not a good general solution.

I think java is poorer for its lack of const but the java pattern is usually to work around it with immutable objects, so as you get more used to "the java way" you miss it less and less.

2. "Code fom the outside in" ; that is, the API, and how objects are to be used, are far more important than the implementation; implementing without a very clear picture of what the caller needs from a class will almost always result in refactoring.

3. The two principles stated in Design Patterns: "Program to an interface, not an implementation." and "Favor object composition over class inheritance."

4. Perhaps emphasis on tools like JUnit is appropriate here, too...

5. The central idea of an object is to provide services, not to encapuslate data.

6. The code is not its own spec. The spec is in English, eg javadoc. "What the code purports to do" is a distinct idea from "what the code does". Understanding a method, and what its implementation does, does not tell you if it is a *correct* implementation of some service: only comparison of the impl with a spec can answer that question; nothing else.

7. Making a class safe to subclasss takes significant extra effort.

8. The concerns of library builders are light years from the concerns of the builders of an end-user application.

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 ?

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 ?