ReVersioning Issues With Abstract Base Classes and Interfaces
Phil Haack is talking about why the MS MVC team changed IHttpContext to HttpContextBase. I follow the argument, but at some point, I just lost it. This, in particular, had me scratching my head in confusion:
Adding this method doesn’t break older clients. Newer clients who might need to call this method can recompile and now call this new method if they wish. This is where we get the versioning benefits.
How on earth does adding a new method to an interface would break an existing client? How on earth does adding a new method to an interface require a compilation from client code. Now, to be clear, when I am talking about changing the interface I am talking solely about adding new methods (or overloads), not about changing a method signature or removing a method. Those are hard breaking changes no matter what approach you take. By adding a method to an interface? That is mostly harmless.
The only thing that require that is if you are implementing this interface, not if you are using it. It is possible that Phil is using the term clients in a far wider meaning than I would put on this, but this is not the general use of the term as I see it.
Prefer abstract classes to interfaces, use internals and no virtual by defaults are three of the main issues that I have with the framework design guidelines. I have major issues with them because they are actively harming the users of the framework. Sure, it might make my work as a framework developer harder, but guess what, that is my job as a framework developer, to give the best experience that I can to my users. [Framework Design Guidelines rant over]
Now, I do believe that I have some little experience in shipping large frameworks and versioning them through multiply releases and through a long period of time. I also believe that some of those frameworks are significantly larger and more complex than what the MS MVC is going to be. (Hint, if MS MVC even seems, by an illiterate drunken sailor on a rainy day, to approach NHibernate's complexity, it is time to hit the drawing board again).
And those frameworks are using frameworks to do pretty much everything. And I cannot recall off hand any breaking change that resulted from that. In some cases, where the interface is an extension point into the framework, we have gone with interface + base class with default functionality. If you use the base class, you are guaranteed no breaking change. The reasoning for an interface is that it is giving the user more choice, you aren't limiting the options that the user have when it comes to use this (by taking out the single inheritance slot, for example).
Now, if we analyze the expected usage of IHttpContext for a moment, who is going to be affected by changing this interface? Only implementers. Who is going to implement IHttpHandler? I can think of only two scenarios. Hand rolled test fakes and extending the Http Context in some interesting ways, perhaps by adding proxies or decorators to it.
In the first case, that is no something that I would worry about. The second is far rarer but also the much more interesting case, but those are generally not done by hand (I wouldn't want to type all the methods of IHttpContext, that is for sure). Even if it was, I still have no issue with it. New framework version, add a method. It is not a significant change. A significant change would require me to rework large swathes of my application.
Now, why do I care for that?
The reason is very simple. It is a pain to me, personally, when I end up running into those warts. It is annoying, frustrating and aggravating. I like to be happy, because otherwise I am not happy, so I try to minimize my exposure to the afore mentioned warts. Hopefully, I can make them go away entirely. And not just by pulling the blanket over my head.