MVC and Testing. A New(?) Idea


Right now, a lot of people are extremely jazzed about Microsoft MVC. While I am glad to see that Microsoft is creating a web application model with good separation of concerns, I am not doing flips over the project. This does not mean I do not like it, just that it is not as big of a deal as the buzz makes it out to be. Okay, considering how MOST people build web forms, it probably is a big deal.

Why MVC? In all reality, the problem domain we are entering is one of ignorance. The ignorance is bred by the plethora of examples that build a UI similar to this one.

<%@ page language="C#" %>

<script runat="server">

  void Button1_Click(object sender, EventArgs e)
  {
    string resultOfWork;

    //lots of lines of code to do the work by using a value from
    // the textbox


    Label1.Text = resultOfWork;
  }
</script>

<html>
<head>
    <title>ASP.NET Inline Pages</title>
</head>
<body>
    <form id="Form1" runat="server">
      <h1>Welcome to ASP.NET 2.0!</h1>
      <b>Enter Your Name:</b>
      <asp:TextBox ID="TextBox1" Runat="server"/>
      <asp:Button ID="Button1" Text="Click Me"
         
OnClick="Button1_Click" Runat="server"/>
      <br />
      <br />
      <asp:Label ID="Label1" Text="Hello" Runat="server" />
    </form>
</body>
</html>

Before I begin to sound like a major rant, understand that there is nothing inherently wrong with the example above … AS A LEARNING EXERCISE. The problem is too many people do not understand that they should not code production applications this way. Let’s dig a bit deeper.

The Problem

The real problem is how applications are designed. We start from the User Interface and then work back. Instead, we need to consider the design of the different layers as if they are separated applications (or better yet services) that are working in tandem. When we view our applications as a set of services, we design each service to do what it does in a way that is complementary to what it needs to do. As this is a single app, at least for now, we do have to consider how the different layers talk to each other, but we do not have to design linearly from UI to back end or vise versa.

Once you break free from this mold, you start to think of the business tier as a set of behavior objects and state objects that guarantee a user plays within the constraints of our business rules. You then start modeling the behavior in your business tier behavior objects rather than writing lengthy event handlers in code behind.

If you have read much, you are probably thinking domain modeling. And, this is precisely what we are doing. But, you do not have to let the domain drive your UI and database design. That is the shortcoming of the way most Domain Model Architects design their applications. They get so overly concerned with the domain that they mold the UI to the domain. Okay, getting on a tangent and close to a rant here.

If you think about it, you have completely different concerns when you are building UI, business objects (domain objects) and the data layer and physical data storage. Let’s look at a few things.

 

  • The UI has to flow naturally for users and that should be your primary concern. Thinking about how it communicates to the "domain" leads you to compromise form for function, when form is what users need. Conversely, if I start letting the UI drive the decisions, I am more apt to place a lot of code in my code behind. Neither of these are particularly appealing, but both are very common.
  • The domain needs to be concerned with the rules of my business. If I let business rules drive my UI, however, I will end up taking away some of the natural flow to fit processes rather than tasks. Also not good. In addition, I may start modeling my database as my objects rather than store information efficiently and in a manner that performs well.
  • The database needs to be concerned with efficient and performant storage. And, there is the serious concern of data integrity. But, if I build my business tier around my database, I end up sacrificing the focus on the "domain". Also not good.

The Solution?

By Microsoft’s blogging, one of the biggest "problems" solved by MVC, however, is testability. And, I agree, but it is not really as big as it sounds, depending on how you design your applications.

Prove it? Let’s go back to our original example and alter it:

<%@ page language="C#" %>

<script runat="server">

  void Button1_Click(object sender, EventArgs e)
  {
    BusinessTierObject businessObject = new BusinessTierObject();
    string resultOfWork = businessObject.DoLotsOfWork(TextBox1.Text);

    Label1.Text = resultOfWork;
  }
</script>

<html>
<head>
    <title>ASP.NET Inline Pages</title>
</head>
<body>
    <form id="Form1" runat="server">
      <h1>Welcome to ASP.NET 2.0!</h1>
      <b>Enter Your Name:</b>
      <asp:TextBox ID="TextBox1" Runat="server"/>
      <
asp:Button ID="Button1" Text="Click Me"
         
OnClick="Button1_Click" Runat="server"/>
      <br />
      <br />
      <asp:Label ID="Label1" Text="Hello" Runat="server" />
    </form>
