Geeks With Blogs
Boy Meets 'Hello World' Blogging the journey from College Grad to .NET Developer

Jonathan Starr joined in the "to var or not to var" discussion that occurred recently with his post "Code Redundancy Is NOT Necessarily Bad". No, I'm not jumping into the ring with this whole var thing. Not much anyway. Ok, maybe a bit at the end, it's all Jon's fault, the text box on his comment section is too small, so I made a post instead, and that lead to me thinking harder about the subject, and things kinda' just took off from there :P

In his first post, which I've linked to, he declared:

 

Say I have a class named Example that implements two interfaces, IFoo and IBar.  When I instantiate I have several options when dong so statically.

Example example1 = new Example();
IFoo example2 = new Example();
IBar example3 = new Example();

In the second case I am ensuring that example2 implements a certain interface, and I can swap this out with an instantiation of a different object that implements IFoo.  This strategy pattern is fundamental to object oriented programming, and 'getting in the habit of writing code using var' can provide inflexible suboptimal design.  Additionally, if you are coding using TDD (Test Driven Development) you won't be able to write unit tests that remove all dependencies for your class unless you write your dependencies as interfaces.

I asked about the comment regarding how you "won't be able to write unit tests". Whether in response to myself, or the other commenter, or both, he made his second post (Code Redundancy is NOT Bad - Part 2), where he said:

If the method PartitionMerchants had been written using class declarations instead of interfaces, than any test I would write for this method would be an integration test, not a unit test...  Because the failure could be in one of the dependent classes, not in the class that is under test in my unit test!

This is why I was confused with his assertion. The difference between a unit test and an integration test is not whether you are using interfaces are not, but whether you are testing the smallest "unit" of code or the interaction of multiple "units" of code. If you couldn't mock class methods, then he would be right, since you would have no alternative other than to have the unit of code that you are testing also be interacting with another unit of code that you're not. But, we can mock class methods, and without needing to make an interface wrapper.

To do this, you would make a subclass of the class in question, which will be used as your mock (fake, double, whatever) and override the method you wish to mock with your implementation. Since frameworks like Rhino.Mocks and Moq use DynamicProxy, they too rely on subclassing the class to mock. This all means that the class you wish to mock will need to have those methods you wish to mock marked as virtual to correctly override them. In addition, you should probably allow for a protected parameterless constructor (if a public one is not available) just so that you don't have to rely on passing in dependencies to your mock object (which these frameworks include abilities to do, but honestly I can't even imagine a scenario where this would be preferred to refactoring). Since I wouldn't mind seeing all methods being marked as virtual by default anyway, I have no qualms with it.

Not that I'm disagreeing with the whole coding to an interface. Actually, I thought that I had stopped doing this myself, so I dug up my code from the last few days so I could show Jon an example of where it might be ok to just use a class and refactor to an interface when necessary, but I couldn't find one because I had been coding to interfaces the whole time without really even noticing it. I think that's a good thing :)

Ok, I said I wasn't going to join the fight, but just had a few comments to make on Jon's example. I wasn't following the whole var discussion, so my apologies if any of this has already been said.

Jon starts by creating an object three times, and shows that because he doesn't use var he can instead explicitly set the type to an interface, which he can now "swap out". Then he goes on to say that

This strategy pattern is fundamental to object oriented programming, and 'getting in the habit of writing code using var' can provide inflexible suboptimal design.

To me, what he appears to be saying was that you can do this...

   1:  public interface Notification
   2:  {
   3:      void Run();
   4:  }
   5:   
   6:  public class FirstNotification : Notification
   7:  {
   8:      public void Run()
   9:      {
  10:          Console.WriteLine("First");
  11:      }
  12:  }
  13:   
  14:  public class SecondNotification: Notification
  15:  {
  16:      public void Run()
  17:      {
  18:          Console.WriteLine("Second");
  19:      }
  20:  }
  21:   
  22:  public class Service
  23:  {
  24:      public void DoStuff()
  25:      {
  26:          Notification firstExample = new FirstNotification();
  27:          firstExample = new SecondNotification();
  28:      }
  29:  }

 

First off, let's just imagine that I'm using factories to create stuff, so that no one can gripe about the inherit untestability of the code and miss the point.

Because we used Notification instead of var on line 26, we can now "swap out" on line 27, whereas the var would create an error message. This is not the strategy pattern. The strategy pattern would be about if I were to later use the the instance in another method which took Notification as a parameter. I could pass in whatever notification strategy I wanted to, and it would run it. I'm asumming that this is more what Jon had in mind, so let's imagine this case...

   1:  public interface IOtherService
   2:  {
   3:      void Run(Notification example);
   4:  }
   5:   
   6:  public class Service
   7:  {
   8:      private readonly IOtherService otherService;
   9:   
  10:      public Service(IOtherService otherService)
  11:      {
  12:          this.otherService = otherService;
  13:      }
  14:   
  15:      public void DoStuff()
  16:      {
  17:          var firstExample = new SecondNotification();
  18:   
  19:          otherService.Run(firstExample);
  20:      }
  21:  }

 

Here, I pass it to another method. By using var, you do NOT lose any "flexibility". Ok, perhaps the DoStuff method will be returning this instance, in which case just make the return value exactly what you want to return. Want to return the interface? Go for it.

public class Service
{
    public Notification DoStuff()
    {
        var example = new SecondNotification();
        example.DoSomethingThatICouldNotDoWithTheCTorIKnowNotWhat(
            "ButMakeItPlainlyObviousThatICannotJustReturnTheVariableDirectly");

        return example;
    }
}

 

The only problem I can see is when you want to make sure that something is only used as an abstraction. If you didn't want to deal with it as a SecondNotification when it was returned from this method, you would've changed the return type. If using it as a parameter in another method, that method probably is expecting the actual class as opposed to the abstraction for a reason (probably a bad one, go change it). Thus, the only time you would be using this object in it's actual form is when the instance is still part of the method. Perhaps you want to avoid this situation...

 

public class Service
{
    public Notification DoStuff()
    {
        var example = new SecondNotification();

        example.MethodOnSecondNotificationThatIShouldNotBeRunningInThisCase();

        return example;
    }
}

 

Honestly, if you need to change that var to Notification to send the point home, fine. But otherwise, I don't see the deal regarding strategy patterns and flexibility. And once again, no, I didn't read everything in the blogosphere. I'm sure that when I get hit with something bad about it, I'll figure it out then, and make a blog post about it. For now, I'm not worried.

Posted on Monday, June 23, 2008 11:38 PM | Back to top


Comments on this post: That whole, crazy var thing...

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © mhildreth | Powered by: GeeksWithBlogs.net