Significant coding change request

Mar 20, 2013 at 5:42 PM

Is it possible to modify most of the code in the framework as follows:
a) Change all private attributes/methods to protected
b) Make all protected methods virtual

This will make it MUCH easier for me to subclass a given class and correct issues. For example, had you done this, I could have easily subclassed the SwitchThemeViewAction method and added code to "guess" what the correct CategoryOrder should be and then call the base and parent code.

But the way it is currently written, I have to mostly copy/paste code and create "new" methods to override the default actions.... Not really OOP... :)

I do understand that, in a very few cases, some methods attributes may be best defined as private, I would rather you err on the side of making too many protected than too many private. Also, I am hoping that much of this could be done with a regex based find/replace vs. having to actually go in and edit all the code.

Mar 20, 2013 at 8:08 PM
It is possible, yes. But it isn't really desirable as there are consequences of doing so. Virtual methods are slower, for instance. Also, things that are flagged as overridable in subclasses should be designed for that. This was different in the Visual FoxPro world, where everything was always virtual, with all the pros and cons that go along with that. Also, as a rule of thumb, unless there is reason for something to be available in subclasses, they should be made private. For instance, backing fields for properties have no business to be anything but private (fields should always be private). The same is true for methods that are implementation details. So we try to give thought to what we want to make virtual and what now.

The specific example of the SwitchThemeViewAction class (I assume we are talking about the class, because I don't think there is such a method). This whole action is really very simple and does one thing only: It sets the theme property on the current application. So it does this:
private void ExecuteCommand(IViewAction a, object s)
    var appEx = Application.Current as ApplicationEx;
    if (appEx != null)
        appEx.Theme = _theme;
So not a whole lot of stuff going on here (and certainly not where you'd want to put your code for view action ordering... that goes into whatever object that specific place in the theme uses, to show actions). If you wanted to create a different version of this, it might just be better to create a new view action, because there isn't anything else in the class worth preserving. So all you'd end up doing by making this virtual is introduce overhead with no functionality.

But let's say you really wanted to change the method that fires when this command is triggered. There is a different built-in mechanism this view action has (all view actions have this). You can set the execution delegate. By default, the execution delegate is set to the above method with this code in the constructor:
So this ties execution to the method listed above. But you can create another method and point to it instead. Most likely that method would completely redefine what you want to do, so you don't need the default in this specific case, although you could certainly call that as well if you wanted.

Mar 22, 2013 at 5:46 AM
Edited Mar 22, 2013 at 5:47 AM

The example I used was just that, an example. In the above case, I just wanted to be able to specify a category order.

As you said, I could create my own class and copy/paste the code over. But if you later modify the class to give it some new feature, I won't get that. If I subclass it and create a "new" method to override the existing method, I have the same issue. However, if I could subclass it, then I could add in the value I need and still get the benefit of any future changes you may make.

Also, changing attributes/methods/etc. to be protected (and virtual) does not expose those values any more than as protected except to subclasses.

As you well know, the beauty of OOP is the fact that we have inheritance. And you are so well versed in OOP that there is no need for me to elaborate on that.

While it may seem to be a lot of work, if it was simply decided that future class attributes and methods should be protected (and virtual) and as well as that when updating classes that those attributes also be changed, then over time, most of the code would be updated with minimal time taken (hey, I know your team is as busy as we are.)

What I do know is that I don't want to make changes to the CODE FW nor do I want to copy/paste code from the framework into my classes and then lose any new stuff you add to the source classes.

(and, if I use this approach to subclass and enhance your classes, then it's easy for you to look at those enhancements and add them to the FW should you so desire.)

Mar 22, 2013 at 6:00 AM
Edited Mar 22, 2013 at 6:02 AM
Yeah, but the point is that there will not be any significant changes to that class because the code of significance is somewhere else. If there was significant code in that class than it would be different and it should in fact be protected. As such, the fact that is isn't gives you a specific indication that this class was not designed to hold significant code.

I understand completely where you came from. In the VFP world, inheritance was a) extremely powerful, and b) the only such tool we had. In the .NET world, we have inheritance with even greater power, but we also have additional features that allow us to define exactly how inheritance works. We also have other tools such as interfaces (and interface inheritance), delegates, and more, which are also very valuable tools that are often more appropriate than plain old implementation inheritance. But like I said: I understand where you are coming from, because when I originally moved into .NET, I also tried to deploy the inheritance hammer everywhere.
Also, changing attributes/methods/etc. to be protected (and virtual) does not expose those values any more than as protected except to subclasses.
OK, there are a few confusing things here. I assume when you say "attribute" you mean "property", because attributes do not participate in this mechanism as such.

I also assume you mean "protected exposes things no more than private". In that case: Yes, protected does in fact expose things more. In .NET, inheritance works in a way where the two classes that participate in an inheritance relationship form two object instances in memory. The first one then exposes everything that is protected or public to the other one. Not the private ones though. So there is a great difference there. Now for something like a property, the idea is that ANYTHING outside that class always accesses the property's values through the set/get method pair. You NEVER would want to access the backing field from a subclass.

It is also very important to understand that just because something isn't virtual, that doesn't mean you can't inherit from it and override it. So this is perfectly valid:
public class Dog
    public string Bark()
        return "bark!";

public class BigDog : Dog
    public new string Bark()
        return base.Bark().ToUpper();

Console.WriteLine(new BigDog().Bark());
So this works perfectly fine even though the method in the superclass is not flagged as virtual. So there is no need to copy and paste if you want to do this sort of stuff with the framework classes. (Note: I think we have a paper on that explains the finer points of all this stuff, with a VFP slant)

Also, as mentioned in my prior post: Virtual methods introduce significant runtime overhead. So it is NOT desirable to make all methods virtual, especially on framework level.

And, to add a general statement again: There really shouldn't be that much or a reason for you to have to subclass much from the framework. I know that in VFP that was the recommendation, but in hindsight, that recommendation only really made sense for the UI classes (which does not at all apply in WPF). So the need to subclass everything simply doesn't exist in .NET.

Mar 22, 2013 at 6:40 AM

Ok, points well made. And I didn't realize the overhead caused by the Virtual methods. Thanks for clarifying for me. Next time I run into a similar situation, I will try to explore some of the alternative options first.