</body>
</html>

And, let’s stub in an object.

public class BusinessTierObject
{
    public string DoLotsOfWork(string input)
    {
        string resultsOfWork;
        //Do lots of work here
        return resultsOfWork;

    }

}

At first blush, this does change things much, but I now can do this:

[TestMethod]
public void TestLotsOfWorkMethod()
{
    string passedInValue = "{something here}";
    string expected = "Results of Work";

    BusinessTierObject target= new BusinessTierObject();
    string actual = target.LotsOfWork();

    Assert.AreEqual(expected, actual, "Work values are different");
}

Please don’t get caught up in the test method. I just made it up. Instead, notice that I have effectively tested all of the logic from the button submit method in a way that is repeatable. And, if I find a bug with a certain input value (easy with a textbox), I can confirm the bug on the library and stomp it out.

At this point in time, the main benefit of MVC over my model is MVC allows me to test a bit closer to my UI, as in this example where I add a controller "double" that derives from my default controller.

private class ControllerDouble : DefaultConroller
{
  public ControllerDouble()  { }

  public string SelectedView { get; private set; }
  public object RenderedViewData { get; private set; }
    
  protected override void RenderView(string viewName
    , string masterName
    , object viewData)
  {
    this.SelectedView = viewName;
    //I don’t care about masterName at this point.
    this.RenderedViewData = viewData;
  }
}

Don’t get me wrong. I think the more you can test, the better. And knowing that you are rendering the proper view is a great thing, as well as seeing the view data. But, in your average application, is testing this much closer to the UI really adding much? Stop. Take that back. In your application designed where the UI is a UI and not a be all, end all mass of code behind spaghetti, is testing this much closer to the UI really adding much?

I am currently playing with the MVC Framework. I think it could be a really neat model that can serve the masses nicely. But I also see that much of its wow factor is based on the fact that a great number of programmers are building web applications incorrectly and the MVC Framework is a tool that forces them out of the ignorant/stupid mold. If it can accomplish that, I give it kudos, but there are some hidden costs along the way that Microsoft will have to work through.

First, the model is currently set to only work REALLY well with the latest IIS. As it is not available for XP, some will be left adding some extra code bits to test locally. Fortunately, this is a minor config change and may be ironed out prior to RTM, but it is currently a small hassle.

Second, there is a learning curve associated with MVC. While there are plenty of examples (I even blogged one – pat! pat!), the curve gets steeper as you move deeper outside of the simple view examples.

Third, you end up writing an awful lot of code that Microsoft helped you with when you were not MVCing. This will change over time as Microsoft, and third party providers, give you more things to help with your MVC work, including more templates and possibly some recipes. 🙂

Finally, there is some relearning to do many of the things you now know how to do in ASP.NET. This is closely related to the third item, but there are some subtle differences. Fortunately, a lot of people are blogging on how to do things in MVC, including more TDD focus, including Membership providers, etc.

Summary

Do I think MVC is great? Yes, overall. Am I going to use it in my applications? I am currently deciding that right now. As much of our work, at least the newer work, is already in libs, moving to MVC is not that a huge step for those apps. With some others, it may take some doing. As Scott has stated we can Go Live with the Mix preview, I am thinking about it, but I fear being burned by the Microsoft beta bug. Whether I go with MVC or not, I am already writing fairly testable applications that have repeatable tests, so it is not going to offer me the silver bullet it may offer others.

Peace and Grace,
Greg

Advertisements

2 Responses to MVC and Testing. A New(?) Idea

  1. Alan says:

    Greg, I think the key to testability is separation of concerns. If you create thin UI views already then MVC doesn’t add much value. MVC, however, forces the creation of thin views. Also, MVC doesn’t try to abstract away the stateless, request/response nature of http. This is a big win for those of us who crave fine-grained control over out applications.Cheers,++Alan

  2. Gregory says:

    Alan:
     
    The separation of concerns is a big part of testability. It is the reason we have mocks, fakes, etc. As I currently attempt to either a) design to separation of concerns (thin UI) or b) refactor to separation of concerns, MVC does not add a huge amount, overall. This does not mean I will not embrace it as it is released, as it will force other developers to remain thin on UI, as well. Keeping everyone on the same page is often worth its weight in gold. 🙂
     
    Peace and Grace,Greg

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: