Single Responsibility in C++ - Should I implement it using friend classes or more accessors?
I wish to follow the Singl开发者_Python百科e Responsibility principle in C++. However, as I break up classes, it seems that in order for classes to "see" each other, I have the following choices:
- Add many more accessors for each class
- Make classes friends of each other
- Improve the design (maybe the fact that I would have to do 1 or 2 indicates a flaw in my design)
The friend vs. accessors issue has probably been discussed before, but I did not know if one was more advantageous with regard to implementing Single Responsibility.
I've always thought that rule was BS. Most classes have several responsibilities, and no harm done. Consider a bank account class - it might have the responsibilities:
- maintain client details
- allow for debit & credit transactions
- provide current balance
- report dubious transactions to security
Of course, these responsibilities will probably be implemented using other classes that the account is composed of.
If you must expose private data from one class to another, than make the second class a friend. Creating an accessor for your private data defeats the purpose of making it private in the first place. The single responsibility principal has no bearing on this.
Edit
In response to Dima's comment below, perhaps I went a little too far in saying "the" purpose. There are, after all, more than one reason to make data members private. One reason, as Dima notes, is to protect the integrity of the object. Accessors do accomplish this.
But a second (and more important, in my opinion) reason is to hide the class's implementation details. Once you've added public accessors, you've lost control over how many other classes reference your class's implementation details. Over time, this can make it extremely difficult to modify your implementation because of the cascading effect on other classes.
Friend classes, while far from perfect, at least give you strict control over how many classes will be affected by your changes. Another benefit is that when you do make changes, you know exactly which classes might be affected. Thus, they're a better option when you must share your class's internals. But the best option of all (of course) is not to not expose implementation details at all.
Now that you have a group of classes that all need to work together, you should consider how they should work together. If it's via accessor functions or friends, then you're tightly coupling the classes. It would be difficult in the future to drop in a new class that does something different. It's also difficult to test the classes since they're all inter-dependent.
Consider creating an interface class(es) that defines how your classes should communicate. Unless there's some special privileges involved, this interface will also define how anyone else would communicate with them. This way, you break the classes' inter-dependency. Any future changes are localized to the class involved. Nobody else has to change (or maybe even recompile).
You also have option 4: add more classes to represent the different roles/interactions between the classes.
That at least falls more in line with the Law of Demeter.
精彩评论