It’s been a while since my last post on C++ and I have been immersed in Java as of late. Some of the points today actually apply to languages other than C++ as Scott presents sound arguments for all objected oriented developers.
22: Declare data members private: Scott takes a two step approach to this proof. He first looks at why data members should not be public and then follows up with arguments against other forms of non-private members like protected members.
The first argument has to do with syntactic consistency. It is difficult as we move back and forth between languages to know what things are objects and what things are native operations or data members. I never know when to use parentheses to access a piece of data or just a dot for a static data member. If all data is private then there is only one way to access it. The second part of the argument for private data is one of control. When data is encapsulated, the designer can make any data read only, read/write or in rare cases write only. The last argument has to do with future-proofing your design. If all data access is encapsulated, the interface can remain the same, but the internal workings of the class could change from data access to computational data access.
In some cases the implementation of the class may change based on the compute platform. If the platform has the ability to do a computation in hardware, the data is returned, where if the hardware does not exist, the computation is done in software and the result is returned. For platforms like Android where the OS runs on many different hardware platforms this becomes a real advantage.
Arguments against protected members are basically the same with respect to syntactic consistency and access control. Protected members are usually used in derived classes so if you want to change the base class to perhaps replace data with a function, you could break any derived classes as a result.
By hiding your data from your clients, you insure that the class can be completely refactored without effecting down stream code.
23: Prefer non-member non-friend functions to member functions: This point is really about keeping your options open with respect to your designs. The example in the book refers to a web browser application that could have three different methods. (One method to clear the cache, one to clear the history and another to clear cookies.) You have the option to provide a method in base class to perform all three together or you can leave that to programs that might use this class.
If we stick to strict object oriented design principles, we should put all functions that operate on a classes data in the class itself. The reason that we do this is to improve encapsulation (Just discussed in point #22). So just to be clear, we have the option to introduce a member function called “clearEverything” or a non-member function called “clearBrowser”.
One of the ways we measure object encapsulation is by looking at the number of member and friend functions that access the encapsulated data. By adding another member function we actually increase the number of ways that the encapsulated data can be accessed. This in turn detracts from our goal of not impacting down stream code. So clearEverything provides less encapsulation than clearBrowser and the better choice is to prefer the non-member function.