BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles Fulfilling the Promise of MVC

Fulfilling the Promise of MVC

Bookmarks

Model-View-Controller (MVC) is probably the most cited example of an architectural software pattern. It was conceived by Trygve Reenskaug working in the SmallTalk group at Xerox Parc in 1978. One motivation for the pattern was the separation of concerns: to allow Model objects to be concerned only with modeling business capabilities, not with how their data and methods were presented to the user, nor with capturing or responding directly to user inputs.[1]

In the last decade, interest in MVC has grown again, but from a different direction: web development. Here, the problem wasn’t having domain objects that knew too much about presentation, but the reverse: too much business logic ending up in the presentation layers, resulting in poorly-structured systems that are hard to maintain. Today, MVC has become a popular pattern for the development of ‘data intensive’ web applications, and is supported by many frameworks including ASP.NET MVC. [2]

Yet though a web application built on MVC is probably better structured than one using prior patterns such as web-forms, most such systems are still nowhere near as clean as the pioneers of MVC envisaged. In a typical MVC application, today, a huge proportion of business logic ends up in the Controllers, and a surprising amount leeches into the Views. And most of the remaining business logic is delegated, by the Controllers, to services. So the Model objects end up as little more than dumb data structures. The pioneers of object-oriented programming must be turning in their graves! (Ole-Johan Dahl and Kristen Nygaard died within six weeks of each other in 2002, just a year after having their contribution recognised by the prestigious ACM Turing Award).[3]

A little over ten years ago, I started to propose an alternative architectural pattern specifically to address this issue. The idea was driven by two principles. That ...

  • If you went back to the original idea of putting all your business logic as methods on your domain (Model) objects - even if some of those methods delegated on to services - that it ought to be possible to create a complete, rich, object-oriented user interface directly from that model using reflection.

and that ...

  • If you created your user interface entirely automatically from the domain objects, it would force you to do a better job of the domain modeling. To pick up on the subsequent work of Eric Evans in Domain Driven Design, it would force you to make your model a true representation of the ‘ubiquitous language’ of the business, because there would be no opportunity to paper-over-the-cracks with custom views and controllers.

The theoretical work became my PhD thesis, which also coined the name of the ‘naked objects’ pattern [4]. In the six years since then, a dozen frameworks that claim to implement the pattern have appeared [5]. The only two I can personally vouch for are the open-source ‘Naked Objects for Java’ (currently in the process of being incorporated into the Apache ISIS project), and Naked Objects for .NET, which is now my principal occupation.

Whenever the naked objects pattern is mentioned it seems to divide the audience: people love it or hate it. I have to say that some of the strongest criticism comes from those who’ve neither examined the idea properly, nor tried our framework. They seem to imagine that it must somehow require that UI responsibilities be put into domain objects. It doesn’t.

More legitimate criticism is directed at the idea of a generic user interface. The initial versions of the Naked Objects framework did not permit any customization of the generic auto-generated user interface. To many people this is unacceptable. I would point out that the largest user of the Naked Objects framework (a Department of the Irish Government) has not only found that the non-customizable user interface works perfectly well for their 1500-user mission-critical applications, but that it has given them huge advantages. However, I do accept that the non-customizable user interface is one of the biggest factors that has limited both the applicability and the appeal of the naked objects pattern.

So a year ago I set my team a challenge to ‘square the circle’: could we create a framework that would synthesize the naked objects pattern with the MVC pattern - giving you the full benefits of both, without the downsides of either? We’ve just released the result - called, unsurprisingly, Naked Objects MVC [6]. With this framework you can write a data-intensive web application solely by writing domain objects. (These are POCO domain objects - they don’t need to inherit from the framework nor implement any interfaces.) It uses Microsoft’s Entity Framework to create the underlying persistence layer on relational database, and it uses ASP.NET MVC 2 to create the HTML user interface.

You can then customize the generic user interface as little or as much as you want to.

Now at this point, Naked Objects MVC might sound like a number of other frameworks that can generate a CRUD interface from a data model - Dynamic Data being just one of them. There are some similarities, but two important differences.

First, Naked Objects MVC does not involve any code generation or ‘scaffolding’. I’m not keen on that approach, though I accept that some people like it. With Naked Objects, if your domain model has 100 classes, you don’t end up with 100 (or, more typically, several hundred) views and/or controllers. The entire generic user interface is created using a fixed set of about a dozen generic Views, and a single generic Controller.

Secondly, Naked Objects MVC does not just provide CRUD access. Rather, it reflects the full functional capabilities of the Model objects. If a Model object has a public method then, by default, this method will be made available on the objects ‘action menu’ at the user interface, and if that method takes parameters then these are reflected-on to create the dialog for that action. Adopting the pattern of programming by convention, you can provide methods that will validate the input parameters for that action, hide, or disable the action based upon the object’s state, for example.

Where the generic interface is not suitable, you can customize the user interface at one of three levels.

The first level of customization is using CSS. By editing the CSS files you can not only change the overall layout and design of the application, but also the layout and design of individual object types, properties, actions, or parameters. The reason for this is that in the (dynamically) generated HTML we’ve paid a lot of attention to the use of class and id in our divs. Adding this line to the CSS, for example:

.Property#RetailStore-SalesPerson {color: Green;}

will cause just the Sales Person property on the RetailStore object to be colored green.

By the way, we’re also very committed to generating pure HTML. Even the drop down menus of object and service actions are achieved using CSS. Currently, our only use of Javascript is to add the JQuery pop-up calendar to date fields. This can be removed, or more Javascript added according to your preferences/constraints.

