Let's look at both points separately.
1. Class invariants
In programming, reasoning is simplified when you have invariants. For example, you may have already heard about loop invariants:
for (size_t i = 0; i < vec.size(); ++i) {
In this loop, 0 <= i < vec.size() is an invariant that ensures that vec[i] always a valid expression.
A class can also have invariants, for example, if you consider std::string , its size() method returns the number of characters in its buffer. Always.
Now suppose you write your own string class:
// Invariant: size represents the number of characters in data. struct String { size_t size; char* data; };
Well documenting what you want was invariant, but I can do it perfectly:
void reset(String& str) { delete str.data; str.data = 0; }
and forget to reset str.size , thereby violating the invariant.
However, if you remove the members of the class:
// Invariant: size() returns the number of characters accessible via data() class String { public: size_t size() const { return _size; } char const* data() const { return _data; } // methods which maintain the invariant private: size_t _size; char* _data; };
now only you can break the invariant. Thus, in the event of an error, you have less code to audit.
2. Insulation with replacement performance
The idea is that you should be able to switch the internal presentation of information without adapting class users. For instance:
class Employee { public: std::string const& name() const { return _name; }
Now, if I understand that std::string not a suitable representation for the name (for example, I would need wide characters):
class Employee { public: std::string const& name() const { return _name; }
I am stuck. I can no longer return std::string const& (I no longer have an internal std::string ). I can change the return name() to make a copy:
std::string Employee::name() const { return encodeUtf8(_name); }
Unfortunately, it can still break customers:
std::string const& name(Employee const& e) { std::string const& n = e.name();
If Employee was designed from the very beginning using std::string name() const , we could make the change without a problem.
Note: when used in the real world, you need to make an external API with isolation, but the internal API can perfectly display the data representation ... due to more changes on your plate when making changes.