MVC is dead, it's time to MOVE on
cirw.in
cirw.in
The MVC abstraction has an issue with web applications, since the request-response cycle doesn't provide feedback as directly as the hardware-monitor-software cycle that the pattern was originally designed around.
However, if the problem is that you are putting too much "logic" into your controllers, you should probably find a better place for it.
In Java/Spring-MVC, there is a typical class hierarchy of Controller -> Manager/Service -> DAO. The extra level of indirection is a very handy place to put business logic, then each class in the tier has a dedicated function:
Controller -- Parses input, delegates the action and returns the response (rendered by the view).
Manager -- Handles sanitized data, encapsulates business logic and makes calls into the Model / Data layer.
DAO -- Interfaces with the data store, makes sure only good data goes in, and appropriate responses are returned.
This approach doesn't seem to offer anything more than that, except for putting a label on the messaging between subsystems, but those operations are not well defined (at least in this piece), and seem like another nebulous way to bury logic.It seems like this problem has arisen from a rather narrow reading of what an MVC system should be, as in, not having utility libraries because they aren't strictly an M a V or a C.
*edit: formatting.
http://en.wikipedia.org/wiki/Apache_Struts
MVC with "action" (or event, similar semantics).
Speaking of Java/Spring-MVC approach, I tend to have a mix approach of Service and Repository (since DAO seems to be getting a lot of bad-rep, time to pick a new name :D).
Controller -> Service (SOAP) or Resource (REST) [although Resource could simply forward to Service as well)
or
Controller -> Repository (for specific entity that requires no interaction with other entities)
Unfortunately the Service layer is necessary in the situation where there are 2 or more domain models need to interact with each other.
This seems to help writing test-automations by splitting the tests into 2 categories:
1) End-to-End w/ mock repository
2) Integration only at Repository level using in-memory DB (Derby, H2)
By doing this, we were able to speed up the test significantly.
I believe in Rails, you're tied with ActiveRecord and would require real database (be it SQLite3). There may be open source libraries that can intercept AR calls and re-route it to either fake DB or just simply fake 'em all, but not sure how popular/complete they are.
If you want to just fake 'em all, which does not sound particularly ideal, people just generally mock em
for example:
FriendsRepository.java is an interface that can be mocked during unit-test while the integration-test would use the actual implementation.
I know that the Java solution tend to be brittle because it somewhat forces people to have 1 interface, 1 class implementation (the mock implementation would be provided by mocking library).
The main advantage of Operations over controllers is that they're fully composable. You can take the operation that logs a user in (which displays the login screen, and awaits the user typing a username and password) and use it as a sub-part of any other operation.
In a purer MVC world you get something similar to this by making a function that instantiates the login controller with its associated view; that's pretty good, but there's no obvious place to put that function.
I'll certainly be following up with more details, and some actual code.
I understand the motivation, and have come across several situations where I wanted "controllers calling controllers", but ultimately, you're repurposing a piece of the architecture to do something it shouldn't be doing. A controller handles the input into the system, it shouldn't be defining a workflow.
> In a purer MVC world you get something similar to this by making a function that instantiates the login controller with its associated view; that's pretty good, but there's no obvious place to put that function.
That just sounds backwards to me. Are talking about creating dynamic endpoints? That sounds like a much bigger headache than composing stuff in a service layer.
MVC can be a little ambiguous, and with web-frameworks it can be hard to see that each piece is actually a subsystem. The Model isn't just your model class, its the model class, the DB and the ORM library you are running. Similarly, the View is the entire response / template rendering subsystem. The part that is addressed in the framework is mostly the "controller" subsystem, which is a way of organizing code so that the actual "controllers" can do the primary work of sanitizing input, delegating function calls and returning the output to the View system.
Again, MVC is just a pattern that doesn't fit perfectly in the web request/response cycle, which then necessitates a pattern to handle the leakage (in my case I'm talking about the service/manager pattern). However, I just don't see your suggestions that MVC is "dead", or how this system is radically different.
It seems like it is just semantics.
If I sound snarky, it's because I'm sick and tired of similar opinionated proclamations in too many self-important blog posts.
Edit: Re the down votes. If you're going to write posts with titles like "MVC is dead" with no justification whatsoever, then proceed to self-post on HackerNews, then I feel justified calling you out on it. Again, I would appreciate someone informing on how MOVE is fundamentally different from MVC.
1. http://doc.qt.nokia.com/4.7-snapshot/model-view-programming....
Suppose I have an MVC web app. Suppose I add some database triggers so that when some data is entered other things happen. Maybe I flag an invoice to be printed and the trigger notifies a waiting program which processes the invoice data and sends it to the printer.
Now, from the perspective of any single request, the application is MVC-centric. However, from the perspective of the application structure as a whole it's not, because model operations trigger other operations which can have other effects beyond the immediate knowledge of the model.
Is that kind of what you are talking about? MVC with a sort of events backplane?
Your post explicitly identifies these two roles and formally seperates them. This is perhaps not a bad thing, but I don't know that it justifies the title. Something like "The two faces of an MVC controller" might have been a better description...
I do however think there's still great benefits to MVC, if you're shovelling code into controllers and can't make it work like it should then MVC is not the right design pattern for the project. Like every other pattern it'll only work when it works, but MOVE sounds like an interesting addition that I might have a play with.
(The original MVC is actually useless for web apps because there is no client-server connection in it, and that profoundly changes everything. There's no point in trying to bash a GUI top-level design into a new client-server world, especially when DRY is just sitting there, waiting for you to use it.)
MVC, MOVE, all the variants just obscure your vision from the underlying and far more important principle.
The big epiphany for me was when I realized that the server has its own MVC, and the browser has its own MVC. The server's output is the View for the server and the Model for the browser. For a complex set of objects in a given Model, the final output of those objects is their View, and the consumer of that output uses it as a Model. In theory, any View can be a Model for the thing accepting the View, so in a complex system, you have a chain of MVCs.
And one can further imagine that applets written in JavaScript have their own MVC unit.
I work on complicated, large-data web apps sometimes daily. MVC has been a fine model for them and has kept my group's organization clean and modular.
People complaining about factual inaccuracies on Wikipedia annoy me. It's Wikipedia. The entire point and purpose of it is to fix what you know is wrong.
For once, I'd like to see, "I just touched up the Wikipedia article on this subject to explain it a bit more accurately."
"But then all my changes were reverted by an overprotective editor; I brought the issues up on the talk page, but my comments were brusquely dismissed."
If you don't make any changes, he has nothing to work with except some random whining.
(And yes, that's how it works in the real world, too.)
(In my experience most Wikipedia edits are gratefully received, assuming you provide references for your claims. Kind of like HN, really)
This presupposes
1) I care about fixing it. 2) I have the knowledge to fix it (spotting and removing an inaccuracy is easy, knowing the correct and full set of facts to substitute it with not so much) 3) I can write well enough 4) The Wikipedia process is not convoluted and broken for casual contributors.
"Touching up the Wikipedia article" has little value in cases like this. Usually the only remedy at that point is to delete the entire thing and start again, which somebody finally did not long ago.
While I'd still advocate DRY over this POV (unless of course DRY leads you here naturally), I will agree this is a generally valid viewpoint, because you've got the server-client model built in there instead of glossed over. And you are now the first person who has gotten me to be generally agreeable about MVC used in the web world.
Which raises the interesting question of building a framework that builds this idea into the core, with server-side MVC, client-side MVC, and some sort of defined crossover instead of the usual hacky stuff that emerges from single-MVC.
I use Angularjs in the browser, now.js for the interface, and, at the moment, custom code on the server that follows the MVC pattern.
The server is lightweight: its role is to
* manage authentication and authorizations,
* ensure data integrity and
* push data on update according to user permissions.
That's it.The lexical/nested scoping in the templates is just perfect. I've reviewed the documentation of all competing frameworks, and I couldn't figure how to do it in any of them. Since it was a primary requirement for my app, I went for Angular.
The service-based architecture, and the automatic service injection in controllers, based on parameter names are pretty nice too, as is the fact that you can pass arbitrary parameters to filters.
In a calendar widget that displays a month, I pad the `month` array with days of the surrounding months in order to get complete weeks. I wanted to have these days styled differently. `dayName` and `idem` are custom filters.
<ul id="calendar">
<li ng-repeat="day in month.days"
class="day {{day.day|dayName}} this-month-{{day.month|idem:month.month}}">
<div class="date-number">{{day.date}}</div>
Events go here.
</li>
</ul>
In CSS: .this-month-false{opacity: 0.7;}
.sunday{clear:both}
.day{float:left;width=...;height=...;}
Bam: calendar!One thing I found interesting in the blog article was the notion of "smart controls", but I can rationalize that away as another MVC module; after all, the Windows OS itself is handling all the interesting behavior, and the GUI app is borrowing the behavior. Depending on the toolkit that interfaces with the "smart controls", we get access to events (mousedown, keypress, etc) that can serve as input to one of our application's controllers.
Can you expand more on this? I've used MVC for webapps quite a bit, and find it to work well.
You haven't used MVC, you have probably used Model2. The post we're discussing is about MVC.
http://andrzejonsoftware.blogspot.com/2011/09/rails-is-not-m...
Server MVC (Model2) is not the same as client MVC (the classic one). They are totally different architectures. Patterns that apply to one, don't apply to the other.
You can't get MVC with Rails/Django/Struts. You can get a nice MVC with a Single Page Application or with a desktop app.
A similar discussion was already here: http://news.ycombinator.com/item?id=3035549
Patterns are great, but slavishly following them, and not understanding that there's often multiple patterns for different circumstances can lead to coding dragons.
Honestly I'm sick of reading all those "x is dead"-alike articles. Hey, if you believe the web PHP is dead, Java is dead, C is dead.. etc... Technologies, patterns, languages or structures don't die, in fact, if you really fancy you could write your application using C code and compiling it into asm, why not? If it works, perfect! There are enough examples out there where old technologie works. And I think people tend to be spending too much time thinking why something is imperfect, or how to do it better, instead of actually making stuff that rocks.
If you really do have the need to improve something, prove it! Make a useable example, write a framework, library or new language if you really need to.
I was with you until this. I think it's actually important to think about where flaws are and how improvements could be made.
The literary critic Howard Bloom actually argues that many of the best creative works are agonistic: they take a previous masterpiece and say, "I could do better," and from that claim do. The produced work ends up being a response, saying, "That was good, but here's your mistake, here's how it can be done better, and look how well it turns out."
How much of my code survives if I drastically change the view?
For example, if I want to switch to a new desktop, web or text console interface, can I reuse much of the application? Of course, architecture changes this significantly (particularly web architecture), but still, if I cannot swap out the view, then I'm losing out on one of the significant advantages of an MVC architecture. One way to make sure this works is to start with 2 views from the beginning - the view you're actually going to ship, and a headless view for tests.
Quote from the inventor of MVC, Trygve Reenskaug:
"The essential purpose of MVC is to bridge the gap between the human user's mental model and the digital model that exists in the computer."
Source: http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf
And you are not a human user, you are an engineer.
I am most certainly a human user.
Maybe there is some significant difference, but you haven't outlined one other than "it's not what person X says MVC means".
We call those, "views".
[1] Although were talking about Model 2 here, so thats irrelevant. Come to think of it, this whole discussion is pointless: we're arguing about whether views in a Model 2 architecture are proper MVC views...
If you're claiming that regular HTML views are compliant with MVC because they have HTML links, one can argue that some RSS readers convert the reference links from the RSS feed to actual HTML links that you can use to navigate to the individual RSS item. How is that different than a regular HTML view with links?
I see no purpose for this distinction. A view is an output representation of the model data.
Given the challenge, "How much of my code survives if I drastically change the view?", I think json and rss make perfect sense. They are drastically different output representations of the data.
That said, non-HTML output bypasses the view entirely in Rails (it makes sense to), so it can equally be the case that the distinction is correct.
https://github.com/rails/jbuilder/
It looks a lot like a view file :)
as JSON encoded output, as XML....
You have just provided a new definition of a view:
"A view is just an interface layer. Whether it's interfacing to a human or not is irrelevant"
If this definition suits your application, good for you. But you are no longer talking about MVC.
Unfortunately, the wrong choice comprises nearly half of comments made. You were obviously right the first time - let it lie :)
The problem here is that Reenskaug explicitly abrogated the authority you're appealing to. He recognised that MVC as originally posed was problematic and incomplete, and invited others to refine it via a pattern language, making MVC a metadefinition. At this point in history, you simply can't point at "MVC" and say that the original definition is canonical.
If you're still going to appeal to the original definition, the View still isn't a visual representation. That's the Editor. Everyone seems to forget about that bit. If you exclude the Editor, we're no longer in Reenskaug-MVC, so even if they weren't in the first place, machine representations would be ok. If you include it, your objection to JSON and RSS representations per se falls apart, because they can be perfectly valid technical details of the Editor layer under control of the View.
If this definition suits your application, good for you. But you are no longer talking about MVC.
Yes, I am. I'm just not talking about your definition of MVC, which is needlessly proscriptive.The Formatter inspects the Request to determine what format it should be (html, json, xml, etc.), and returns the correct View to the Controller, which then passes the Model to that View.
Anyway long story short. I don't think the pattern is abused anywhere near as much as the term as been.
That is, a model encompasses extracting the knowledge and turning into something that the controller passes to a view or another model, but is not processed much (if any) during the transfer. At most, it might be combined with data from other models into an uber-record that is passed to the view.
The way we chose to do things in LedgerSMB (starting with the new code in 1.3) is to adopt a sort of untraditional MVC. The view has to represent the model and vice versa (information present in the model thats not in the view is never used, information present in the view but not in the model is always discarded).
However, the controller scripts are agnostic of this structure. They just glue these together and process operations. Therefore depending on the changes to the view, you may or may not have to change the model, but you should not have to change the controller unless you want to change what a button does. Similarly for reports, you can change these to your heart's content and no underlying changes are needed at all.
We've run into a lot of resistance from folks more used to traditional MVC stuff because the controller only needs to know what it minimally needs to know (and usually this is virtually nothing). Since everything is hash refs passed around....
But in the end the approach works, and specifically because we try hard to keep things fairly abstracted and loosely coupled within the application.
user = userService.login(name, password)
It's also nice to abstract this service layer with some clean interfaces so that you can replace the underlying implementation, for example to move from MySQL to Memcached.Using events for everything has appeal but my experience is that the added synchronicity problems creates unneeded complexity and makes reasoning through the logic and debugging hard.
The O and E in MOVE sounds effectively the same as the C in MVC.
Model objects are generally just POCOs (or POJOs, or whatever) and should not know about their storage mechanism or dealing with user events.
Sounds like he's basically been doing MVC wrong, and thinks MOVE is something new, when really it's just closer to the way MVC should be done in the first place.
If userService.login method knows how to check a User's password, it's probably inextricably tied to the model and, therefore, part of it. Even if it's on a different module, it cannot be reused with a completely different model.
<?php
class AuthController extends Controller {
public function __construct(Request $request) {
$this->service = AuthService::getInstance();
}
// reflection calls a Module + Action attribute to {module}Controller
public function login(Request $request) {
if ($request->getRequestMethod() === WebRequest::POST) {
if ($this->service->login($request->getAttribute('username'), $request->getAttribute('response')) {
die('{ "success" : true }');
} else {
die('{ "success" : false }');
}
}
}
}
class AuthService { // Application Service -> it just defines a clear API, not a Domain Driven Design service
public function __construct(Session $session) {
$this->session = $session;
}
public function login($username, $response) {
try {
$user = User::getRepository()->getByUsername($username);
return $user->isValidChallengeResponse($this->session->getAttribute('challenge', 'auth'), $response);
} catch (UserDoesNotExistException $e) { }
return false;
}
}
class User {
protected static $repository;
public static function setRepository(IUserRepository $repository) {
self::$repository = $repository;
}
public function getRepository() {
return self::$repository;
}
// yeah yeah, it is arguably if this belongs as a Domain method of the user…
public function isValidChallengeResponse($challenge, $response) {
// and yes, this is very weak challenge response…
return md5($challenge . $this->getPassword()) === $response;
}
}
?>
If anyone can tell me what's wrong with this type of MVC, except it isn't using an actual View in this limited example, I'd love to hear it. Controllers should be thin, models and services should be thick.Not only is there an MVC on the web server and a MVC in the web browser, but there is an MVC in the db as well, if it is well designed and well encapsulated. For example a well normalized db may have a model (physical table structure), a view (logical table structure) and controller logic (which essentially maps these two together and may enforce other things like audit trails and app-level replication).
The biggest problems I've seen in model 2 architectures is weak models. The side effect of this is everything gets stuffed in the controllers. This is understandable because there is no observer pattern and therefore the models don't have nearly the power they do in real MVC.
Heres a great explanation of the MVC[1]:
In a nutshell the classic MVC architecture work like this. There is a model that is at the heart of the whole thing. If the model changes, it notifies its observers that a change occurred. The view is the stuff you can see and the view observes the model. When the view is notified that the model has changed, the view changes its appearance. The user can interact with the view (e.g. clicking stuff) but the view doesn’t know what to do. So the view tells the controller what the user did and assumes the controller knows what to do. The controller appropriately changes the model. And around and around it goes.
[1] http://michaux.ca/articles/mvc-architecture-for-javascript-a...
Having used MVC for many years, and in the environment where it was invented (Smalltalk-80), I couldn't help but wonder why he was reinventing MVC while thinking he was criticizing it.
If your controllers are getting fat and spaghetti like, I wouldn't blame MVC. There are many patterns one can use that are compatible with MVC without going to a completely different architecture. For instance, if you need to encapsulate multi-model interaction you can create a presenter abstraction that the controller simply calls into. Just because there is a bunch of code that ends up in the controller because "you don't know where to put it" doesn't mean there isn't a better place to put it without re-designing the entire application.
Another thing is while I love the data-binding event deal, this really only works for client-side frameworks like Backbone. Server-side kinda goes at the window, but I suppose you could add a framework that piped event signals in the response from changes that occurred in the ORM layer (although this further couples components).
I'm not convinced that separating the data from the methods that operate is a great idea unless you want to go purely functional. Doing this clearly breaks encapsulation, throws any notion of OOP out the window, and still binds the "operations" too closely to the data. Generally speaking, the data is useless without the operations and vice versa.
So the real difference between MOVE and MVC, at least according to this article, is that models are no longer useful on their own, the controllers aka "operations" know everything about how to manipulate models (it shouldn't), and models generate events which are only consumed by views, which makes no sense if you wanted to use the model on its own (but you can't without your operations).
Generally speaking, the model should MODEL something. That includes data and behavior. Without both, you have a database, and a set of operations kinda like a C library but only because OOP hadn't been invented yet.
In my mind this further couples all of the components because it actually increases the reliance on each other for them to be useful.
MVC isn't dead. There is a good chance you are using it wrong. I highly suggest Rails Antipatterns. While it is specific to Rails, it works for MVC in general. http://www.amazon.com/Rails-AntiPatterns-Refactoring-Addison...
edit: spelling
Binding data and behavior together breaks the rule of single responsibility, which I believe is far worse than designing separate roles in sepearate components that work together. Models should model the data structure only, if you need a presentation abstraction anyway for multi-model operations. Why not go the extra mile and use this abstraction level for all operations?
It is a false dichotomy that you go either full-OOP or purely functionaly. Models wrap knowledge as the article suggests, That means that, in addition to getters and setters, they might contain functions that let you check "is this the user's password?". I envision these methods to work on a single attribute, whereas multi-attribute and multi-model business logic belongs to operations.
MVC isn't dead, but it was a local maximum OOP gave us. Event-driven development seems to raise and work well with objects and datasets.
Are you suggesting that OOP breaks the rule of single responsibility? Any 'operation' that modifies the internal data should belong on the model. Would turnLeft() belong on a Car model? Or do you pass a Car into a turnLeft operation? In my mind a turnLeft operation shouldn't know the details of how to turn a car left, or a bike left, or a boat left. These operations belong in the Car, Bike, and Boat.
Obviously, I don't say "turn your handlebars such that the left side is closer to your chest," or "rotate your steering wheel counter-clockwise," when I mean to tell someone to turn left at the next intersection. I might, however, tell a sailor to steer to port at the next buoy. =)
EDIT: forgot to say, fwiw, that I agree that such actions do not belong in the model. The things go in the model, and the only actions the model should support are those relative managing the data in the model, not interacting with the data... That is, after all, what the controller is for.
I see thing which is called a Car, an instance of which is stored in the Model, which may contain other things, including other types of Transports. The user interacts with the View, instructing a left turn - the controller grabs the Car (why it grabs the Car, and not the Bike is undefined =), and tells it to turn left. None of the M, V, or C understand what a left turn is - but the controller knows that the Car can perform such a thing if instructed. The Controller knows it can tell the Car to turn, because the Car is descended from a Transport, and all Transports have a virtual method for turning.
That last sentence was in my head and unfortunately took over my comment.
I think any logic inherently tied to the data should be in the model. The controller shouldn't have to worry about internals of the model any more than necessary.
Here's an example. Suppose I create an i18n framework for handling numbers. I certainly am going to include in it a function for converting the number into the current user's localized format, and another one for converting the number from the current user's localized format. I will probably also have functions to convert to/from db formats and to/from arbitrary formats. Not all of these will be called by the controller (in most cases, just the ones to/from the user's localized format and maybe an arbitrary format on rare occasions).
This way the controller script can just call something like $number->to_output; and get the localized string back. Other model objects can call $number->to_db and get a string suitable for entry into the db.
Interestingly in LedgerSMB 1.4 where we have done this, the number of cases where the model calls number i18n functions are remarkably small. These are usually called in the model or in the view simply because the controller probably shouldn't have to worry about this, and the view gets to worry about display logic.
However, instructing a contained object to take some action at the user's request that is unrelated to display or management of contained objects is neither the responsibility of the view or the model, but specifically the task of the controller.
I want an email to be sent to me when the quantity on hand of a part gets below the re-order point.
So now, I build a program that listens for notifications, and when it gets one, loads the data, erases the queue, and sends me an email.
I build this so the app itself doesn't know this is required or is going on. Database triggers, queue tables listening scripts, and templates all are triggered when the db write takes place.
Now, what we have here are arguably two MVC environments where the model behavior of one triggers a model change in another, which triggers a controller to run, calls some other model stuff, creates an email (via a view) and sends it.
But this is the sort of action you are talking about, right? You think this violates separation of concerns?
I'm speaking to the point that if you are separating Model, View, and Controller, and you have complex objects in your model that can do many things, it would not make sense to put all of the logic about what those things can do, how to do them, and when to do them in the model. Otherwise, you're simply blending the model and the controller (which may not be a wrong thing to do) - so you just have MV.
Let me give a more concrete example: I have a model which represents a network of connected complex "devices," there are five types of devices, each that can do 50 distinct things. The model can add a new device, delete a device, or retrieve an existing device. It can also ask the devices what their names, and addresses are, and what features they support, on behalf of any view which needs that information.
It cannot, however, tell device 1, which is of type X to take action "foo". That, instead, is implemented by a controller attached to a view that shows a big button that says "Do Foo", and a drop-down with the list of available devices that can do Foo. The view passes the press of the button onto the controller, which asks the model for the selected device, and then executes a "do Foo" command on it, and then, perhaps, contacts the device again to check that "Foo" was completed.
If all such logic were built into the model, I'd have several hundred methods in it, and I'd be very quickly looking for somewhere to move all of this logic, like, you know, controllers.
My point though is in essentially shimming functionality. In my example, for example, here is how it would work.
1) User requests "save this invoice", which activates a controller script which automates the model elements for "invoice" instantiates an invoice (since this is a stateless web app) and saves it.
2) The model saves the invoice by writing it to the db.
3) Saving to the db fires a trigger which checks ROP vs on-hand and where ROP is greater saves a record in a queue table and issues an asynchronous notification, which doesn't have any immediate effect.
4) Controller commits the db transaction. The DB sends out the notification and makes the rows in the queue table visible.
5) Controller for application b wakes up (let's say every 15 min) and polls for notifications. Ok, we got one. Look up the queue table, prepare the email (model stuff) runt he template (view stuff) and sent it out (model stuff again).
So what I am getting at here is a way to have model events have side effects which are outside the scope of Application A, but are at least triggered by model operations. This is not an anti-pattern really because application A is not relying on those side-effects for operation. However if you look at application A as the primary one and application B as contained within it, then application B can only be described as contained within the model of application A, from application A's perspective, because all of its functionality is abstracted behind the model. From application B's perspective, there is a model, a view, and a controller, and it doesn't care as to where notifications and queue table data is coming from. From it's perspective it is a loosely coupled app in its own right.
But as always what I am suggesting is that common sense usually determines the best place for a given piece of logic. LedgerSMB is very model-centric but there are cases where we have a fair bit of logic in the controller.* I think that anything which is inherent in the model belongs in the model. So back to the vehicle analogy, a bike object should support a $bike->turn('l') and a $bike->turn('r'). However telling the bike when to turn left is the controller's job.
* for example in contact and employee management, the controller has to coordinate a lot of different model operations, leading to unusually long/complex model code in the system.
That's a good thing, though. They're at the verge of rediscovering SOA now and there's hope this incarnation will be less plagued by IOC-fluff and boilerplate, simply because the involved people have more of a hacking and less of an engineering background.
I, for one, am looking forward to the "great shattering of Rails".
Everyone thinks everyone else is doing it, few are actually doing it and the ones that ARE doing it are doing it wrong.
We use a similar pattern that we internally call "Actions". An Action, in our parlance, is similar to the Command pattern from the Gang of Four. It can be invoked from anywhere and performs a single state change on a single model, or even multiple models (if several need to be updated at the same time, in the same transaction).
Separating Actions from Models was a huge step in writing readable code, and it's immediately clear what is happening in the system at any given time. Any Action can invoke any number of "child" actions, as well, to maintain encapsulation. For example: when a user registers on the site, we trigger a RegisterUser action, which in turn calls a CreateUser action and a LoginUser action.
Basically, we took any complicated method on our models and turned them into Action classes. Common concepts like database transactions, logging, event tracking, and so forth, can now be abstracted away, and don't need to be re-implemented in each model class. It's a huge productivity increase and a real win for software engineering.
I highly recommend this general approach to any large software system, and I'm grateful that we're all experimenting with things beyond MVC.
Maybe I don't understand MVC, and you all can tell me How Wrong I Am, but here's how I understand MVC at present:
Your Model is a public API, a Service Gateway -- and it should do a couple of things in principle. The first is that it should be able to manage a list of subscribed view/controllers, and push updates out to them -- this was difficult with Web 2.0 but we're now moving to systems where this is considered normal. The second is that it should define a set of API commands which change that state and push out those subscriptions. That second bit is crucial, it's the difference between writing assembly and Python. If you have logic in your controller then it's probably because your model does not expose certain high-level concepts which your controller would use directly, so you're taking data from the model and building a higher-order model in your controller, before you operate on it.
It helps me to remember that in Smalltalk the idea was to always have <view|controller> pairs. They were always the same object split in two; each view had its own controller and vice versa. The controller is supposed to be input-oriented and the view is supposed to be output-oriented; the model says "hey, X changed" and the view updates what X looks like; the user clicks on X and the controller sends a signal to the view to change some more, the user erases X and the controller sends this request to the model, which will update the view when the request is complete.
Viewed this way it's really hard to see what the difference is supposed to be between MVC and MOVE. Clearly the messages in MVC are the Events in MOVE. Most of the controller logic has been pushed into the View, which should now handle input actions. Data cannot be dynamically pushed from the Model to the View because this is of course a Web 2.0 technology (pre-cometcasting, pre-websockets). The Operation sits in a grey area, implementing higher-order abstractions from the lower-order model.
Maybe we could do better with a hybrid, because the idea of decoupling subscriptions from the public API might actually be a good idea, in line with the Clojure philosophy that things should be de-complected into their simplest representations. But if I understand MVC right, then I don't see why you've got all your business logic in your controller. Heck, the View is supposed to be client-side, why isn't your Controller client side? Or if it is, and you have all this business logic in it, why are you trusting the client to do your business logic? Your gripes with MVC don't make sense to me.
So they're fixing a valid issue with an invalid solution, causing bloated and dual purpose (business and application logic) Controllers.
The problem with MVC is that it makes people think that there are only supposed to be three things, and if something they require doesn't fit into thing 1, and doesn't fit into thing 2, then it must go into thing 3, instead of inventing a new thing 4 for it. Most real-world software is complicated enough that it requires more than three pigeon holes. Cargo-cult MVC programmers who can't think outside of three boxes are why the Controller usually gets gang[4]-banged into a kitchen sink of everything that didn't fit into the model or the view, because the words "Model" and "View" have easily understood meanings, but "Controller" could mean anything, so it gets some of everything.
Services is where the logic of your application should live, and services should be HTTP (or any protocol) agnostic. They should only speak in models and native types, and should abstract all of your logic away from your controllers and models.
This leaves the controllers as a thin http handling layer that parses inputs and then lets the service handle the work.
The response from the service is then transformed appropriately (JSON, HTML, etc) and sent back to the caller.
Just my $0.02
"Developers are sometimes surprised when they learn that the Observer pattern (nowadays commonly implemented as a Publish/Subscribe system) was included as a part of MVC's architecture decades ago. In Smalltalk-80's MVC, the View and Controller both observe the Model: anytime the Model changes, the Views react."
So, not really new actually.
[1]: http://addyosmani.github.com/backbone-fundamentals/#mvc
Essentially it's a way to move code where multiple objects collaborate to achieve something into its own separate class (Context). However when executing in a context, each involved object takes on a "Role" which grants its additional methods specific to this context.
This doesn't make any sense to me.
The first problem is the blatant argumentum ad populum—just because other things are popular right now doesn't mean they're better.
The second problem is: I simply do not agree that we have new technologies that are so radically different and empowering from those that were available when MVC was invented. Indeed, Smalltalk (the language in which MVC was conceived) has late binding, dynamic typing and code blocks. I still think ‘modern’ scripting languages are playing catch-up with Smalltalk and LISP in terms of power, performance and clarity of expression.
Trygve Reenskaug (the inventor of MVC) later went on to develop DCI, a system which complements MVC, rather than replacing it wholesale. I'd recommend reading the Wikipedia page for more info, it's a coherent proposal and it seems to require the creation of far fewer classes and objects: http://en.wikipedia.org/wiki/Data,_context_and_interaction
The issue I have with traditional web-framework MVC is that it assumes that each URL associates with one controller, which I've found to be very straightjacket-esque. Often the pages I'm building have many separate bits of functionality present, from simple stuff like a login box, numerous widgets, and then the main thing the page is about.
In lift, each URL maps onto a view, which will contain the templating code for that page, including perhaps inheritance to pull in an overall template, and then will contain one or more (and perhaps MANY) snippet invocations.
A snippet in Lift is kind of sort of like a controller method. It takes the contents of it's template tag as input, and as output returns a transformed document tree, using what ever resources (models, web service calls, calling out to other classes, etc) it wants to do that.
If you write the snippets in a general way, binding text off of IDs, this allows you to get different outputs for the same data, depending on how you call the snippet - it's like passing a partial template in as a closure. Very different but powerful - the snippet handles the LOGIC, but only abstractly the templating.
It's a very powerful paradigm - it frees you from the MVC straightjacket, since you can arrange and organize your code however you like, but forces very strict separation of concerns - it forces you to compartmentalize your business logic, but doesn't force you to do it a certain way. Lift does really cool stuff with your xHTML/HTML5 templates too - it's truly operating on a server-side DOM tree, none of this is textual substitution.
http://www.assembla.com/spaces/liftweb/wiki/Templates_and_Bi... for more info.
Also, Twitter's recent 180 on shifting some processing from the client back to the server [1] suggests a server-oriented framework like Lift's is worth considering, despite the hype and excitement around client-heavy Rich Web Apps. Lift does the API-consuming rich client model as well, but its uniqueness is the DOM transform stuff.
Very different mental model than MVC and hard to get started with for some because of that, but here's a great bit of advice on best practices I came across recently (especially the part about pretty everything being done via either LiftRules or the S object) [2].
1. http://engineering.twitter.com/2012/05/improving-performance...
2. http://www.quora.com/Lift-web-framework/What-are-the-best-pr...
I cant understand the distinction between a 'setter' (stated here as part of the MOVE 'model') and 'functions that let you save... to a database or upload... to an external API' (stated here as part of the MOVE 'operations').
I would understand the logic a lot more if the 'model' excluded 'setters' entirely and just included 'queries' (which don't change the underlying data set) as opposed to 'commands'/'setters' (which do...). As it is I'm not sure where the line is between 'operations' and 'model' except for the use-cases that have been explicitly stated.
And Events are handled with a combination of Key-Value Observing and UI binding. http://developer.apple.com/library/mac/#documentation/Cocoa/...
Controllers still exist but the design of a program is easier to reason about if everything that mutates data is pulled out of the controller.
UI changes must be made on the main queue, but the above design helps pull out model changes, network requests, etc on to background queues.
I've spent the last few years on an piece of software where the model and controller must be reusable between desktop, phone and tablet.
I started with a layered approach. Then I moved to MVC. After that I discovered MVVM. I finally ended up with an MVVM/Naked Objects hybrid.
The result is views that make changes to the model via command bindings, and respond to changes in the model via event bindings. The application (aka controller) is similarly bound to the model, and contains all business logic. It's clean, easy to maintain, and easy to test against and debug.
The views are different for each platform (desktop, phone and tablet), the model and application are re-used as-is.
I guess my point is that none of these approaches (MVC/MVVM/MVP/etc.) are bad. Each is good within a pretty small scenario window. The trick, probably learnt through experience, is knowning when to use which.
The problem with messy code or where it lives will not go away because you think about it differently, you just have to either hire better people or spend more time and money refactoring.
Whereas controllers have a pretty undefined lifetime, operations are finished when they're done. This means that operations can use each other to get work done, a pattern you don't see with controllers.
A design pattern is a reusable solution to problem, given a certain context (set of constraints).
My design pattern study group iterated over the Gang of Four book 3 times, please many others. The MVC sessions were the least constructive.
No two people could agree on what is and isn't MVC.
Or MVP. No, you're not doing it right. Oh, MVC can only be done "correctly" using Smalltalk.
Yadda yadda yadda.
I can't even begin to discuss "MVC web frameworks". Huh? Methinks the only reason for "MVC" is to justify Spring, inversion of control, containers, dependency injection, annotations, and all that other useless enterprisey J2EE-esque shovelware.
I agree with jerf's statement (upthread) that devs should worry more about DRY than MVC.
Models are just data, View are just representations and Controllers are just endpoints. You can program your own way in your language, and if you can categorize your code as such, you can argue it is MVC.
And of course, because its just a concept, anyone in the world can argue why your implementation is not MVC as well.
No, MVC is not the reason to justify Spring, inversion of control, containers, dependency injection, annotation and all other "enterprisey J2EE-esque shovelware" as you mentioned.
MVC has been around since SmallTalk (you know, before even Java...). Heck, you even get MVC in Rails. You see Spring in Rails? Dependency Injections? Annotations? Of course not, since I could not even begin to think they are related.
Sure they are.
Spring is the Java community's effort to get some of that dynamic programming goodness (ahem).
Rails is the Ruby community's effort to reproduce the unmaintainable mess of J2EE.
You couldn't have one without the other.
Martin Fowler has an excellent write up on the history of MVC and related patterns (and resulting confusion) in http://martinfowler.com/eaaDev/uiArchs.html.
I've written a direct manipulation vector structured graphics program. Think FreeHand / Illustrator with a scenegraph. I tried every which way to make something MVC esque. No can do.
I believe, but cannot prove, that the MVC failing(s), eg tight coupling, unclear flow of control, comes from the Observer/Listener like message passing between the players.
Further, I believe some future UI paradigm will be a hybrid, mutant love child, inspired by, of functional reactive programming and an VRML-97 like event model (FROM->TO style patchcord event routing). It's on my to do list, but I'm easily distracted and followed thru.
And that wouldn't happen to have anything to do with the fact that "you" either don't know any other patterns or solutions besides MVC, or are under the impression that using MVC somehow forbids you to use other patterns?
Not to mention the fact that the definition of MVC that the author uses is false (in a way that describes MVC as more simplistic and limited than it truly is), but after so many years I'm not even going to argue with that any more. Just fucking Google it.
tl;dr: Those who cannot learn from history are doomed to repeat it.
Everyone repeats history. Some repeat the good parts. Others repeat the bad parts. Learning from history allows us to try to stop repeating the bad parts and do better with the good parts.
What do you think helpers are in PHP MVC frameworks? They are code blocks that should not go in controllers but are required; like a password generator or reformatting for print command.
Go use Symfony to see how events and MVC mash up together. They do a good job in there.
Author's next post will be about including services for controllers/helpers/actions that are called more frequently. Once again, Mr. Author, check the PHP framework called Symfony.
RAPHT (https://github.com/DanielWaterworth/Raphters/blob/master/RAP...) attempts to something similar (adding more layers of abstraction to MVC) but I have the same problem with that.
If we were really understood the problem we'd have come up with a way to make things simpler, not more complicated.
I think the real problem is that MVC is understood by different people to mean different things but they think they're talking about the SAME thing. Back end developers tend to think of the view layer as a trivial thing ("It's just HTML and Javascript! How hard can that be?") and front end developers tend to think of the model layer as trivial. ("Look, my backbone.js code is handing out and consuming JSON, how hard can it be to persist that?")
With a pattern like MVC, where developers implement it again and again, and many of these are junior devs, it's highly likely that people who don't entirely understand the pattern are going to be adding code. The correct use of the pattern is going to get diluted, and certain classes are going to get overstuffed with code that often turns into spaghetti code.
I'm not so sure this is the fault of the junior developers. If there is one "obvious" place to expediently stuff code to implement new functionality then this is actually the fault of original designers. I don't know of any pattern for building applications that doesn't fall into this trap, but I think that one which escapes it is possible through some trick of code organization and programming language technology.
Doesn't address any of the actual issues with writing an MVC web application.
MVC -> Views are templates, Controllers are HTTP server end point bindings and Model is everything else.
Rookie mistake; put logic in controller actions. No! This is a terrible idea: your controller should never do more than: parse input, apply update to some model object, generate response view model.
'Model' does not mean 'Something that serializes and goes into a database'. It means everything else. The entire state and associated classes that manipulate that state. That's where these operations from MOVE exist.
I mean, if you want to critize MVC (especially some popular frameworks...), go for it, but I'd be much more interested to hear how a new approach addresses:
- What about all that javascript / flash / etc? Where does that fit in?
- How do you effectively test controllers and views?
I usually get around the cited issues through dependency injection into the model. That is, instead of placing large amounts of logic in the controller, I let the model hold the logic.
In a naive implementation, this may couple the model to things it shouldn't be coupled to. So, to avoid the model coupling to infrastructure resources (say, storage), I let the controller inject those objects into the model, as needed.
But, I realize that that's an architect-y, OO kind of way to do it that requires some background knowledge which can may obfuscate the code. So, I'm all about making things easier for everyone.
As others have mentioned, it'd be useful to have a more sophisticated example.
As to MOVE, the issue that the author points as the problem with Controllers in MVC is that'controllers are nice self-contained bits of.. what?'. At some point people will start asking these questions about 'Operations' and 'Events'. What would you classify as an 'event' vs an 'operation'. Some mature Rails projects that I've seen already uses this paradigm - there is an internal synchronous pub/sub event listener to which messages can be pushed by both the controller and the model. Even then, there is always a question of where to put what. Some answers are very clear - like an audit log which is only a side effect. But it is not the case always.
The author is trying to solve this 'classification' problem by giving us a more granular model. This can help to a certain degree - but there will be some point where even this wont help us. At that point we can choose go to a finer granularity, or ask the question whether all this extra organization is worth the hassle?
Abstractions are not without a cost. Some abstractions are too essential for any project. Some abstractions are nice to have. But all of them have a cost. In the case of MVC, the cost of the extra organization is paid many times over by the increased maintainability of the application. But given the number of components the MOVE paradigm advocates, I'm doubtful whether the added organization will be worth the cost.
I agree with what DHH said on a recent podcast - it is easy to talk about concepts in abstract and they can look really good. But what changes the game is a real implementation and being able to contrast the code 'before' the change and 'after' the change. This is not feasible all the time - some things have to go through the ideation and a slow testing phase. But at the least, I'm looking forward to see a non-trivial application that uses this paradigm. I'm ready to try imagining how it would have looked in MVC and decide whether the extra organization is worth it.
I primarily use PHP, and have gotten in the habit of using a service layer to handle business operations. I've found that it's worked extremely well, and so far does not seem restrictive. It's let me clean up my controllers and models quite nicely.
It's been awhile since I've used the RobotLegs Actionscript framework, but its 'implementation' of the MVC pattern seems awfully close to MOVE.
Overall, I think the author makes a good case of how to improve MVC application development, regardless of whether the name should change or not :)
Look at Django, it is often called MVT but yet it follows the MVC conventions. Maybe the language you are using is forcing you to add beef into your controllers hence the negative view of this pattern. But ultimately if your coding in Python you would be abstracting logic code out into your Models and Modules and only making references to them in the Controller.
I write my code initially as one monolithic controller, and then refactor my code into an MVC pattern. It doesn't take that long to move functions from one object an other, and now you're working with an already-functioning piece of code rather than guessing how things might work later on.
I don't think so, but I feel that Grails may be the closest thing currently. It has a concept of a Service construct that feels like an Operation. Then again I could be completely wrong.
http://www.martinfowler.com/eaaDev/uiArchs.html MVP via M. Fowler seems a little closer to what client side should feel like (imho).
http://en.wikipedia.org/wiki/Model_View_ViewModel MVVM also makes sense for a client side app, which is just an extension of MVP.
IMO MVC on the client side is just a carry over from people who were experienced in writing web apps who wanted something that felt familiar on the client side. It's a leaky abstraction at best.
I'm not sure what the right answer is, but I certainly feel like the race for rich client-side apps had too many frameworks settle on MVC without thinking about the bigger picture.
Of course, MVC was developed and popularized on Smalltalk.... which had both of these notions...
That sounds like more than just wrapping knowledge to me.
Also, why do you absolutely want to fit everything into a framework? Or a pattern? Business logic goes into your domain models. Don't mix your business logic with your framework, that's about it...
http://news.ycombinator.com/item?id=554397
Once I see "X is dead" in a article title, I stop reading.
You simply divide controller into 2 parts.
1. Events 2. Operations
I too find event also can be think as a router. The title is bad. This is not new. But a good useful practise.
What the hell is he talking about? Has he never worked with Fat Model™ design?
Do you haz teh codez?
The idea in practice gives a much better idea of what the pros and cons are.
Kind of like in MacOS it has methods and delegates?
If you really want to "get" the original MVC, see the classic book "Smalltalk, Objects, and Design" [1] which explains MVC and other OO architectures as well as the principles behind them, which might guide you to picking an appropriate structure for applications that don't fit the GUI/MVC paradigm.
[1] http://www.amazon.com/Smalltalk-Objects-Design-Chamond-Liu/d...
Looking back at it now, it had everything your typical web MVC framework has, just slightly diffrent:
* Models, with cleanly encapsulated functionality, but without an ORM. I only built small websites, so all related database tables were managed by the same model.
* Controllers that handled all input and delegate it to models.
* Views in the form of HTML code following the controller code in the same file, but strictly separated.
* "Forms" that abstracted away the controller/view and input validation of forms in a neat, reusable package.
My point is that whatever you come up with that actually works well and lets you be productive will more-or-less resemble MVC.
Out of the three terminologies (state, representation, flow), the third one is arguably the most tangled. I find it healthy to refactor it into reusable chunks (operations) and event-driven flow management.
The problem was, in my opinion, that operations should have not been put into controller units. It attracted more copy-paste solutions in my experience.
The original MVC designs and sample code all had views and controllers observing models through an Observer based event pattern.
The operations were the controller units. The events were not.
http://emberjs.com/images/ember_mvc/embermvc.png
Operations are similar to controllers for sure. But where's routing or state? We don't have a full picture here.
After trying out that new meta-pattern, things get overly coupled, too many bi-directional relationships between state, views, models, and controllers/operations.
I'm going to have to agree with the parent here. Without example code to compare, how is this different than MVC? (or "MVCE")
app.trigger 'boom'
Somehow, I'm just seeing the Observer pattern and the MVC pattern in the OPs post.
Eventing is HORRIBLE. Regardless of the source, but models especially are not the place to be firing events.
This was all tried years ago. Before writing an article purporting to replace a foundational concept in application development maybe do a little more research into what the actual practical solutions to these factoring problems are.
> it's the part of the Operation to both decide what to show and also get it in the correct format to show
Did you mean Views, not Operations, here? Or maybe I'm missing something.
In a world where "social" apps are increasingly important (and this time I use "social" non-pejoratively, because even if 99% of "social" is crap, the other 1% is damn important) and notifications need a first-class status, MOVE (the separation between operations, which are agent-initiated, and events, which are observed and can come from anywhere) makes sense.
>the problem with MVC as given is that you end up stuffing too much code into your controllers, because you don't know where else to put it.
What was that? You stuff all of your logic into controllers then claim that MVC is broken? Your ugly face is broken. Uglyface.
Now an important question: how would you practically implement this? Would this dicate a separate framework/language altogether or something else (I have a cursory knowledge of development, so play nice)?
Edit Just noticed the footnote at the bottom of the article linking to these: https://github.com/bitlove/objectify and http://collectiveidea.com/blog/archives/2012/06/28/wheres-yo...