Can you ever have too many "protected virtual" methods?
Here's a question for those of you with experience in larger projects and API/framework design.
I am working on a framework that will be used by many other projects in the future, so I want to make it nice and extensible, but at the same time it needs to be simple and easy to understand.
I know that a lot of people complain that the .NET framework contains too many sealed classes and private members. Should I avoid this criticism and open up all my classes with plenty of protected virtual members?
Is it a good idea to make as many of my methods and properties protected virtual as possible? Under what situations would you avoid protected virtual and make members private.
Your class includes data members; methods that perform basic internal operations on those data members where the functionality should never change should always be private. So methods that do basic operations with your data members such as initialization and allocation should be private. Otherwise, you run the risk of "second order" derivative classes getting an incomplete set of behaviors enabled; first derivative members could potentially redefine the behavior of the class.
That all said, I think you should be very careful with defining methods as "protected virtual". I would use great caution in defining methods as "protected virtual", because doing so not only declares the possibility of overriding the functionality, but in some ways define an expectation of overridden functionality. That sounds to me like an underdefined set of behaviors to override; I would rather have a well-defined set of behaviors to override. If you want to have a very large set of overridable behaviors, I would rather look into Aspect Oriented Programming, which allows for that sort of thing in a very structured way.
When you mark a method with the word virtual, you're allowing the users to change the way that piece of logic is executed. For many purposes, that is exactly what you want. I believe you already know that.
However, types should be designed for this sort of extension. You have to actively pick out the methods, where it makes sense to let the user change the behavior. If you just slap on virtual all over the place you risk ruining the integrity of the type, it doesn't really help the user to understand the type, and you may introduce a number of bugs including security related issues.
I prefer the conservative approach. I mark all my classes with sealed unless I specifically want to enable inheritance and in those (few) cases I only make the required methods virtual.
It is easy to remove the sealed tag if the class needs to change to allow inheritance in the future. However, if you want to change a class, which is already being used as a base class for some other type, you risk breaking the subclass when you change the base class.
My point of view is:
- If you can user events, its preferred to protected methods.
- Try to avoid protected methods as possible, if not possible then you have to use it ;-).
Choosing protected over private is a deliberate design decision. You are stating that your class explicitly supports having that function used, with all the overhead (design and implementation effort) that comes with that. I would only use protected in those situations where I know that it is necessary, largely because I am doing it myself. (You'll also find comments from BCL developers along the same lines as what I have said.)
The virtual/non-virtual performance difference is irrelevant on any machine that is powerful enough to run the .NET Framework.
No, you can't have "too many." However, the idea that we should just make every protected instead of private or avoid "sealed" at all costs is just silly. I would keep "helper methods" and internal data structures private.
Is it a good idea to make as many of my methods and properties protected virtual as possible?
Not as good idea.
Protected virtual methods provide extensibility points in the framework while adding coupling.