I’m trying to look at the way I write software simply — and trying in the same process to avoid rewriting infrastructure software (i.e., frameworks) from scratch.
So I know that MVC is a good pattern, and I know that DAO is a good pattern, and I know using a Domain Model/Business Objects is a good thing. But using all three of these systems, and combining caching, templating, and object-relational mapping is not simple. In fact, I can’t think of a single system I like to to use to do it.
My post yesterday about my enthusiasm for CodeIgniter in it’s simplicity showed that. It misses a few things I’m used to, but I’m willing to forgo that to get back to the joy of simplicity.
One constant disconnect I always run up against is how to reconcile MVC with web based template display. The obvious way is to put the MVC behind the page display, and you can see the subsuming of action based frameworks (like Struts, Webwork) to GUI component based frameworks (like Tapestry, Wicket, JSF, GWT, Echo2) as a symptom of that.
Actually, I think partially it’s emblematic that display logic is at least as complex as business logic in most cases. I don’t really understand the hiding of request/response that some like Echo aim for. There can’t be that many unemployed Swing programmers wanting to write JFrames, JPanels, and JButtons but refusing to think that the drawing might be done on a different computer. Surely anyone who could hand-code with a Swing layout manager can figure out HTML tables and CSS.
If compatibility were the real issue, I’d rather code with AWT and sockets over even the wildly divergent Mozilla DHTML platform. That’s why some people talk about flash or sliverlite or whatever. But c’mon, people that want to use flash just want to use flash designer, because it makes animation easier. It’s only recently that tools for building JSF GUIs or Instantiations’ cool GWT designer have come along. But the complexity makes even veteran EJB developers cringe.
So given that (in my mind, at least) HTML layout is a benefit to GUI design (at least until a better markup that renders natively, not XFORMS or XUL or XAML) how do we reconcile MVC with web development?
I had a minor epiphany recently using CodeIgnitor, which has a very weak framework MVC, particular M. But because it’s so lightweight, it’s up to you how much you want to take or leave. I’d go so far as to say CodeIgniter is really a URL mapper tied to a semi-ActiveRecord DB tool tied together with a bunch of suggestions and conventions. (I actually really like their ActiveRecord design, but can’t really speak for the implementation yet, having not looked inside or tested it under load or in production.)
Since the model is only a suggestion, and really, the view doesn’t even work with the model, it works with a multidimensional array–which is the actual model, it started me thinking. That’s the benefit (or curse) of simplicity.
I’ve been wanting to divorce business objects from the web layer and from the persistence layer. A recent article on theserverside.com had a limited concensus that the view should be tied to the web framework. There was a disconnect about how to display the view. Another article by Tony Marston about PHP data object, arguing that business objects should be tied to database tables (which the popularity of ActiveRecord implemations bears out.)
I’m aware that the two references in the above paragraph aren’t complete sentences.
The key problem I have is how to map the business objects to the persistence layer *and* the presentation layer. Tony Marston argues that you shouldn’t decouple, because you’re essentially duplicating data. I agree with this. Mapping is a waste of time and adds complexity. But it increases testability and helps scalability.
A cache is essentially a duplication of data, and no one argues that caches are a bad practice, and that hooks into the cache from the business object rather than direct DB integration are a necessary complexity. Lately caching has been pushed downward (when in truth, if you pay for a good DB, it has pretty good caching built in.) That’s really the #1 reason people like hibernate. It’s not because they think HQL is better than SQL.
I remember a good article on O’Reilly about a toy store from back in 1999, building a cache with a mod_perl cluster. It’s a great article, and one that convinced me that Apache + mod_perl can make a great appserver. If only it wasn’t for perl. I used to hope for a mod_php or mod_python that had some of that capability.
CodeIgniter and most templating systems want you to slurp up all your data into the template and display it. I agree with this. The value of separating layout design is too great, and as I said before, the major appeal of web development. The truth is, there wasn’t much thought to layout (except in games, which rolled their own everything) before web apps. At least not beyond horizontal alignment and resizing.
I want my MVC components to be testable. In fact, I think I actually want to think of MVC the way it used to be thought of. Not as smalltalk components, but as components with 3 parts. Not as Sun’s Model2 design of a framework split in three ways: display, request/response, and data. I want my business objects to be MVC.
Then I realized: the page is a business object. It’s the one users interact with most. It’s probably the most complex business object (except maybe a fancy transaction — thinking of transactions as objects might be a fruitful pursuit.) Maybe this is something everyone else already knew, and I’m just a slow thinker. But a lot of early frameworks that thought of a page in an object oriented way (thinking again of perl and things like HTML::Template) got it wrong trying to build an OOP hierarchy out of HTML tags. But it’s the tags that make HTML appealing, remember? How can we treat the page as an object then.
It’d be nice if we could think in terms of components. And if designers could build page “parts” in a specialized tool. I remember being excited by Tapestry the idea, but being confused trying to learn it. I’m interested in Wicket now, but until I’m back in an enterprise environment don’t want to deploy on Java, no matter how nice it is to develop in. If deployment weren’t an issue, Rails would be much more popular.
I also remember being excited about portals, but disgruntled that they didn’t offer anything except a login and a complex second servlet (portlet) layer.
One reason people keep going back to simple page-based systems like PHP is that they allow page control and you can just include a section. Remember SSI (server side includes) — people want to do that. And people want to have a page template.
Yesterday, I argued that people use a CMS like Joomla or Drupal because it offers a page template, not for it’s content management. But how do you use MVC with that? There are various hacks, and Joomla now has MVC (sort of) for writing components. But I don’t want to write a Joomla component. I want to write a business object. And I want to display it on a page. Not inside a CMS. I want data stored in my DB, not content. I want my content to be versioned.
So I’m suggesting that you write your business objects as business objects. Using MVC. Like you would if it was smalltalk, but without the annoying and useless smalltalk execution environment. And not as something like Naked Objects, though that’s a cool concept.
Create a model — you know, the data model for your object. And create a controller — you know, the thing that controls your model. And create your view — you know, a representation of the model. And maybe they’re the same class. But that’s an implementation deal.
Where the confusion comes in is thinking of the controller as the page controller. But it’s not the controller, it’s a controller. The controller of the page. And they think of the view as the page view. But it’s not the view, it’s a view. The view of the page.
And implement your page view as HTML markup. GUI layout designers since at least VB 5 have specified the GUI in a layout file. HTML is the layout file for a web page. It also happens to be the transport format that remote clients know how to render.
While a business object has a view, it isn’t normally exercised over the web. It’s exercised in the context of a request. A request – response cycle can be thought of as a transaction.
Take the idea of a shopping cart.
It has a controller for the following actions:
- add item
- remove item
- list items
- get item details
- calculate quantity of items
- calculate total price of items
- expire cart
It has a model:
- item list
- perhaps quantity and price are attributes, and not only calculations
- cart owner
- cart created on
- cart lifespan
One nice thing here is it manages it’s own session state, which can be decoupled from a HTTP session, a User session, or even an Order session.
It can have a test view, which returns simple data, or a web view, or mutliple web views. Or a web component can implement a view and interact directly with the cart via it’s controller. Finally, getters and setters will have a point.
cart.getItems() will have an implementation. And it will be testable. And you won’t need a big testing framework to test your big web framework. Of course, you will still need to do integration tests.
Have a page component that knows how to render a cart model. Or have a cart web_view that renders an HTML page component. Let it talk to the cart via the cart’s controller. The page has a template and a page model. The page model includes a copy of the cart model, and maybe a reference to the cart id (of the business object, not the database table row) for callbacks.
This has gotten confusing and too tangential. The main idea is that the page is a business object, just like the cart. The implementation detail of whether the page knows how to render the cart or the cart knows how to render html is still unresolved.