Table of Contents
Glossary
MVC: Model-View-Controller
MVVM: Model-View-ViewModel
MVP: Model-View-Presenter
Foreword
During the recent years lots of JavaScript frameworks based on MV*(MVC,MVVM,MVP) patterns have emerged and a significant part of developers gravitated to these programming patterns. However this question is still remaining that what the benefits of using MV* patterns over client side scripting are. In this article I will answer this question using tangible and simple JavaScript codes alongside a complete delineation of each pattern. In other words in this article an accurate differential diagnosis over MV* patterns will be done. After reading this article the reader is expected to know how JavaScript deals with MV* patterns and how to distinguish between each pattern in this category.
Background
As a developer who has used MVC patterns through MVC frameworks for years, it was still such an unsolved question in my mind that what are the main differences between MVVM, MVP and MVC? I was also wondering how and when we prefer one pattern to another. This question was unsolved until I did a job interview at IBM. However I did it well but I couldn't answer one important question. Can you guess what that was about? Yes, It was about differential diagnosis over MVC, MVP, MVVM patterns. In the meantime I was supposed to represent an article for my object oriented programming class in the university. Hence I thought it would be great if I choose an article about MV* patterns, so that it would be such striking two birds with one stone.
Consequently I chose an article concerning MV patterns. During the time I was reading the prementioned paper, I had to take a look at the other papers published over MV* patterns. At the end I made the presentation and in spite of that most of the students were sleeping during my presentation, I was sure that in the future they would realize how much this issue is important. I suggest reading this article slowly, step by step and also over and over. In the end I hope you don't sleep while reading this article and enjoy it!
MV Patterns : Just a Client-Side Fad or Somthing Useful?!
In most of the software development teams (Even professional teams) JavaScript is still considered as a good solution for whitewashing the project's sh*ts or making the web application "fancier". They often ask server-side developers to code JavaScript. Here is the point where silent disasters get born! Since the majority of developers never take JavaScript serious, after writing some JavaScript codes (exp : "document.getElementById"s), they get bored. As a result they decide to use JavaScript frameworks making their job easier (just see how it is enjoyable when instead of writing the whole "document.getElementById", you can simply use "$()"! ). This is the second critical point where the aforementioned disasters get fed and power up. Eventually the process of writing JavaScript codes will turn into the process of sh*t incubation.
The disasters grow up during the time and get more complicated using more frameworks. At the end the development team spends a lot of time for :
- Debugging the JavaScript errors raising from different frameworks that are often obfuscated
- Obviating the problems by cause of not having unit tests
- Adapting various frameworks in the jungle of frameworks
- Editing the mess of prewritten codes with different coding styles that imposed by different frameworks
- Adding some specific needs have not met by used frameworks. As a result a new coding style will be foisted on the aforementioned jungle
- Adopting the new codes with prewritten ones which itself is potentially such a fertile ground for new bugs
So it seems reasonable when we say: "In big projects using skillful JavaScript programmers is better than using bad programmers who use good JavaScript frameworks". You may ask "what if we use Good Programmers beside JavaScript Frameworks?".The answer depends on the project but often the adroit JavaScript programmers try not to use JS frameworks in enterprise web applications unless they use frameworks very carefully and through a limited and controlled coding environment. Professional JavaScript programmers try to keep their code testable, reusable and maintainable, the codes that are pretty flexible in the constantly changing client-side environment. To do so, they also utilize programming patterns. Since in this article we are supposed to take a detailed look on MV* patterns, let's point out how MV patterns can effect the code in terms of testability, reusability and maintainability.
Reusability
Once a class has been programmed and debugged, it can be handed over to the other programmers being used in their own programs. This called Reusability .You has out-of-the-box Separation of Concerns. In each MV* patterns you have Model and View. They both have their own responsibilities – the model is responsible for encapsulating your domain specific models, on the other hand the view is responsible for showing the model (and eventually handling events, it depends on the framework). This means that your model is not coupled with its representation and eventually can be easily reuse it in different project.
Testability
It is a loosely coupled development framework as it is divided into three layers. This loose coupling helps in reducing the complexity of the web application, and makes it is easy to maintain and provides better Test Driven Development which was one of the goals of MV* patterns to increase the testability of applications.
Maintainability
MV* patterns tend to be modular by nature, which makes it much easier to alter (or even rewrite) one part of the application without it adversely impacting on other areas. They make it very easy to achieve Separation of Concerns that is a key principal to writing code that is easy to maintain and refactor.
As a result using MV* patterns through JavaScript can make the code understandable, maintainable and also testable. A clean and understandable code is another result of using MV patterns. It prevents appearing code jungles due to separation of concerns in client scripting. In the rest of this topic I will dig into the details of MV* patterns. Before I will talk about two important kinds of synchronization methods called "Observer Synchronization" and "Flow Synchronization" which somehow MV* patterns are built on these methods.
Synchronization Methods
Flow Synchronization
Flow synchronization is based on sequential command execution: e.g., read user input from text box A, processing it with method B, and write the result to text label C. Flow synchronization uses direct calls between user interface components and domain components. "Essentially each time you do something that changes state that's shared across multiple screens, you tell each screen to update itself. The problem is that this means, in general, that every screen is somewhat coupled to the other the other screens in the application" (By Martin Fowler). For small applications with relatively simple user interfaces, flow synchronization results in clear and easily understandable code. For more complicated programs and more sophisticated user interfaces, the approach can result in code that is difficult to maintain due to the lack of separation of domain and user interface concerns.
"Flow Synchronization is an alternative to Observer Synchronization for synchronizing screens with domain data. It is, in many ways a more explicit and straightforward way of doing things. Instead of implicit Observer relationships which can be hard to see and debug, you have explict synchronization calls clearly laid out in the code.
The problem with Flow Synchronization is that things can get very messy once you have an unconstrained amount of screens that may share data. Any change on any screen needs to trigger other screens to update. Doing this through explicit calls to other screens makes screens very interdependent. This is where Observer Synchronization is so much easier" (By Martin Fowler). In the below example you can see how a Flow Synchronization method works.
function Load() {
bookName.setText(model.getBookName());
price.setText(model.getPrice());
Author.setText(model.getAuthor());
}
Based on Martin Fowler one of the well-known code styles for implementing Flow synchronization is having a root window which is open for the whole application (It is the main window of the application). Each time you want to open a part of application features a child window will be opened. After changing any data in child, the root window will be updated on closing the child window.
Observer Synchronization
Unlike Flow Synchronization which is based on direct and sequential calls, Observer Synchronization is found on the Publisher-Subscriber style where there is a central publisher who publishs an event and there are a set of subscribers who subscribe the events and start listening the publisher. As soon as publisher raised an event all the presubscribed members get notified. In this method the publisher is not aware of the subscribers and their internal structure, hence we have a good seperation of concerns. Also in this way the encapsulation principles are met.
"Observer Synchronization uses a single area of domain oriented data and has each screen be an observer of that data. Any change in one screen propagates to that domain oriented data and thence to the other screens. This approach was a large part of the Model View Controller approach."(Martine Fowler)
"As usual the trade-off is between complexity and performance. The coarse-grained approach is much simpler to set up and less likely to breed bugs. However a coarse grained approach leads to lots of uneccessary refreshes of the screen, which might impact performace. As usual my advice is to start coarse grained and introduce appropriate fine-grained mechanisms only when needed after measuring an actual performance problem." (Martine Fowler)
Observer Pattern
For implementing observer synchronization we either use the language's built-in delegation & events (For example c#) or we may use Observer Pattern. Rely on dofactory, Observer Pattern "Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically." As you can see this definition meets the oberver synchronization characteristic where it notifies the subscribers. So, let's take a look at Observer Pattern's UML diagram :
The participating classes and objects are :
- Subject (Publisher)
- knows its observers. Any number of Observer objects may observe a subject
- provides an interface for attaching and detaching Observer objects.
- ConcreteSubject
- stores state of interest to ConcreteObserver
- sends a notification to its observers when its state changes
- Observer (Subscriber)
- defines an updating interface for objects that should be notified of changes in a subject.
- ConcreteObserver
- maintains a reference to a ConcreteSubject object
- stores state that should stay consistent with the subject's
- implements the Observer updating interface to keep its state consistent with the subject's
As you can see in the above class diagram the news publisher has two methods called "attach" and "detach". Here the publisher is responsible for attaching the subscribers however it is possible that Subscribers (Observers) subscribe (attach) a publisher to themselves as well. Apart from that which one attaches the other, the method gets a subscriber type (in case publisher attaches subscriber) or publisher (vice versa) as an interface or abstract class and stores them into an array list or normal array(depends on the programming language). Eventually publisher (Always) notifies the subscribers through a for
or foreach
loop. In the next section I will talk about how we can implement Observer Pattern in JavaScript since we need it for implementing some of MV* patterns.
How to Implement Observer Pattern Using JavaScript?
Similar to the other object oriented programming languages(or scripts), JavaScript can implement design patterns in its own special manner, although working with JavaScript is a little tricky and sometimes confusing as well. Therefore I would expatiate how the observer pattern get implemented through JavaScript.
Push vs. Pull
Imagine the domain is a group of Newspaper selling system. Generally in the real world there are two ways selling the newspaper. The first one is called "Push" when the publisher employs some delivery guys to deliver the newspaper to the customers daily. The second style is to put the newspaper in a newsstand in order that customers go there and get access to them ("Pull"). However the first style is based on publisher-subscriber approach, In my opinion the Pulling should be implemented through a Flow Synchronization since each user should get a direct call to the newsstand to get access the latest news. This is considerable since we use "Push" approach in Observer Pattern where I will talk about how we can use this approach via JavaScript.
Building an Observer API
Now that you know the basics of Observer Pattern we are going to see how to implement each part through JavaScript. First of all we create a class called "publisher". This class play the "Subject" rule in the pre-demonstrated class diagram. Here the Subject will add subscribers in an Array data structure. So, let's see the code:
window.publisher = function () {}
window.publisher.prototype.subscribers = [];
First the publisher
class was created and the subscribers
field was added to the prototype ofpublisher
object. In the next step we will write the subscribing code where the observers can subscribe the publisher.
window.Function.prototype.subscribe = function (publisher) {
var self = this;
var _publisher = new window.publisher();
var alreadyExist = _publisher.subscribers.some(function (el) {
if (el == self)
return;
});
if (!alreadyExist) {
publisher.subscribers.push(self);
}
return this;
}
The subscribe
method gets a publisher and adds itself as the subscriber of the mentioned publisher. This part is a little tricky, then lets see how it works. First take a look at the below line :
Function.prototype.subscribe=function(publisher){
This code line adds the ability to all the functions in Window area to have an extra ability called subscribe
. So, how does it work? Native JavaScript objects store their methods in prototypes. Every JavaScript object has a prototype. The prototype is also an object. All JavaScript objects inherit their properties and methods from their prototype. Function
is also an object and has its own prototype. When we create an object like var object ={};
and it is just an empty object, so why it has for example the "toString()
" method? Becase actually we are abstracting the default behavior which is var object=new Object();
And the object, made by new Object naturally receives object.__proto__ == Object.prototype
, where Object.prototype
is a native object with Object.prototype.toString property.
The same story is credible for the other objects such as Function
, Array
and so on. When we add a new method or field to the Function object, since all the functions get inherited by the basic Function object prototype, therefore they get inherited the new methods as well. For example:
Interesting, isn't it? Yep!! Now we can do the same for all the objects as we did for Array or Function objects. We can modify the built-in functions as well (but this is out of the scope of this topic).
As you can see, I have used the some
function. some
is a boolean
function who tests whether some of the array members can pass the test implemented by callback function or not and returns True
or False
. In the above line you can see that the some
function has used to see whether the subscriber already exist or not. Obviously when it comes to conclusion that it doesn't exist, the subscriber will be added into the subscribers
array of publisher
class.
As observers can subscribe, they ought to have the ability to unsubscribe as well.
window.Function.prototype.unSubscribe = function (publisher) {
var _publisher = new window.publisher();
var alreadyExist = _publisher.subscribers.filter(function (el) {
var self = this;
if (el !== self)
return el;
});
return this;
The filter
method filters the array's members rely on the callback functionality. Then in this method thefilter
method returns all the members except the one who is the object itself.
The last function called deliver
that is responsible to deliver the events to the event listeners (Observers).
window.publisher.prototype.deliver = function (data) {
this.subscribers.forEach(function (fn) {
fn(data);
});
return this;
}
This function uses the forEach
method of Array object. The forEach()
method executes a provided function once per array element.
Now that Observer Pattern was implemented It can be used as the below simple example :
var NewYorkTimesDelivery = new Publisher;
var AustinHeraldDelivery = new Publisher;
var reader1 = function (from) {
console.log('Delivery from ' + from + ' to Joe');
};
var reader2 = function (from) {
console.log('Delivery from ' + from + ' to Lindsay');
};
reader1.
subscribe(NewYorkTimesDelivery).
subscribe(AustinHeraldDelivery);
reader2.
subscribe(AustinHeraldDelivery).
subscribe(NewYorkTimesDelivery);
NewYorkTimesDelivery.
deliver('Here is your paper! Direct from the Big apple');
AustinHeraldDelivery.
deliver('News');
As you may have realized I have used Method Chaining in this class. Chaining Methods also known as Cascading, refers to repeatedly calling one method after another on an object, in one continuous line of code. It allows us to read code like a sentence, flowing gracefully across the page. It also frees us from the monotonous, blocky structures we usually construct.
Now that you know some important basics, you are ready to take a travel to the land of MV* pattern. Then pack your baggage and be ready to go.
Representative Patterns
In this section we will go through the details of each MV* patterns. First of all I will talk about the history of each one, Then structure and finally the relationship between layers. After I will show how each one can be implemented by JavaScript. This arcticle discusses existing MV* patterns classified in three main families: Model-View-Controller (MVC), Model-View- View Model (MVVM), and Model-View-Presenter (MVP). It takes a practitioners’ point of view and emphasizes the essentials of each family as well as the differences. Before talking about MV* patterns lets see how the applications world looks like without patterns. To do so, I will talk about the Widget-Baded User Interface and then I will expatiate the MV* patterns.
Forms and Controls
Forms and Controls (also known as Widget-based User Interface) is the concept of Visual Programming as we had in Visual Basic and the other Visual Programming languages, where the programmer adds a bunch of controls to the form and then simply starts handling all the domain logics in the class related to the designed form. In this approach the form class is responsible for handling everything related to the domain area such as the business logic, user interface, event handling and handling data model. Widget-Based approach is too simple and it is totally adequate for small applications. If we are expected to create a simple application for a university task and we know it won't extend, why we need something more?!
This approach already have tested in the 90's by Delphy, VB and others and by the way It was successful too. Since there is no separation of concerns, this approach usually use Flow Synchronization. As already mentioned Forms and Controls are totally acceptable for small and simple applications however there are some disadvantages as follow that makes this method vulnerable while using through the complex applications
- There is no separation of concerns, accordingly it is very hard to reuse. Also the application coded on this way is not flexible
- The more new forms and features we have, the more maintainability will be decreased
- Probably after a while these systems turn into the software systems we call Legacy systems
However as mentioned this approach has some benefits as follow
Simplicity: widget-based user interfaces are very simple to understand: the widgets on the form become fields of a Form class, so the developer can access the widgets just as any other field.
Consistency: the approach employs flow synchronization. Synchronization is handled explicitly: target views/widgets are modified by direct calls, so the code is easy to understand.
Efficiency: creating a sophisticated multi-tier architecture for applications that do not require rich user interfaces would be overkill. Keeping the design simple in such cases reduces development time and increases maintainability.
MV* Patterns
Welcome to the land of MV* patterns. In this land you will learn about MVC, MVVM and MVP , their structure and their difference. Also you will learn about each one's pros and cons.
All the Patterns in this area have two shared parts: View and Model. However Model and View are shared between all but the responsibility and the scope of authority of each pattern varies. On the other hand each patterns has a third part e called it " * " that means this part is different for each pattern. The "*" can be either Model-View in MVVM, or Controller in MVC, or Presenter in MVP. The other issue that may vary based on each pattern is the type of Synchronization Approach we talked earlier.
The above figure shows three arrows labeled with question sign "?". Also as you can see, the third part is responsible for connecting View and Model. When we are talking about the way two components talking to each other, actually we are talking about the different Synchronization approaches. The rest of this article is dedicated to survey how the variation in the third part ("*") and also the relationship between each layer ("?") can affect the way we deal with each pattern.
SmalTalk'80 MVC : Model-View-Controller
MVC was invented at Xerox Parc in the 70's and first time its basics were published on a paper named "A Cookbook for Using the Model-View-Controller User Interface Paradigm in Smalltalk -80", by Glenn Krasner and Stephen Pope, published in the August/September 1988. SmallTalk 80's MVC even came earlier that "Forms and Controls" approach. Initially, MVC was used for designing and building desktop applications with rich graphical user interfaces. Over time, the original MVC pattern evolved and variants emerged driven by technological evolutions and new needs. Nowadays, MVC is used for integrating interface logic with domain logic in development of various domains, such as Web applications and mobile systems.
Structure
SmallTalk80's MVC has been composed of three parts. Model , View and Controller. In SmallTalk MVC, Model is responsible for domain data and logic. This part is very important and it makes a key difference with the other patterns where Model is just responsible for domain data. The View component is responsible for displaying model data. The third part in MVC called Controller who is in charge of connecting Model and View, also handling user inputs. Controller is responsible for handling user inputs. Another responsibility of controller is handling the events. Lets take a look at the below diagram :
Collaboration
As we said the collaboration between each layer in each of MV* patterns is different. In MVC Colntroller is such a dealer between View and Model for all the requests goes from View to Model. See the diagram. In this diagram you can see that both View and Controller are observing the Model. It means MVC uses Observer Synchronization. View and Controller work as a pair allowing the user to interact with the user interface. For example, the user interface may provide a text box allowing the user to enter a user name. The View is responsible for rendering the text box. The user can change the text and press keys (e.g., the Enter key) – such events are handled by the Controller. The Model maintains the domain data. Often, the application has one Model and a set of View-Controller pairs working with it.
But there is something confusing here. First time when I started implementing this pattern, It was completely confusing. I sent an email to some of the guys who had written some papers about MVC and asked them about the rule that Controller plays in this diagram. Unfortunately they were also confused and couldn't give me a clear answer. So, what was that confusing issue about? It is normal for View to observe the Model ( since it needs to get model data as soon as Model publishes) but why Controller observes the Model? Why we need it? As we said Controller is just responsible for handling the user inputs and events. To know this, lets talk about the Model in MVC.
Model in MVC, as already mentioned undertakes the Domain Data and Domain Logic parts. This behavior has considered as one of the disadvantages of MVC because it doesn't follow the separation of concerns. Imagine we have a textbox in View and View sends a request through Controller to Model getting some data related to the textbox. Lets suppose this textbox contains the age and we want to change the color of textbox's value to red if the age is more than 80. Who is responsible for this? The text color is purely a user interface property and therefore should not be part of the model. In SmallTalk80's MVC, Model is responsible to do this and it isn't right.
Smalltalk developers found ways to handle such cases, e.g., by developing custom Views that implement the required logic. However, these solutions did not solve the underlying problem. In one of the articles I read this sentence : "Smalltalk’80 MVC provides a good solution for displaying the model data itself; however, it provides no explicit means to deal with the presentation of state that is not part of the model but that makes a user interface more convenient for usage".
Let's return to our BIG question, "why Controller observes Model"? If Controller observes Model, then Controller will be notified of every changes of Model ( while View is being updated too). So, Controller can observe the Data which is getting prepared to View. Therefore Controller can take part in a part of domain's logic. So we won't have the previous problem anymore because Controller can check the age now. On the other hand View connects to Controller through the direct calls. Thus Controller can read the age each time, set one of its properties as View State (The state of TextBox color), so that View is able to get access to the Controller's property through a direct call and set its color based on the View State. As a consequence we can allocate a part of domain logic to Controller and free Model of doing the thing was not its responsibility. Now we can Strike the following sentence since it was not right :"it provides no explicit means to deal with the presentation of state that is not part of the model but that makes a user interface more convenient for usage".
Javascript in the Land of MVC Pattern
Now that you know the structure of MVC pattern, it is the dance time in MVC land. Our dance will be implementing a simple example by JavaScript where Model, Controller and View are separated based on their own responsibilities. This simple example is about a simple page that gets some information of some Books and represents them based on a specified View State (e.g. price, ...).
You already learned how we can Implement Observer Pattern with JavaScript. Well, we need it here since in MVC the synchronizations are found on the Observer Synchronization. This class will be used through some of the other MV* patterns where we will need Observer Synchronization.
window.publisher = function () {}
window.publisher.prototype.subscribers = [];
window.publisher.prototype.deliver = function (data) {
this.subscribers.forEach(function (fn) {
fn(data);
});
return this;
}
window.publisher.prototype.ready = function (fn) {
window.addEventListener('DOMContentLoaded', function () {
var params = Array.prototype.slice.call(arguments, 1);
fn.apply(this, params);
}, false);
}
window.Function.prototype.subscribe = function (publisher) {
var self = this;
var _publisher = new window.publisher();
var alreadyExist = _publisher.subscribers.some(function (el) {
if (el == self)
return;
});
if (!alreadyExist) {
publisher.subscribers.push(self);
}
return this;
}
window.Function.prototype.unSubscribe = function (publisher) {
var _publisher = new window.publisher();
var alreadyExist = _publisher.subscribers.filter(function (el) {
var self = this;
if (el !== self)
return el;
});
return this;
}
The next step comes ahead as it is shown in the below diagram :
As you can see Model get inherited from Observer Synchronizer class. The getData
method is the one will be called by Controller. This method can be very simple like the below sample, or it can use some Ajax calls to get some information from DataBase.
window.ModelPublisher = function () {
}
window.ModelPublisher.prototype = Object.create(window.publisher.prototype);
window.ModelPublisher.prototype.getData = function () {
this.deliver({ Name: "Javascript", Price: 200 });
}
Lets take a look at View. As I said View is responsible for just view elements such as html forms, controls , css styles and son on. View creates a List of books based on the view state and will add a color to the respective text.
Also View observes Model to get notified when any event raised by Model.
And here is where View observes the Model :
var _publisher = new window.ModelPublisher();
view.bookVendorObserver.subscribe(_publisher);
So, this was a very simple implementation of MVC pattern with JavaScript. The code part is more but I just talked about the key parts since showing more codes makes this article a code junk. Anyway if you want you can see the whole code and see what exactly happens.
Microsoft MVVM
In 2005 John Gossman unveiled Model-View-View Model pattern in his blog. He is one of Microsoft's WPF and Silverlight architectures and by the way MVVM has used on Silverlight and WPF and it was totally successful. MVVM is identical to Fowler's Presentation Model, in that both patterns feature an abstraction of a View, which contains a View's state and behavior. Fowler introduced Presentation Model as a means of creating a UI platform-independent abstraction of a View, whereas Gossman introduced MVVM as a standardized way to leverage core features of WPF to simplify the creation of user interfaces.
As you read before, I encountered a big confusion in MVC about the controller and it's scope of authority. When I wanted talking about MVVM in this article, i thought it was better read more resources and suddenly I saw this : "In Martin Fowler’s “GUI Architectures” document (bit.ly/11OH7Y), he states the following about MVC: “Different people reading about MVC in different places take different ideas from it and describe these as ‘MVC.’ If this doesn’t cause enough confusion, you then get the effect of misunderstandings of MVC that develop through a system of Chinese whispers.” The “Whatsa Controller Anyway” document at bit.ly/7ajVeS sums up his point nicely stating: “Computer scientists in general have an annoying tendency to overload terms. That is to say, they tend to assign more than one meaning (sometimes contradictory) to the same word.”"
In Smalltalk MVC, “every” View will have a Controller and only one Controller at any given time can be active! This can be sometimes considered as a big lack. Imagine you want to have several View for each Controller. MVC itself doesn't prepare this ability and for implementing this, probably we need using some programming techniques and tricks.
These lacks and confusions caused emerging new architectures such as MVVM. The next sections will talk about the MVVM in detail.
Structure
In the first glimpse the most important thing has changed in MVVM is the way View and Model communicate together. The second one is the third part called "ModelView".
The pattern has a linear structure. The View is responsible for rendering the user interface; it can observe the View Model, trigger its methods an modify its properties when needed. View maintains a one-way reference to the View Model. When a View Model property is changed, View is notified by observer synchronization. On the other hand, when a user interacts with the View, View Model properties are directly modified. View-Model is responsible for handling view state and user interaction; it has access to the domain Model, so it could work with domain data and invoke business logic. View-Model is unaware of View. Model is responsible for handling domain data and is unaware of View Model. This approach allows creation of several different views for the same data, and observer synchronization makes these views work simultaneously.
Collaboration
In this pattern each "View-Model" can have several Views. Guess why? Yes, since several Views observe an individual View Model. "View-Model" has direct access to Model. It calls Model's methods and returns results through events! When an event raised all the Views get notified and update themselves. As you can see, "View- Model" is like a wrapper and prevents direct communication between View and Model. "View-Model" is responsible for the domain logic. As it was mentioned, View also can have a direct calls to "View-Model" in order to requesting data from Model through "View-Model". As before "View-Model" is responsible for handling the View's events as well. For example when a button clicked, the respective event handlers in View-Model is called and some commands are executed in "View-Model".
Microsoft uses Data Binding for all the talks between View and "View-Model" however for implementing via JavaScript we need to use our own way.
Javascript in the Land of MVVM Pattern
Here I am going to talk about implementing MVVM with JavaScript in our previous example. Implementing MVVM showed me that using MVVM is completely reasonable since I didn't have any doubt about each layers and their tasks. Here some things have changed. Model don't publish events anymore , instead View Model undertakes this task. Therefore, model is very simple and it is just responsible for Domain data as below:
Window.Model = function () {
var dataFile = {
Books: [
{
"Name": "Javascript",
"Author": "J.Reisig",
"Publisher": "Wrox",
"Pages": 534,
"Price": 200
},
{
"Name": "Head First Java",
"Author": "Kathy Sierra",
"Publisher": "Head First",
"Pages": 426,
"Price": 100
},
],
};
this.retriveBookList = function () {
return dataFile;
}
}
View Model has direct access to Model and Model has no idea about View Model and View. Then View Model calls one of the methods of Model who retrieves data and the rest of things will be done by View Model.
On the other hand View Model is a publisher. It gets data, checks them and set View State based on the domain logic and sends the result to View through an Observer Synchronization.
View on the other hand is responsible for interface elements. It observes the View Model ang get notified as soon as View Model publishes books list. This is where we see one of the power points on MVVM. Now several Views can observe View Model and generate interface elements considering their own style. For example imagine we want to show the recieved data in several charts such as linear chart , Area chart and Bar chart. Now each view can geberate its own chart based on the same data.
As you see MVVM is such a very powerful pattern for handling separation of concerns however it seems one of its weak points is over using the observer synchronization that may cost performance .In the next section we will see another pattern which won't have performance issues.
Dolphine Smalltalk MVP
Welcome to the last part of this article. "The Model-View-Presenter software pattern originated in the early 1990s at Taligent, a joint venture of Apple, HP, and IBM, and was the underlying programming model for application development in Taligent's C++-based CommonPoint environment"(Wikipedia). After Taligent's demise in 1997Dolphin Smalltalk adapted the MVP pattern to form the basis for their Smalltalk user interface framework.
Structure
MVP has composed of three parts. View, just like MVC is responsible for showing the Model's data. In one of the papers it's said that View in MVP is almost unchanged however based on Dolphine Smalltalk paper unlike MVC, here, View is responsible for handling some events such as onclick
: "One significant difference in MVP is the removal of the controller. Instead, the view is expected to handle the raw user interface events generated by the operating system (in Windows these come in as WM_xxxx messages) and this way of working fits more naturally into the style of most modern operating systems." Consequently first time I did a mistake and coded the event handling part on Presenter while based on the aforementioned paper View is responsible for event handling.
Here the Presenter guarantees to affirm the domain logic. Moreover Presenter is in charge of how View can manipulate the Model data or send a request to Model. Here is where we can see the heart of MVP that makes a significant difference with the other MV* patterns. I will talk about this in the next section.
Here the Model plays the Publisher rule for some viewers who play the observer rule. Furthermore Model is unaware of Presenter and View. In MVP, the Model is a purely domain object and unlike Model in MVC, it cannot manipulate the View.
Collaboration
View observes the Model and Model notifies View. There is a two-way connection between View and Presenter. This is where that heart of MVP appears where Presenter has direct access to View. It means View get data from Model and Presenter impose the domain logic spontaneously. View triggers the Presenter to perform domain logic. The Presenter performs the domain logic and commands the View to update its View State. The great flexibility of the Dolphin Smalltalk MVP pattern comes from the decision that the Presenter can directly access the View. This can be considered as one of the power points of presenter, but this kind of empowering the Presenter can easily lead complexity.
Javascript in the Land of MVP Pattern
In this section the Model has the same code as I wrote in MVC. Then let's focus on Presenter and View where the key differences come from.
View in MVP is almost same as the View in MVC with this key difference that View in MVP is also responsible for handling the Controller events such as onclick
.
And here View trigger the presenter to perform domain logic.
As a result Presenter will perform the doman logic and with a direct access calls the setCss()
method of View. Additionally Presenter can call Model's respective methods based on the issued request from View.
As I said I avoided putting the whole code here, then take a look at the code attached in this article to know the code in detail.
However I prsented the Dolphine Smalltalk MVP, but talking about the MVP (Passive View) is totally necessary since nowadays when we are talking about MVP we mostly mean Passive View Pattern. In the next updates I will expatiate it.
Conclusion
Writing the current article was such a journey for me because there are few articles which talk about implementing MV* patterns with JavaScript describing architectural details. Hence I had to read several papers. During this learning curve I sent some emails to the writers clearing my doubts. The interesting point is that sometimes even the paper authors are not free of doubt when it comes to MV* patterns. So I am not totally free of doubts as well. I tried to gather all the papers, conferences and discussions about each pattern and publishing my own experiences through this article.
Since JavaScript is going to be taken as a serious client side solution in the modern web development era, I guess in the near future lots of developers will believe in separation of concerns in client side programming. This is why I decided to write this fundamental article hoping it can be useful for developers in the future. The name "Belly Dance" comes from this reality that it has always been used during the history for pregnant women making them ready giving birth. So, now it is your turn to guess why I chose this name for this article. At the end I can call this article as a letter for the future when Separating Concerns in Client Side will be taken much more serious than today! Thanks all for reading this article. I am looking forward to your questions, doubts and your suggestions improving the probable mistakes.
References
http://www.object-arts.com/downloads/papers/TwistingTheTriad.PDF
http://www.computer.org/csdl/proceedings/wicsa/2014/3412/00/3412a021.pdf[^]
https://www.lri.fr/~mbl/ENS/FONDIHM/2013/papers/Krasner-JOOP88.pdf[^]
http://blog.osteele.com/posts/2004/08/web-mvc/[^]
http://micsymposium.org/mics_2009_proceedings/mics2009_submission_55.pdf[^]
http://msdn.microsoft.com/en-us/magazine/hh580734.aspx[^]
http://www.amazon.com/Pro-JavaScript-Design-Patterns-Object-Oriented/dp/159059908X[^]
http://c2.com/cgi/wiki?WhatsaControllerAnyway
History