Recently, while talking to my classmates, I have found myself frequently explaining the rationale behind common programming no-nos. Though many students have been told that we should “avoid using goto,” and we are often told “don’t make everything public,” a lot of these “pariahs” of programming are never actually explained; they are simply re-iterated. To help combat this, I plan on posting the why behind these words of warning in a series of posts.
So, on to today’s topic: Why not make everything public?
Perhaps the most obvious benefit to private data members is that you can restrict other classes’ access to that data member. By providing both an accessor (getter) or mutator (setter), users will have read or write access (respectively). By providing one, both, or neither, you can control whether users have read access, write access, read/write access, or no access to your class’s data field; the choice is yours. First and foremost, this helps make your code safer. For example, you cannot accidentally change a value that was not meant to be altered if your code cannot change that value in the first place. Second, your class’s interface (in the sense of what methods, fields, etc. programmers using your class are supposed to use, not in the “ISerializable” sense) is dictated by what users have access to publicly. In other words, the public parts of your class dictate how your class is meant to be implemented. If the interface is mucked up with implementation details, it is a lot more ambiguous.
Another important reason to declare data members private is encapsulation. If you don’t know, or perhaps don’t fully understand, what encapsulation is, read this article for a solid explanation. Encapsulation allows you to change implementation details with minimal (or, ideally, no) effect on code outside your class. You could add logging features to a method call, add verification for pre-/postconditions (e.g. with assert statements), add thread synchronization, clamp input values, or whatever else you can think of. If your implementation is not encapsulated well, although it is still possible to add such functionality, it’s a much larger headache – you’ll have to re-write all the code that used the (now-broken) old implementation. Thus, even if you’re using only your own code, encapsulation is beneficial.
A quick side note: protected is (for all intents and purposes) no more encapsulated than public. The main idea behind encapsulation is to minimize the chance of other code breaking when you change something. If another class implements yours, it has access to all of your class’s protected members, and thus you’re still stuck with the same dilemmas as public members. With this in mind, a good rule of thumb is to prefer private data members to public or protected whenever possible.
Finally, a not-so-obvious reason is for consistency. Scott Meyers explains this one excellently in his book Effective C++: “If data members aren’t public, the only way for clients to access an object is via member functions. If everything in the public interface is a function, clients won’t have to scratch their heads trying to remember whether to use parentheses when they want to access a member of the class. They’ll just do it, because everything is a function. Over the course of a lifetime, that can save a lot of head scratching.”
References / Recommended further reading
Effective C++: 55 Specific Ways to Improve Your Programs and Designs, Third Edition by Scott Meyers. pp.94-98
P.S. Thanks to Somara Atkinson for inspiring this.