On the Framework Design Principles from Raymond Lewallen
Raymond Lewallen posted his presentation from Framework Design Principles. I mostly agree with what he has to says, except that on slide #5 he has this:
- Can cause problems by users of your framework who don’t understand it.
- Virtual members cannot be inlined.
What?!
The first issue is very simple, if a programmer do not understand what a virtual method is, he has no business touching. This is such a basic gap that you just can't fill with trying to protect the user. Check the Daily WTF story about such a programmer.
The second issue is a more serious matter, and is actually the reason that in .Net 2.0 List<T> has no virtual memebers. My personal opinion in this matter is probably already known, this is the wrong design desicion to make. Especially since so much of .Net 2.0 (controls, data binding) assumes that you are working with List<T> and not with the interface.
The JIT is capable of inline interface methods, as a matter of fact, so if you think that you class will see as much perf critical code paths as List<T>, make the methods non virtual and always use the interface. One of the big things about OO is that you can use polymorphism to cleanly modify the actions of the system. You should always leave a way for a programmer to come in and change what the system does.
A simple example: I want to use WithEventsList<T>, which will raise Added, Removed, Cleared events at the appropriate times. Not a hard thing to do, except that I can't use List<T> as a base class, all those methods are non virtual, I have no way to extend the functionality of the class.
Speaking about interfaces, this is what Raymond had to say about them;
- Use abstract classes, not interfaces, to decouple contract from implementation.
I am pretty sure that I don't agree with the above, but I am not sure what the meaning is, Raymond, can you clarify?
Comments
I don't get it either. What does the abstract class have that an interface can't have with regard to the contract? But then I don't think the code is the contract. Does Raymond?
Oren, you are taking the slides out of context of the presentation in which they were presented. You needed to hear the talk that went along with it.
While sometimes virtual members are required, they should be avoided if you can provide the extensibility you are looking for through a template pattern. Also, virtual members are more difficult to deal with when making changes in terms of breaking existing code and compatibility. You have to take into account any user implementations of those virtual members, and you've sealed your fate into having to support that design and poorer performance model.
Naturally, there are reasons to use virtual members and most advanced programmers know what they are getting into. I was merely pushing the guideline in a course entitled "basic framework design" that if you can avoid it, do so. I certainly don't expect more advanced programmers to adhere to these guidelines (and they are guidelines, not rules) when the circumstance calls for exceptions. There are drawbacks to virtual members that may not be directly understood until you have more experience with them, and that was the point.
On to the interfaces comment: again, since you didn't hear my presentation, you missed where I said that I am a big supporter of interfaces and use them throughout my code, probably too much. I also had to note that I "mistyped" what was written in the slides (I should go fix that) about the interfaces defining semantics. Semantics should say "syntax" instead. The semantics and contract are the same thing, and neither are supplied by an interface. An interface merely supplies syntax. Abstract classes should be used for separation of contract from implementation as they can be evolved and extended with much greater ease and versioned without causing breaking changes, if done correctly.
Now, again, I favor interfaces personally, but I also understand exactly what I'm doing with them versus abstract classes and what I am both limiting myself to and also what I'm gaining. I expect you do as well. Again, this was a "basic framework design" presentation and I certainly wouldn't think you would argue with those guidelines at a basic level, would you? At a more advanced level? Absolutely. After all, they are just guidelines. How else would we make something both comparable and formattable and even convertible without interfaces? A base class doesn't make too much sense here, and again, without hearing the presentation itself, I can certainly understand the disagreement while viewing the deck out of context.
Thanks for the speedy reply.
I thought that the last part wasn't in context, but the first one looked complete.
There are two major issues here that I see:
1/ You and I have different approaches to extensibility, both are valid, but I tend to use a lot less template methods and a lot more overloading.
2/ I really don't like idea of different guidelines for advanced and basic developers. In fact, I would argue that if you are building a framework, you should be above basic at the very least.
The main issue that I have with this is that there are plenty of people that are taking those guidelines and treat them as rote. I once had to deal with a system where interfaces where completely forbidden. The reason: the architect believed that interfaces were slower than abstract base classes, so they used pure virtual abstract base classes for everything. I would spare you the way they implemented multiply inheritance with generic parameters, but it wasn't fun to work with. The actually hit a few compiler bugs because of it.
As I said, in the entire presentation, only those things bothered me, everything else I completely agree. That is probably a good ratio :-)
I am glad to know that I didn't have full possession of the facts :-)
The part about interface == syntax and abstract base class == contract is interesting, can you expand on that a bit, I don't think that I quite follow what you mean here.
Oren,
Yes, there are certainly multiple avenues to approach extensibility, and I favor the template and strategy methods. I personally don't like overloading unless I can keep it to a minimum and I'm sure you are the same. I just have better luck with templates and strategies.
I agree on the guidelines shouldn't be different for basic vs advanced developers but at the same time you have to provide comfort and draw a line somewhere. Some people are just getting into frameworks, and trying to spill into their heads in 2 hours what I've spent 12 years learning just doesn't make sense. As they progress, and I mentioned this in the presentation, you're much more likely to disagree with some of the things I mentioned, and that is perfectly fine and expected. Even though some people didn't speak up during the presentation, I spoke with some people afterwards who questioned some of the things and we talked about them. Its certainly best to explore what you think is right and treat guidelines as what that are: mere paths from which you should venture off of and explore its surroundings.
I'm glad to hear you agree with everything else :) It'd be nice to get your feedback of the actual presentation someday, but not likely we'll cross paths on that avenue any time soon.
How about you let me elaborate more on the interfaces = syntax vs abstracts = contract in a blog post so we don't draw out this thread beyond its scope?
Cool, thanks.
Comment preview