Software Design Best Practices Debate
Date Published: 06 March 2008
I’ve been following the discussion on Phil Haack’s blog surrounding how best to introduce polymorphic objects into the MVC framework as part of the framework’s interface for developers to work with. In .NET, there are basically two ways one can build in this polymorphism: interfaces and abstract base classes. There is a very vocal set of developers who seem to think that the answer must always be interfaces, and while I think interfaces are great and have their place, I think Phil makes some excellent points about their limitations when it comes to versioning. In particular, his post on The Cost of Breaking Changes describes the scenario wherein a breaking change in the Microsoft framework may not break anything in your application, but if it does break something in a third party component or control you’re using, you’re stuck. I think that’s a bad thing.
I think one thing that differentiates Phil and the rest of the team building the MVC support for ASP.NET and 99% of developers in the world is who will use their code and how they will use it. Most developers control their code after it is released. If something breaks in a future version, they catch it at development time and refactor the code to fix the bugs introduced by the breaking change. Need to update an interface? No big deal, just change it, recompile, and fix all the errors.
Even ISVs who ship components and controls typically don’t need to worry about versioning nearly as much as a framework developer does. Sure, some small number of customers may inherit from the controls and some will write unit tests for the controls that might leverage existing interfaces, but the scale here is very small. So again, if you really need to update an interface, it will cause *some* pain outside of the company’s own software (e.g. for customers’ applications), but it won’t be the end of the world.
Now consider ASP.NET MVC in comparison. Its entire purpose in life is to allow developers to use test driven development to build ASP.NET apps, and to provide much greater control over the output generated by each page. Right away, this means that there are going to be a lot more unit tests built on top of this framework than on, say, a third party control suite. What’s more, it’s a low level framework, which means a lot of things are going to built on top of it. Not just web applications, but also controls and tools will be built on top of this foundation, and eventually applications will be comprised of many of these pieces. So it is a very real concern that a breaking change could affect pieces of your application over which you do not have direct control, which puts you at the mercy of your vendors to wait for (or hope for) a new build that has been updated to the new bits.
I would say that I favored interfaces over abstract base classes before I read Phil’s series of posts. However, he’s convinced me that, in the case of a framework like MVC, the versioning pain that interfaces would introduce (I say would, not might, because the team already knows there are things that will change) makes an excellent case for using abstract base classes as the fundamental units to pass around within MVC’s libraries.
Steve is an experienced software architect and trainer, focusing currently on ASP.NET Core and Domain-Driven Design.