MVC Applied To The Web
The web heavily relies on the HTTP protocol, which is stateless. This means that there is not a constantly open connection between the browser and server; each request instantiates a new communication channel between the two. Once the request initiator (e.g. a browser) gets a response the connection is closed. This fact creates a completely different context when compared to the one of the operating systems on which many of the original MVC ideas were developed. The MVC implementation has to conform to the web context.
An example of a server-side web application framework which tries to apply MVC to the web context is Ruby On Rails.
At its core are the three MVC components we would expect - the Model, View and Controller architecture. In Rails:
- Models represent the data in an application and are typically used to manage rules for interacting with a specific database table. You generally have one table corresponding to one model with much of your application’s business logic living within these models.
- Views represent your user interface, often taking the form of HTML that will be sent down to the browser. They’re used to present application data to anything making requests from your application.
- Controllers offer the glue between models and views. Their responsibility is to process requests from the browser, ask your models for data and then supply this data to views so that they may be presented to the browser.
Although there’s a clear separation of concerns that is MVC-like in Rails, it is actually using a different pattern calledModel2. One reason for this is that Rails does not notify views from the model or controllers - it just passes model data directly to the view.
That said, even for the server-side workflow of receiving a request from a URL, baking out an HTML page as a response and separating your business logic from your interface has many benefits. In the same way that keeping your UI cleanly separate from your database records is useful in server-side frameworks, it’s equally as useful to keep your UI cleanly separated from your data models in JavaScript (as we will read more about shortly).
Other server-side implementations of MVC (such as the PHP Zend framework) also implement the Front Controllerdesign pattern. This pattern layers an MVC stack behind a single point of entry. This single point of entry means that all HTTP requests (e.g.,
http://www.example.com
, http://www.example.com/whichever-page/
, etc.) are routed by the server’s configuration to the same handler, independent of the URI.
When the Front Controller receives an HTTP request it analyzes it and decides which class (Controller) and method (Action) to invoke. The selected Controller Action takes over and interacts with the appropriate Model to fulfill the request. The Controller receives data back from the Model, loads an appropriate View, injects the Model data into it, and returns the response to the browser.
For example, let’s say we have our blog on
www.example.com
and we want to edit an article (with id=43
) and requesthttp://www.example.com/article/edit/43
:
On the server side, the Front Controller would analyze the URL and invoke the Article Controller (corresponding to the
/article/
part of the URI) and its Edit Action (corresponding to the /edit/
part of the URI). Within the Action there would be a call to, let’s say, the Articles Model and its Articles::getEntry(43)
method (43 corresponding to the /43
at the end of the URI). This would return the blog article data from the database for editing. The Article Controller would then load the (article/edit
) View which would include logic for injecting the article’s data into a form suitable for editing its content, title, and other (meta) data. Finally, the resulting HTML response would be returned to the browser.
As you can imagine, a similar flow is necessary with POST requests after we press a save button in a form. The POST action URI would look like
/article/save/43
. The request would go through the same Controller, but this time the Save Action would be invoked (due to the /save/
URI chunk), the Articles Model would save the edited article to the database with Articles::saveEntry(43)
, and the browser would be redirected to the /article/edit/43
URI for further editing.
Finally, if the user requested
http://www.example.com/
the Front Controller would invoke the default Controller and Action; e.g., the Index Controller and its Index action. Within Index Action there would be a call to the Articles model and its Articles::getLastEntries(10)
method which would return the last 10 blog posts. The Controller would load the blog/index View which would have basic logic for listing the blog posts.
The picture below shows this typical HTTP request/response lifecycle for server-side MVC:
The Server receives an HTTP request and routes it through a single entry point. At that entry point, the Front Controller analyzes the request and based on it invokes an Action of the appropriate Controller. This process is called routing. The Action Model is asked to return and/or save submitted data. The Model communicates with the data source (e.g., database or API). Once the Model completes its work it returns data to the Controller which then loads the appropriate View. The View executes presentation logic (loops through articles and prints titles, content, etc.) using the supplied data. In the end, an HTTP response is returned to the browser.
No comments:
Post a Comment