Paradigm Shifting: Rethinking ASP.NET MVC
March 4, 2010 Leave a comment
NOTE: This is the first part in a series of notes for an upcoming book Paradigm Shifting: Rethinking Architecture and Development in .NET, Visual Studio 2010 Edition.
I recently read a book on ASP.NET MVC that had the following statements:
- Model – An MVC Model contains all of the application’s logic that is not contained in a view or controller. The model includes all of an application’s validation logic, business logic and data access logic. The MVC model contains model classes that model objects in the application’s domain.
- View – A view contains HTML markup and view logic.
- Controller – A controller contains control-flow logic. An MVC controller interacts with MVC models and views to control the flow of application execution.
I have a problem with the statement about what a model is, as it goes far beyond what I find a model should be in a well design statement. To understand my issue with the statement about models, you need to understand what a domain is. I will try to do this in very simple terms.
The Domain and the Model
A domain is generally classified a “problem domain”. We have a “problem” that needs to be solved for business and we are “modeling” objects in this area, or “domain”. But that is a bit of an oversimplification.
Let’s look at a order as an model. Within the “problem domain” of a customer ordering items, an object model contains information about the various items the customer is ordering, including pricing information, payment information, a payment address (used primarily for authenticating a user), a mailing, or shipping, address, etc. When you move to the “problem domain” of shipping an order, however, you no longer need the payment information. In this domain, you need a pull list of items and shipping information. If you follow domain design properly, you will often create different objects to represent an order in different domains.
When you look at the last paragraph, the “model” of an order, when properly designed, contains information (data?) and not much more. To be a bit more geekish, the model contains “state”, which merely means it represents the object as it is during a certain point in time (when it is being interacting with, for example). I don’t have a problem with a model that also contains validation logic, although you can separate out that responsibility at times. There are samples of models that handle their own validation that do not break the rules of separation of concerns rule, but be careful how you handle validation and make sure it fits your feedback methodology.
The problem comes when you start introducing other types of logic in a model. There is a pattern called Active Record where the class contains methods to load (SELECT/READ), save (UPDATE and INSERT/CREATE) and destroy (DELETE). These methods are CRUD (CREATE, READ, UPDATE and DELETE) methods. I have also included the SQL keywords that correspond to CRUD in the sentence (SELECT, INSERT, UPDATE and DELETE). This pattern does not contain business logic, however.
When I examine applications from a few years ago, the Active Record pattern was very much in vogue. And this particular pattern is still popular, as an option, in some O/R Mapper projects. Subsonic comes to mind, but you also see Active Record in .NET Tiers and some others. When you examine sites today, however, the Active Record has largely fallen out of vogue and you see the Repository pattern being used.
The Repository pattern separates the data access logic from the domain model. You “feed” the model to the Repository, which is responsible for the save (INSERT/CREATE and UPDATE) and delete (DELETE) methods and the model only contains state. As stated before, I don’t see validation as a huge problem in these objects, as long as you ensure the validation logic fits your feedback methodology.
NOTE: If you want to learn more about Domain Driven Design, consider Eric Evans book Domain Driven Design: Tackling Complexity in the Heart of Software.
I don’t have any problem with the View description, but understand that view logic is merely logic necessary to display the domain models to the user in a “view” (think of a view as “one way to view a model” and you see the reason for the name). In MVC, this user will be a human (at least in the instances that come to mind right now). Note, however, that you should be able to easily switch out view engines, which serves to muddy the waters (Silverlight, for example, can be used as a view). If you want to read one opinion on which view engine to use, you can look here or here or here.
I also don’t have any problem with the description of a Controller. In a simple MVC application, the Controller simply marries the model with the View and ensures models changed by user interaction get sent back to the application. There are decent UI reasons to expand it beyond a simple minister model (ministers “marry” people), but many of the simpler samples do little more than facilitating this “marriage”.
Okay, so this brings us to a bit of a paradigm shift in thinking. When you think ASP.NET MVC, you probably don’t think of it as interacting with an application, but rather as the user interface part of an application. When I think of applications, I think of them pretty strictly as the business layer only. Here is my reasoning:
- You should be able to switch out the database without changing application logic. Most people find this to be an easy concept to get their heads around, as we have plenty of examples of applications that can work with multiple types of databases.
- You should be able to switch out the user interface without changing application logic. This is harder for many people to completely grasp, as they think of the UI as part of an application (3-tier or n-tier come to mind).
In my view (play on words?), ASP.NET MVC is one choice of user interface. Other types of UIs include Windows Forms, classic ASP, WCF services (or ASMX web services), WPF and Silverlight. This is not a complete list. And, many may disagree with WCF being a UI technology, as it presents information to another application or service rather than a human. If you agree with this grouping, we might define WCF, and all UI technologies for that matter, as boundary technologies, as they represent a boundary in an application. The more standard UI technologies, like ASP.NET MVC, end on a boundary that requires interaction through a front end; WCF ends on a boundary between “applications” or “services” in most instances. Taken to the extreme, as Juval Lowey does, WCF can be used for all boundaries. That is a topic a bit too involved for this discussion, however.
Here are a few guidelines I believe work with ASP.NET MVC. There will be exceptions where you step outside of the guidelines, of course (“rules are meant to be broken”?), but the guidelines serve to make for a better application in most cases;
- Models should represent objects in a particular domain.
- Models should contain state, not behavior.
- Models should not contain business logic. Unless a pattern like Active Record is used, they should not contain data access logic.
- Views should be concerned with presenting models to users, as handed off from the controller.
- Views should only contain logic necessary to present models. They should never contain application, or business, logic.
- Controllers should be concerned with controlling the flow of the user interface.
- Controllers should not contain business or data access logic.
We can make this more complex by getting into the subject of binders and actions, etc, but understand that the primary purpose of ASP.NET MVC is to act as the user interface for an application. I will hit a few more topics over the next few weeks, but I thought this one was a good place to start, as rethinking the definition of an application is a useful topic.
FINAL NOTE: For those who are wondering, the book in question is ASP.NET MVC Framework Unleashed by Stephen Walther. Despite having a problem with the statement mentioned at the top of the article (from page 16 of the book), the book does not weigh down the models with business logic. The main reason I “picked” on the book was it was a prime point to focus on what MVC is and how it relates to applications as a user interface technology. When I get through with reading the book, provided it continues to be as good as the first few chapters, I will give it a good amazon.com review. 😉
Peace and Grace,
Twitter: @gbworld – best way to see when other articles are posted