The War Is Over
How did this war wage on and how did MVC win? Against what or whom?
No Lack of Options
There are many options available in this space—too many for your humble author to enumerate. Frameworks like Backbone.js have really caught wind with the community, Ember.js has a very full-featured stack and Knockout is straightforward and based more on MVVM than MVC. Google, of course, has an entry with Angular and that will surely take over the world at some point in time—but not quite yet.
I’m just going to discuss Knockout and use it exclusively in my code samples. Why? Besides my personal experiences with the framework, KO is expressive and straightforward as far as binding syntax, UI refreshes, dependency tracking, and templating.
Haven’t we spent enough time in this industry to at least know having an object model is better than a loose association of variables spread across a number of files that somehow, in someone’s mind, resembles a ball of mud? I mean—that’s a lesson that we’ve learned as well, right?
This model is similar, if not identical, to what we have on the server-side—that’s important because the data is only persisted after it passes through the domain logic and validation back at the server. However, the server can be the page or a service end point. More on that later as well, but as a spoiler alert, it’s no different than any other contemporary Ajax design.
By the way, Knockout is not pure MVC. Don’t worry. It’s MVVM: Model, View, View-Model, where the View-Model is like a special controller that also has all the logic needed to work with the view, convert data back and forth, and protect the other two tiers from each other. It’s an idiom that takes just a little getting used to, but it’s quite powerful for UI development.
Knockout allows you to dynamically generate your client models. Why would you want to do this? Simple—maintain the model code once, and use everywhere.
Pretend you have this class server-side.
In Knockout, it’s the ko.mapping plugin.
With this, you can write some code like:
Next, you can load that data up into a view model object using ko.mapping.
At this point, all the public fields in Portfolio (since the private normally wouldn’t be serialized down) are accessible via viewModel, e.g. viewModel.name(). The mapping plugin also handled making the object a KO object, meaning that all of these fields of the object are observables. More on observables later.
Horizontal Scaling via Browsers
In this figure you see that when we are capable of doing more in the browser, we do so. That means more processing, that is the right processing, can be done in the browser. For instance, reordering and filtering a set of data doesn’t require a server session, a post-back, and a retrieval of JSON, XML or (goodness) HTML. If the data set is present, do the work in the browser. And just as jQuery enables us to write quick and simple DOM manipulations, a framework like Knockout has our data in the model and it’s just a matter of resorting. In fact, the UI can respond to the resorted dataset via observables, which we will cover later.
Once more work is done in the browser, the server-side architecture can begin to change as well. Maybe the solution doesn’t require beefy web boxes anymore to deal with constant dynamic data queries, page renders or POSTs. Instead, a thinner Ajax services layer can be rolled out as in the following figure. Here, we can scale our Services tier as our user base increases. The Services tier can deal with the caching of data from other sources, hiding it from the browsers and the web app. It delivers some specialization, which means that different parts of the system can grow organically and respond without a server whose main purpose is serving HTML getting involved.
Horizontal Scaling via Services Layer for Ajax
Shared Skill Sets
Classic Web Development Model
In this figure you can see how both these sets of skills are required in creating an application, but are disconnected. The disconnection promotes inefficiency all around, as the two often work against each other, and leads to hand-offs during development.
At the end, developers will become full stack developers—able to work from the back to the customer at the browser at the front.
Clean Code, REST and Layers
These three topics are tied together in a lot of discussion and literature, so I won’t be the one to break them apart. REST is, for whatever reasons, seen as clean. Maybe because it promotes layers, or because everyone has an affinity for the HTTP spec and its simplicity. Here is how they break down.
REST—many of frameworks, including Backbone, promote idioms following RESTfull practices to get and put data objects. Knockout doesn’t promote any particular way, but it also doesn’t stop you from following a basic RESTfull approach to talk to the server and manipulate domain-model objects.
Layers—by providing the capability to write Clean Code, following REST patterns, layers will emerge—and when done right, this is considered a good thing. Better the layer you know than the layer you don’t know.
A Word on Templates
The concept of a server-side template can’t help but be contentious. Why? Because it’s rendering a view on the wrong tier of the application. The browser is responsible for the view. But in the traditional web site sense all it receives is an HTML document. That would be fine if the web were still just about traversing resource links to new documents all day, but it’s not.
For example, if your server-side template is rendering a view, let’s say it’s working on the table that is in the middle of a page, and it needs to use another value that was rendered somewhere else in the page to do a row calculation. Ignoring that there are other solutions to avoid such a mess, what is the answer? Trick question: no matter the answer, it’s all server-side so devoid of browser context and requiring a page refresh. Plus, is a server-side page template rendering being done in the View or the Controller? It’s not the view, as the view is certainly not on the server. But, it can’t be the controller, as the controller doesn’t work directly on the view. This model just doesn’t work for every use case the way it used to.
In the last part of this article we’ll dive into some of the core concepts of the framework and explain what makes these important to building powerful apps and growing a team of full-stack developers.
where trxns are all the transactions in a portfolio, an array in the Portfolio object. The value binding is the most basic. There are bindings for all sorts of situations, like text, html, css, if, checked, hasfocus—and what is not there can be developed without too much effort. This too can be found in the Knockout documentation.
Now, when the name field is updated, Knockout knows and can respond by triggering the bound items to update. You can also manually subscribe to change events to be notified of a change.
With a client-side template you’ll find a new canvas of possibilities. Since you are in your view to do view rendering, you can keep iterative looping structures and their associated template close by. As well, the basics of client-side templating mean that the server side can be more concerned about getting the correct data, in the correct format, and not the semantic nature of the data returned. In this way, the FED’s on the team can handle binding large amounts of data into the appropriate UI structures. It can be changed, swapped, iterated on—all independent of any server-side compiles or deployments.
Here we have the trxns collection, from our view-model. The first line says: “bind this data set to the named template and put the content here in my div.” There are many different ways to work with templates and a myriad of applications for them—this is the most basic. Templates work in conjunction with observables and declarative bindings—it is the transportation and implementation engine for those concepts in most cases. The client-side templates also put the CSS and the actual markup closer together, as these are components that should ride side by side and exhibit some cohesion.
For example, if you want to validate that your bindings are working when an observable is updated, you could type something like this right into the console in firebug and watch the UI for the update. The below would turn any field, bound to MarketValue to 555 in the UI.
Stephen Rylander is a technical lead with Morningstar focusing on web platforms on a global scale. He focuses on technical design, high quality code, teams and automation. Stephen has worked on four different public web platforms handling millions of daily page views, from finance to ecommerce to music and entertainment. He is adept at working with globaly distributed teams and has accepted that enjoying software development more than most people is just somethign he'll have to live with. He is also married, loves to cook and has two beautiful children.