Seven Deadly Sins of Programming – #3


I’m sure this is going to be a contentious one. I don’t have a good story about this one, so I’m just going to go right to the sin.


Sin #3 – Overuse of Virtual


There are two schools of thought when it comes to virtual. They are:



  1. Always use virtual

  2. Only use virtual when absolutely necessary

The first group’s argument is that original designer of a class is a poor judge of how the class might ultimately be used. Making all methods virtual allows the users of the class to easily extend/modify the behavior. Non-virtual methods make more work for the user.


(or that’s the argument I’ve heard – please comment if there’s something I missed…)


The argument is true. Virtual does make extensibility easier. The problem with virtual is robustness.


The original designer of a class has a good idea for what the class is about, and the implementation is designed (either explicitly through the tests written with TDD, or more implicitly through the mind of the designer) to support that idea (or contract, if you prefer).


In other words, the designer has an explicit idea about what extension points he wants to support in the class. If virtual is only on those points, then the designer has (or should have) done sufficient testing on those points, and it’s pretty likely that users who extend through those points get the behavior they want. And since only a few methods are virtual, the fact that a specific method is virtual is an important clue to the user that that method *is* an expected extension point.


If virtual is on every method, the user can extend in a lot of ways, but it’s very unlikely that the designer thought of all those ways – or all combinations of those ways – which means that such a user extension is going into uncharted territory. Maybe it doesn’t work when you try it. Maybe it works now, but breaks with the first update when the object behavior changes.


I prefer the “you can only do these 2 things, but I promise that they work” classes to the “you can do any of these 12 things, but they may or may not work” classes.

Comments (14)

  1. Peter Ritchie says:

    > original designer of a class is a poor judge of how the class might ultimately be used.

    Ouch, that sounds like a problem waiting to happen.  I suppose they would also advocate "never use sealed".

  2. Thomas Eyde says:

    >> original designer of a class is a poor judge of how the class might ultimately be used.

    >Ouch, that sounds like a problem waiting to happen.  I suppose they would also advocate "never use sealed".

    Do you have any stories of a bad situation caused by a missing sealed or a virtual too many?

  3. Jarle Nygård says:

    Anders Hejlsberg had quite a bit to say about virtual @http://www.artima.com/intv/nonvirtual.html

    This is said in the context of C#/.Net vs. Java, but most of the remarks are interesting anyways.

    And I’d agree with you Eric, the "2 safe operations" approach is better than the "12 unsafe operations".

  4. Marc Moore says:

    I agree in principle, Eric.  But using the Microsoft Enterprise "Library" as an example, I think one has to recognize that overzealous use of private and sealed limits the usefulness of a library.  I’d lean more toward allowing extension with its inherent risks rather than limiting it.

  5. nksingh says:

    Marc:

    Why not compose the objects together to get the desired behavior?  It’s a pain to make all of the function forwarders, but in the absence of knowing the exact design of the internal class it’s better to treat it as a real black box.  

  6. Jimmy P says:

    I’m going to stick with eric on this… if you’re object is designed and TESTED for extension of 2 methods… then those are the only two methods that should be extended…

    You aren’t going to put trailer hitches on miatas. Just because you can hook up a trailer doesn’t mean it will haul it.

  7. So, the time has come for the worst sin.

    Just to recap – and so there is one post that lists them all…

  8. Moz says:

    Yeah, I just *love* working with libraries where half the library is used via wrapper classes with extra functionality. And then in version two of the library some of the extra functions are now built in, but with subtly incompatible signatures.

    Of course, if every class is a swiss army knife (hello .net) you shouldn’t lack too many functions so the problem goes away.

  9. I was responding in comments, but it doesn’t allow me to use links, so here’s the long version: Judah,