The second level of customization is to write custom Views, which may inherit from one of the generic Views or be built from scratch. Naked Objects MVC provides a large set of HTML helper methods that make it very easy to build new views of objects and actions. For example, you might wish to display a SalesOrderHeader with its collection of associated SalesOrderDetails rendered as a table. Your View, strongly typed on SalesOrderHeader would just need this code:

<%: Html.CollectionAsTable(Model.Details)%>

Or to display a Customer object with one of its actions (CreateNewOrder, say) already open as a dialog on the same page, your view, strongly-typed for Customer, would just need to add this line:

<%: Html.ObjectActionAsDialog(Model, "CreateNewOrder")%> 

Alternatively, if you prefer type-safe code over brevity, you can use an overloaded version that takes a lambda, thus:

<%: Html.ObjectActionAsDialog<Customer, string, DateTime, Order>(Model, x => x.CreateNewOrder)%>

This will insert into the custom view the HTML for a dialog box for the CreateNewOrder action. It will pick up both the types and names of the parameters for that action (in this case a string and a date), will enforce any mandatory ones (picked up from annotation), and will apply any validation rules by automatically invoking the ValidateCreateNewOrder, if one exists.

(Although Naked Objects MVC framework has a proprietary license, the generic Views and Controller, and all the HTML helper methods, are provided open source [MS-PL] to allow them to be extended or modified.)

The third level of customization applies when you want to customize the flow of the application. Incidentally, one of the biggest surprises when we first implemented the naked objects pattern several years back, was not that we could reflect both object state and behaviour in a generic view, but that we could have a completely generic application flow. But that generic flow is only suitable for situations where a user has the opportunity to learn the (few) generic interaction patterns - typically for internal users. To use the distinction made by usability guru Alan Cooper, this generic application flow is best suited to ‘sovereign applications’ [7]. For ‘transient applications’ (including anything that is public-facing) then a customized flow - typically a highly-scripted one - is just as essential as a customized presentation.

You can achieve this by writing custom controllers, either that operate in isolation or in conjunction with the Naked Objects generic controller. When I find myself having to do this, I am always astonished at how difficult is: trying to keep your Views, Controller methods and routing information all in synch. Not that it’s any harder than writing a native ASP.NET MVC application, it’s just that the generic approach of Naked Objects MVC really spoils you! The good news is that I’ve found that you can avoid much of the need for this just by using a View Model. Let’s say you’re developing a public-facing web application that takes a new travel booking in a tightly-defined six-step process. You can do almost all the work by defining a BookingCapture object - still within the Model the project, but marked up as [NotPersisted] - which captures the data and tracks the status. At the end of the stages a single Confirm method on that object then creates the various objects to be persisted. You might need to write a couple of ultra-simple controller methods, but all the real work would be done in the Model, and the presentation of the six stages of the booking handled by six custom views of the BookingCapture, which are very easy to write.

To be sure, the introduction of this not-persisted BookingCapture domain object is a move away from the pure Naked Objects pattern (where all objects are persisted entities) - but I stress that this is strictly for the situation where you do need a tightly scripted user interface. Whenever we build a substantial new application using Naked Objects, we always start by designing the application for the user who is completely-trained, completely-reliable (makes no errors), and completely trustworthy. Not only can this type of user cope with the fully-generic user interface - but they actually need the freedom that it offers. (I was recently invited to give a talk, in Norway, entitled ‘Treating the User as a Problem-Solver, not a Process-Follower’ [8]). Having done that, it is then comparatively easy to layer on such controls and constraints as are needed by mortal users, and such scripting as is needed for public users with zero prior knowledge. By contrast, most application designers start from the other end, and then find it very difficult to create a more flexible system for the more capable user.

In summary, the overall principle of Naked Objects MVC is that when you create a model you should be able to run that model immediately as a complete application by means of default Views and Controllers. You then add customized Views and/or Controllers, but only where you need them - and preferably as late in the development process as possible, so that you concentrate maximum development effort on the model.

Although, to my knowledge, ours is the first framework to achieve this, it isn’t an original idea. It turns out that this was what Trygve Reenskaug had in mind in the first place, but wasn’t able to implement back in the late ‘70s. The only reason I know this - there’s no published record of it - is because Trygve was the external examiner for my PhD thesis in 2004. He’s retired now - an Emeritus Professor at the University of Oslo - but still as sharp as nails ...

Links and resources:

[1] Trygve Reenskaug’s own notes about the origins of the MVC pattern.

[2] For a good overview of the re-discovery of the MVC pattern for web development, read Chapter 2 of Professional ASP.NET MVC 1.0 by Rob Conery, Scott Hanselman, Phil Haack and Scott Guthrie.

[3] Wikipedia entries for Ole-Johan Dahl and Kristen Nygaard, founders of object-oriented programming.

[4] Richard Pawson’s PhD thesis on the Naked Objects pattern.

[5] Wikipedia’s a list of frameworks that implement the Naked Objects pattern

[6] Naked Objects MVC website, where you can watch video demonstrations of building an application, and download the free Evaluation version.

[7] Short summary of Alan Cooper’s ‘Application Postures’. For full explanation read his book About Face.

[8] Video of Richard Pawson presenting recently in Norway on ‘Treating the user as Problem-Solver, not a Process Follower’.

Rate this Article

Adoption
Style

BT