These days it’s kind of official: AngularJS implements the Model-View-Whatever paradigm. That’s a nice solution to a series of fruitless discussions about whether AngularJS implements MVVM, MVC or something else.
However, one of these days I stumbled upon a couple of slides claiming AngularJS implements the MVC pattern during my research for another article. I knew from various tutorials that this isn’t exactly true. My curiosity was piqued. What exactly is the difference between MVC, MVVM and MVP? Are there other useful design patterns? And while we’re at it: do JSF and AngularJS implement one of these design patterns?
Actually, I already knew there are different design patterns you can use successfully. When I implemented my former company’s framework, I got the idea of MVC wrong. So I implemented something slightly different. That earned me a lot of trouble with external consultants. You know, every once in a while we invited a consultant to look over our architecture. Inevitably, they would complain about our non-standard implementation. But our implementation worked, and it worked well, so what?
That’s an important thing to keep in mind: don’t waste your time on this nonsense. It’s like talking about politics: it’s a lot of fun to discuss about the advantages of MVP over MVC and whether your program following on paradigm or the other. But at the end of the days, it’ll change little. It’s more important to chose a clean, sustainable architecture and stick to it. If you need a name, call it Model-View-Whatever. Whatever works for you.
But today I’m not going to listen to the voice of reason. Today I want to have fun. Let’s dissect the design patterns, and let’s see how JSF and Angular fit into the pattern.
At a glance
Look at these pictures. They cover three of the most popular patterns: MVP, MVC and MVVM. Don’t soak yourself in the details – that’s what the rest of the article is about. Just look at the general picture. Do you notice anything?
The intensity of the flame wars hides the fact that these design patterns are very similar. They seek similar goals. Each of these design patterns is about modularization. They are about separating the view layer of your application from the database layer. The discussion is about how to do it.
Most design models consists of a view layer, a model layer and something in between. In most cases, the model can be thought of as your database access layer. It may consist of WebServices, REST services, Hibernate code or JDBC code.
My diagrams allow the model to fire events to other parts of the application. That’s something I’ve never seen in the wild. My models usually provide a passive API to read and write data. Sometimes there’s also an API calling a back-end service containing business logic. The idea of a backend firing events is something I found during my research for this article. It’s a nice idea, so why not? I suspect the original author simply wanted to express that the model transfers data to the presenter when the presenter calls the “load()” method. But asynchronous calls are becoming more and more popular, so this seems like a useful addition to me.
Apart from firing events, the model has no connection to the other layers of the application. In particular, it can be compiled separately.
The view contains the code to display the information on the screen. In the case of AngularJS it’s a collection of HTML pages. In the case of JSF it’s a collection of XHTML pages, and when you’re using Swing, it’s the code creating the
JFrame (or whatever base class you use). JavaFX programmers have to options: either they use the FXML files to define the view, or they use the Java API. The bottom line is that according to the MVP paradigm, the view must not contain business logic.
Actually, frameworks like Swing, SWT and JavaFX (unless you use the FXML to define your page) make it easy to mingle view code and business code. That’s because you need to register a callback function to objects like buttons and menus. When the button is click, the code of the callback function is executed. The only place to define and register the callback functions is the view layer, so it’s tempting to implement business code in the view layer.
The MVP design pattern forbids that. By using MVP, the team agrees to move the business code to the presenter layer. Every callback methods of the view calls a method of the presenter layer, passing the user input as parameters. After processing the business functionality, the presenter calls a method of the view to display the new dialog. Again, the values to display are passed as parameters.
The image is a bit incomplete. The view and the presenter should compile as independently as possible. This can be achieve by adding a collection of interfaces shared by both layers. The implementation use only the interfaces to communicated with each other. This way both implementations can be compiled independently, using dependency injection to get the link to the other layer. A further constraint is that view objects are never passed to the presentation layer. However, views and presenters are closely related to each other, so there’s a one-to-one relationship between them.
Note that these are rules to make sure that there’s no business code in the view layer. If you find a different model to reach the same goal, that’s fine, too.
The key point of MVVM is that there’s a two-way binding between the view and the viewmodel. For instance, AngularJS uses HTML pages as view layer. The viewmodel is the scope (in AngularJS 1.x) and the controller object (in AngularJS 2). The viewmodel contains variables that reflect the changes of the GUI, and vice versa. In other words: when the user types some input in a field, a variable of the viewmodel is changed.
The idea is to build a object hierarchy containing the values of the view, but apart from this, it doesn’t need to contain view-specific code. The objects in the viewmodel don’t have to reflect the structure of the view. Quite the contrary, the viewmodel contains the business logic, so it reflects the business model. One viewmodel may serve several views.
In the MVVM model there’s no dedicated controller layer, so I assume the MVVM also plays the role of the controller. It’s responsible for implementing what happens when a button is clicked, and to choose the new view to show.
The Model-View-Controller paradigm is a predecessor of the MVVM paradigm. The main difference is the MVC doesn’t necessarily require a two-way-binding between the view and the controller. Instead, the view sends user commands and user inputs to the controller, which may update the model with the user input. After processing the business logic, the controller choses the next dialog to present. The view layer reads the data to display directly from the model.
Another explanation from Reddit’s sh0rug0ru__
Update Oct 19, 2015 Reddit user “sh0rug0ru__” gave me a slightly different explanation. I asked sh0rug0ru__ whether I’m allowed to quote him, so I’ll copy his explanation as is:
MVP and MVVM are highly specialized instances of MVC, which by itself is pretty generic. MVC is a generic division of implementation responsibility between a data model (M), the visual representation of the data model (V) and the glue that binds them together (C).
The MVC ideal is that the data model can focus on pure business rules, the view can focus entirely on presenting the data in a specific context, and the controller can focus entirely on selecting the appropriate view and coordination between the data model and the view.
MVC is great for keeping responsibilities focused. However, what if the view itself has significant state and behavior? How do you manage that or test it? Ordinary MVC doesn’t have an answer for that, except maybe more functional testing, because that view logic is locked away in UI code that can only really be tested using tools like Selenium or WindowLicker, which run tests in the UI directly.
MVP and MVVM are specific adaptations to MVC to address this concern.
MVP moves the view state and logic into the Controller in abstract form, presenting a model of the UI through an interface. The different representations of the UI provide trivial implementation stubs of the interface. The view logic can thus be tested without the need of the actual UI. Thus, the View takes on a passive role and the Controller takes on a more direct supervisory role over the View (Presenter is synonymous with Supervising Controller).
MVVM specifies a separate ViewModel class to encapsulate view state and logic. But the ViewModel is usually implemented according to the rules of an underlying data binding framework. Thus, instead of directly telling a view component to disable itself as in MVP, you instead bind the disabled property of the UI component to a property in the view model, and it is the data binding library’s responsibility to propagate changes between the ViewModel and the UI. Thus, the role of Controller is subsumed by the ViewModel and data binding library.
Thus MVP and MVVM are special cases of MVC the goal of which is to specify a relationship between V and C that makes it possible to specify the view state and logic in abstract terms to facilitate testing without the need to directly execute tests in the UI toolkit.
I would also add that the advantage that the specialization that MVP and MVVM confer in testing comes at the price of losing generality in the Controller. One of the central promises of MVC is pluggability of views and the more detailed knowledge that the Controller has about the View, the less flexible you can be with different types of views. For example, if you have a requirement to support HTML (interactive) and Excel (reporting) view types. There’s very little in common between these types of views, so you would be very hard pressed to come up with a common supervisory strategy (MVP) or a common ViewModel (MVVM). So you can either have multiple view specific Controllers or one generic Controller. Or, you might have MVC on the server (which allows more flexibility with clients) and MVVM/MVP on the client (where more flexibility doesn’t offer a clear advantage).
Thanks, sh0rug0ru__, for the great feedback!
Now, back to my own text.
What about JSF and AngularJS?
Most people believe that JSF is an MVC framework, while AngularJS is an MVVM framework. Looking at the diagrams, I’d say both frameworks implement the same design pattern. Both frameworks employ two-way-binding. In both cases, the view layer reads the data to display from the same layer it later writes the input to. In the case of AngularJS 2 and JSF, user actions call methods in the same layer that also stores the view data. In AngularJS 2 that’s the controller class, in JSF it’s the JSF bean.
So I’d say that JSF and AngularJS 2 implement the same design paradigm. Probably that’s MVVM.
In the case of AngularJS 1.x, there’s a separation between the scope (where the view data is stored) and the controllers (where the business logic is implemented). However, both objects are closely related, so in practice, I don’t often think of them as separated objects.
By the way, once you start inspecting JSF closer the picture becomes a lot more complicated. Just think of the temporary viewmodel containing invalid data. JSF stores user input in the controller only after successfully passing the plausibilities. If there’s a constraint violated, the invalid data is still displayed. Obviously, there’s more than one data store in the JSF implementation.
On the other hand, JSF gives you a lot of freedom to organize your application. A view is allowed to aggregate data from more than one JSF beans. You can separate the JSF beans containing data from the JSF beans containing business logic. Dependency injection enables you to keep these beans separated – up to the point that they compile independently of each other – and still make them work together. The resulting model resembles my original but wrong understanding of MVC.
Initially, I said I’d got MVC wrong when I’d implemented it for the first time. At the time, my idea was that the model is a temporary container for business objects. A couple of years later a consultant told me that my model was a “view-helper”. In the language of MVVM, I guess that’s precisely the viewmodel. Later I added attributes to control the visibility of input fields, to display error messages related to individual fields and annotations describing the maximal length of the input field. All this pushed my model closer to the view. Nonetheless, both the view and the viewmodel were agnostic of each other, at least at compile time. At runtime, the view was responsible for establishing a two-way data binding between view and viewmodel.
The connection to the database was negotiated by a separate persistence layer. The rationale behind that was that I was used to keeping every object I needed to work in the main memory. At the time, my applications worked much the way your favorite spreadsheet program or text processor do: load everything into memory. After that, work with the main memory until the user decides to save everything back to disk. Many – or most – web applications work differently: the keep only the data required by the current view in the main memory. After processing, it’s immediately stored back in the database. Some applications even work statelessly, loading everything from the database each time a view is displayed.
My paradigm also separated the controller from the viewmodel. This made for a cleaner separation of concerns, and it allows to put Hibernate entities into the viewmodel. So you can keep the persistence layer very small. Basically, it consists of the Hibernate XML file and some glue code to save and load the entities. In modern Hibernate versions, you’d rather use annotations instead of the XML code. The annotations, in turn, are part of the entities, which we put into the model. Hence the separation of the viewmodel and the persistence layer begins to blur again.
My teams used (and still uses) this paradigm very successfully. Like I said before: there’s no silver bullet. Every design pattern has advantages and disadvantages. You have to look yourself which paradigm suits you best. I always felt a bit puzzled about SUN’s aggressive propagation of the MVC pattern as the one and only solution.
The big picture
Just for the sake of completeness: I’ve never seen an MVC discussion covering important aspects such as print or PDF and Excel export. In my eyes, these are simply specialized views, so they should be covered by the design paradigm, too. I’ve tried to include everything into a single picture. For the sake of simplicity, I omit a couple of arrows. It goes without saying that both print and PDF/Excel/Whatever export need to access the viewmodel to read data.
Wrapping it up
Don’t get stuck on semantics. I was curious what the difference between the MVC, MVP and MVVM model it. But most likely your goal is not to write an MVC application. Your goal is to write an application that works. More often than not, you’ll introduce subtle (or maybe even not so subtle) differences to the “official” paradigm. As long as you see to it that there’s a clean separation of concerns, and as long as the design works for you, everything’s fine. I’d even say it’s not important to separate the application into the view, the controller and the persistence layer. Most likely there are different approaches that are just as good. If asked, call it MCW – Model, View, Whatever :).
Very good explanation of the MVVM pattern by Manuel Mauky, the author of mvvmFX (in German language)
What is the difference between MVC and MVVM
Understanding MVC, MVP and MVVM (in a Microsoft environment)
Martin Fowler on UI architectures
Igor Minar on MV*
Reddit discussion on this article
Another Reddit discussion on this article