SonicCast #3 - It is not MVC
I have finished watching SonicCast #3 - All About MVC, the premise of the webcast is to show MVC pattern in SubSonic. I don't think that this is what is happening there.
Now, for fair disclosure, I am not a SubSonic user, and I am an active member of the "competing* " projects, Active Record & MonoRail. I thought about not posting this, because of the inevitable flames that criticizing another project will bring, but I think that the subject is important.
* Competing is not how I see it, parallel project would be a closer way to describe it.
The main problem that I have with the style of coding shown in the webcast is that is it certainly not MVC.
public void Page_Load(object sender, EventArgs e) { Product p = ProductController.Get(1); }
This is not MVC because the control is not in the hands of the controller. In fact, the "controller", in this case, would be more aptly named ProductDAL or ProductRepository. It has no business logic associated with it and it does not take an active part in the processing of the request.
The test that I use for an MVC controller is very simple: "who decide whatever to show the Edit link on the table?" If the decision is made on the code behind, than this is not an MVC. If the decision is made on the controller, than we have proper separation of concerns. And when I am talking about a decision, it can be as simple as setting a flag per record, or the like.
There is nothing wrong with the approach shown, and I have built a large scale system with this approach, but it is not MVC. Testability and therefor, maintainability, of such systems are much harder, since the business logic reside in code that is only accessible by invoking the entire ASP.Net pipeline, but that is another matter.
Toward the end, Rob says:
So while this is still a bit of a data broker pattern, it is as close to the controller pattern as we can get, again because we are bound a little bit by WebForms
So I think that we are in agreement about that, with the difference being in that I don't see this as "a bit of a data broker pattern", I see it as the whole data broker pattern.
Toward the end, Rob mentions that you can map button clicks and other events into the controller, and while it is possible to do it, it is quite a bit of work. And that doesn't give me anything that I can't do manually.
And just to state it again, true MVC is not possible with WebForms
Comments
Scott Guthrie's non-WebForms MVC framework is likely one of the strongest possible agreements.
Yes, but he still has the whole aspx / code behind stuff, no?
Never got to see that one, but keeping that around would give some serious technical challenges for the framework.
hopefully you got some sleep between this and the previous post...
I tend to agree and I do think Rob was talking about webform limitations.
I'm actually thinking of playing with a monorail site using windsor, but subsonic for the controllers & models. Why? because I'm not really happy with the codegen I wrote to create the ActiveRecord classes from my db.. and I don't like to "put all my eggs in one basket". [It's a colloquialism where I'm from meaning not to bet everything at once or on the same thing.]
I was wondering if you were gonna light me up on this :). I'm pretty sure I mentioned about 5 times this wasn't "true MVC" and is more like a DataBroker model. I totally agree with you Oren in this case.
That said, ActiveRecord can be a disastrous thing using WebForms because it's too damn tempting to load your controls from your model. I've been trying my hardest to abstract this stuff out a little better - thus the controllers.
And who knows what could come of it, but I'm glad you got a post out of it :p
I'm a bit puzzled on this:
"""The test that I use for an MVC controller is very simple: "who decide whatever to show the Edit link on the table?" If the decision is made on the code behind, than this is not an MVC. If the decision is made on the controller, than we have proper separation of concerns. And when I am talking about a decision, it can be as simple as setting a flag per record, or the like."""
Generally, I agree with you, that fetching data is not sufficient for a conmtroller, but I want to take a broader approach.
To me, a controller is a mediator for both parts of business logic: The business model and the workflow. The latter is often forgotten by model-focused programmers/architects/designers/whatevers, which leads to designs like the one you're complaining at. The problem is that the customers don't care much for the model, they want their workflows and processes implemented instead. Unfortunately, these tend to be buried either within the presentation logic or in the individual controllers when there is no explicit workflow logic behind the application, which makes maintainence of business processes very hard.
Therefore the controller must not decide whether to display a edit link, it should instead fetch that info from a workflow/pageflow engine and pass it to the presentation logic which decides how to display the edit link.
For anyone who's interested I think this post does a good sum up of MVC, presenter First, MVP patterns.
http://www.continuousthinking.com/2007/3/4/recapping-ui-architectural-patterns
I also saw a Model Conductor Controller (which I've never heard of until a couple of minutes ago) at http://rubyforge.org/projects/mcc/ which is explained as :
Model Conductor Controller introduces the Presenter First design pattern to Rails web application development. MCC separates the responsibilities of your ActionController into a Presenter First MVP triplet – the model, conductor and controller.
OK just how great is MVC? Should I be pressing my company to switch all our development to it? I keep reading zillions of posts and articles and feel like I'm missing out, but I'm going to look like an idiot if I press for using something that turns out to be worse than ASP .NET.
I work for a mid sized social networking site (million or so users) with 4 developers.
Markus,
The presentation logic decide how to show the link, the controller should decide whatever it should be visible.
From my POV, the controller is not a mediator but a coordinator, it is the driver for the specified use case.
Using your approach, how would you decide if you should display an edit link? In the presentation layer?
Rob,
The problem is that I don't see a significant difference between Product.FindAll() and ProductController.FindAll()
Oren,
"""From my POV, the controller is not a mediator but a coordinator, it is the driver for the specified use case"""
the controller can be driver for a use case, if you can implement the use case with this controller alone. As soon as you need more than one controller for a use case (I usually have to implement workflows taking more than half a dozen pages in Visio) you cannot leave that to the indivual controllers.
"""Using your approach, how would you decide if you should display an edit link? In the presentation layer?"""
Beware! I have a simple workflow engine implemented that instructs controllers about possible continuations. The controller asks the engine about how to continue within a given workflow instance and then acts accordingly. This includes redirecting to the next page or commanding the view to render links to possible continuation pages.
Josh,
Monorail doesn't require ActiveRecord. You could use LINQ, NHibernate, homegrown 'x', etc...
Glad to see the post. Could it called a MVP ?
@Ayende:
The difference (RE the webcast) between Product.FetchAll() and ProductController.List() (there is no FindAll - but I know the point you're making) is that one is your model (Product), the other is a "controller" (or broker) that has nothing to do with the model - it just loads it. To some, this distinction is very important.
My goal here is to allow people an alternative to piling model-logic into their code-behind (if they want it). In our structure, you can overload (or override) the List() and Get() routine to implement your own logic - this is our goal.
My other goal is that someday there will be a true MVC pattern that can be implemented within the ASP runtime. When there is, I'm want the leap from data-broker to true contoller to be a small one.
That screencast is what prompted me to write: http://blog.bits-in-motion.com/2007/07/roll-your-own-mv-something.html
I can say I've also heard sentiments similar to Harry's above in many contexts. These kinds of MVC perversions don't help.
However... it's been my observation that architecture patterns are much more likely to be embraced when:
They can explained in a few sentences without resorting to jargon like separation of concerns, single responsibility principle, decoupling, unit testing, and SmallTalk. ;-)
The average developer has a multitude of examples to learn from.
In addition to being highly recommended, the architecture is perceived as "the right way" or "the natural way" to use a given platform. This essentially means getting first mover advantage and uniform acceptance when a new platform is released. Consequently most of the ability to dictate these things is in the hands of the platform vendor.
To me the average developer should be trained similiar to how electricians are - they study under master electricians and learn the trade. These concepts such as #1 would be taught first.
I think the point Ayende is making is that you can't call Webforms MVC because the whole lifecycle in webforms starts in the view. If sonic was MVC we'd see the controller starting the process, not the view creating the controller.
Now, that being said:
Webforms is called PageController ( http://msdn2.microsoft.com/en-us/library/ms978764.aspx )
the approach Ayende is making is called FrontController ( http://msdn2.microsoft.com/en-us/library/ms978723.aspx )
my 2 cents - just makes for more controversy.
Comment preview