Clean Separation of Concerns in MVC

One of the main areas that is cited as a benefit of using the new ASP.NET MVC Framework is that you can obtain a 'clean separation of concerns'. But the question is, what does this really mean, how achievable is it in reality, and should we really be interested in doing it?

What does it mean?

Well, from Wikipedia (http://en.wikipedia.org/wiki/Separation_of_concerns) - 'the process of breaking a computer program into distinct features that overlap in functionality as little as possible'. The article goes on to say that the MVC design pattern aims to separate content from presentation and data-processing from content. This is all well and good, but where do the lines of separation fall. One is reasonably clear - between the data-processing (Model) and the rest of the application. Almost every attempt at writing an MVC Framework web application illustrates this successfully.

The slightly harder area to tie down the separation for is when you look at Views and Controllers. Where should the separation occur? What is the division of responsibility? Should the two portions be completely independent, or can they have knowledge of each other? At a certain level, it is reasonably easy to provide some definitions: the view takes responsibility for presentation, and the controller takes responsibility for actions. But there is clearly a grey area in the middle. Clearly most actions can be completed without much dependency on the view that is their 'end point', but the reverse is not necessarily true. In a simple 'display' view there is no problem, but by the time we move to 'editors', we are starting to get into the realms of some trickiness of definition. In fact the way the view is set up may have critical importance to the nature of the controller. This is probably best illustrated with an example. Let us say that I have written a appointment diary application. One of the editors in this is used to change the date of an appointment. I could choose to display this date in one text-box (DD/MM/YYYY format), or I could decide that it will be easier to use if I split it and put the day, month and year components of the date in different text-boxes. Either way, I have introduced a link between the way the data was displayed and my controller. If I change one way of displaying the date into another, I may need to change the controller, unless the view takes care of returning the date to the format from which it 'came'.

But here lies another problem - 'format from which it came'. It's perfectly legitimate in MVC that the View may have fetched the data it is displaying from the Model directly and that the Controller had no knowledge of the original form of the data at all. Either way, we are getting towards the situation where the Controller needs knowledge of at least one of the Model and the View in order to function. The problem really comes from the nature of HTTP. The View is split between what it was on the server, and what is able to be transmitted 'over the wire'.

So is full separation achievable?

Well, we could remove the requirement that the Controller knows things about the View. It would require something of a rethink to the way the MVC Framework is currently designed though. It would require that Views 'submit back to themselves', that the View can then sort out the data before triggering an appropriate Controller action. But there is a problem. We've essentially introduced a dependency that the View now needs to know about the Controller. So we're back to square one! I therefore don't think that the View and Controller having no knowledge of the structure of each other is practical. They are implicitly linked.

Where does that leave us?

Well, not all at sea, thankfully! And luckily, I think in considering what we really mean, we come to what really turns out to be a very good way of architecting an MVC web application. I believe that the separation is not a totally strict one of encapsulating all knowledge about the different portions of the code, but rather a clean separation between behaviours and views. Interestingly, this is one of the key points of object oriented design that is often overlooked - designing an application by the behaviours that it must be capable of. The REST-like routing system built into the MVC Framework as it stands takes you even further down this route of considering the application to be much like an object oriented design. Essentially therefore, Controllers can (in some sense) be likened to classes (and indeed this is the language construct they use!), and Action methods are the behaviours of which a Controller is capable. The big advantage of these Action methods being thought of as behaviours is that writing Unit Tests for them becomes a very natural process.

The conclusion of all of this is that there is going to have to be linking between your Controllers and Views. They can't be written to operate independently. The key point is to see the separation between behaviours and templates. Don't code things that are going to cause a change to the model into your View, and don't code things that are purely a matter of presentation into your Controllers, but expect a certain amount of grey area where the communication between them is concerned.

9 Comments

  • I think that having this "grey area" is not a big problem. Views and Controllers are related, and we must live with it.

    A clear example of that is that I can put my /Model folder in a separate DLL and reference it, and everything will work fine, and it will be usable by a Windows application, or a WebService project, or whatever.

    You can't say the same of controllers or views: if separated from the MVC app context, and from each other, they don't make any sense.

    That's just my point of view, of course.

  • I probably should have pointed out that the origin of this post was a discussion in the forums - http://forums.asp.net/p/1297317/2524971.aspx

    See there for some background.

  • "linking between your Controllers and Views"

    At minimum... utilize an interface.

  • Hi, If the controllers are decoupled enough from the views to make unit tests against them, it is ok to me. That is the main purpose of the MVC framework. I think it is not so important to archieve a complete separation of concern.

    Regards,
    Pablo

  • I think you're not differentiating between two forms of coupling. When you talk about controllers knowing about view and/or model classes, it's one thing for them to be aware of the classes and talk to their public interfaces.

    But it's another kind of coupling entirely for one class to rely on the internal behaviour, i.e. the implementation, of another class.

    It's not a question of the controller having to know that the view exists and call on it. It's a question of the controller having implicit knowledge of the implementation of the view and depending on that to function.

    To refer back to your post title, the view is concerned with transforming a model object (assuming we're using ViewPage) into HTML output. It should also therefore be concerned with transforming it back again when the form is submitted. The view doesn't have to submit back to itself. It just needs to provide the service to convert the NameValueCollection back again.

    An analogy is encryption. You can call an encryption class to encrypt output. You'd expect to call that same class to decrypt it again. The crypto class is merely performing a service. Something in the view layer should perform a similar service - in both directions.

  • As stated in the thread that inspired this post, isn't it the case though that we could think of the contract as having been defined by the controller. The fact that the controller's outputs (perhaps a strongly typed business object) aren't the same as the inputs (a mixture of method variables and HTTP request variables), but I'm not sure that's a problem. It's the view's problem to conform to the contract of what the controller requires.

    The problem I think is how to 'define' the HTTP contract. I'm not sure there's a good solution to this. Perhaps the way round it is to (in some way) consider the unit tests to be the 'contract' - you have defined in the code you wrote for them the HTTP request parameters that the controller expects. The View would need to match these. A bit bizarre, I'll grant you, but still not the end of the world.

  • "It's the view's problem to conform to the contract of what the controller requires..."

    Agreed. The last thing a controller requires is a NameValueCollection populated with values from fields on the view. This is equivalent from the business logic getting a NameValueCollection from a DAL populated from fields in a table instead of a DAO.

    The HTTP contract is between browser and view layer. The contract between controller and view shouldn't be at the level of HTTP.

    In this whole discussion, both here and in the ASP.NET forums, no-one has yet given me any argument against my proposal of having the view convert the NameValueCollection back to a higher-level object.

    IOW, given the choice between the controller dealing with a high-level object or a NameValueCollection from fields on the view, which would you choose?

    As for unit testing, how are you going to test the controller? Mock an HttpContext, Request and Form NameValueCollection? That still implies that it's coupled to HTTP. Your previous thoughts suggest you don't want the controller coupled to that. Why not instead mock something that can convert from the NameValueCollection into something abstract and have the controller deal with that?

  • I think the controller is basically fairly implicitly coupled to HTTP. It's a web framework after all. The big problem I think is the number of situations from where a request may have originated. Yes, in a lot of situations, there's going to be a view which can return to the same view for some sort of conversion to higher level objects, but that isn't always going to be the case.

    Here's a scenario that I believe puts a spanner in your works. What if I have a link somewhere on my site (or indeed someone else's!) that is a GET query and supplies several parameters that will be routed to a controller within my application. There is clearly no View that this has originated from (particularly if it's on someone else's site), so it's going to have to be able to deal with a name/value collection. The parameters being passed could quite easily be dates (blog posts by month?). And I think this is quite a common scenario. It's clearly going to be ridiculous to write an action method so that it will respond appropriately to both strongly typed and weakly typed data, so we have two choices. If we go down the strongly typed route, I think it basically means we have to give up the ability to have hyperlinks that cause GET queries to be run. Which would be a shame!

  • Hi, i've read your posts on asp.net mvc forum. I think the problem that you state is valid but the place where the logic of converting the values should stay is not the view. More, I think that the ViewData itself should be responsible for this. ViewData should know how to serialize itself inside the rendered http form. The input controls, if they are non standard should modify the serialized data and not participate in the form postback. The controller would instantiate the ViewData instance from the HttpRequest, so the controller would be agnostic. the view also would be agnostic, if it will use some sort of generic javascript generated by the ViewData serialization itself.

    I may sound confused, but english is not my native languge...

Comments have been disabled for this content.