Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

There are some design guidelines about testable code in “The Art of Unit Testing”. The first one is “Make methods virtual by default”. I’m curious to know your idea about non-virtual-by-default behavior in C#. I’ve read about Hejlsberg opinions but I think one the most important reasons could be that it may lead us to “composition over inheritance” principal.

Could “composition over inheritance” be one of those reasons which make non-virtual-by-default preferred over virtual-by-default?

UPDATE

Regarding this subject, please consider test-driven point of view; where we want to write testable code. While we are encouraged to make all members virtual by default (at the mentioned book), we can follow "composition over inheritance" and keep going non-virtual-by-default. Isn't it better?

share|improve this question

3 Answers 3

Explicit virtual is form of Defensive programming. By enforcing what methods can be overriden, you ensure that person who will create a child class cannot create error by doing something that wasn't intended by parent's design.

I don't think it has anything to do with how people approach design of their code from composition vs inheritance point. But there are definitely people who will dismiss it on basis that defensive programming is not good thing.

share|improve this answer
    
Can you elaborate on how allowing every method to be overridden by default is defensive? If all the methods are non-virtual by default, that is a guarantee that somebody can't come along willy-nilly and override method you did not explicitly intend (and carefully design and code) to be overridable in a sane fashion. This is obviously a fundamental difference between C# and Java, and one I have always felt C# got right. Depending on overridable methods to enable testing is unnecessary. –  Craig Dec 18 at 6:23
    
@Craig I said that NOT allowing every method to be overridden by default is defensive. "Explicit virtual" means virtual methods have to be explicitly defined. I agree with what you said. –  Euphoric Dec 18 at 7:15
    
Oh <sheepish grin>, as opposed to implicit virtual. It occurs to me that it's past my bed time. ;-) –  Craig Dec 18 at 7:37

I think it could, yes. Virtual by default would make it a lot easier to override implementations in inherited classes.
Frankly, I think it's a weird rule. If you really need to override something, then make it virtual. Don't go making everything virtual just because some guideline tells you to.
It sounds like stuff you'd hear in college (overarching advice that could bite you in the backside when applied without second thought).

share|improve this answer

I am puzzled as to why a book on testability would be recommending creating virtual methods, unless it is speaking more to a C++ audience than a C# audience.

Making methods virtual should be done only with great care and caution. Most classes I write that are not explicitly abstract are generally sealed. That way I can be sure that the code that I write is rhobust and thoroughly tested. I can be sure that no other developer is going to inherit my class, violate the Liskov Substitution principle and throw some kind of exception in the code that I have written.

If a developer follows the SOLID principles, particularly the last one (dependency inversion), testability should not be a huge concern. It's when these principles are violated that testing becomes a lot harder.

Here are my rules of thumb for writing testable code:

  1. Avoid writing static methods/classes.
  2. Follow the SOLID principles.
  3. Seal as many classes as is practical and use the virtual keyword very sparingly.

With dependency injection and mocking tools tests are easy to write (even if some become long because of the data that is required to test against).

share|improve this answer
    
upvoted, agree with pretty much everything except the idea that static methods aren't testable. ;-) –  Craig Dec 18 at 6:18
    
It's not so much that static methods aren't testable, but they make testing things that use them more difficult to test. And if they use any kind of state they are extremely difficult to effectively test. –  Stephen Dec 18 at 6:21
    
Those are fair points, which I do actually agree with, particularly static methods that use state, as the state is obviously hidden from the tester. Additionally, static methods that use state are inherently more difficult to deal with sanely because of inevitable timing and synchronization issues. The same largely goes for non-static classes and methods with extensive external state dependencies, of course. But those are still easier to test with mock objects than static ones are. –  Craig Dec 18 at 6:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.