MVC

& patterns

How it begins

Old days

<input type="text" name="date" onchange="validateDate(this);" />

if you have 20+ forms you need to add 20+ onchange functions

JavaScript behavior created and referenced in the HTML can be harder to use and maintain

if you have several handlers

<input type="text" name="date" 
onchange="validateDate(this); dance(something); playMusic();" />
<a href="#faq1" 
onclick="$('#faq1').css('display') == 'none' ? $('#faq1').show() : $('#faq1').hide();">
FAQ Question 1</a>
<div id="faq1" class="faqAnswer">FAQ Answer 1</div>

<a href="#faq2"
onclick="$('#faq2').css('display') == 'none' ? $('#faq2').show() : $('#faq2').hide();">
FAQ Question 2</a>
<div id="faq2">FAQ Answer 2</div>

<a href="#faq3"
onclick="$('#faq3').css('display') == 'none' ? $('#faq3').show() : $('#faq3').hide();">
FAQ Question 3</a>
<div id="faq3">FAQ Answer 3</div>

Obtrusive (or in-line) JavaScript:

Unobtrusive JavaScript

  • Separation of functionality (the "behavior layer", JS) from a Web page's structure/content (HTML) and presentation(CSS)
     
  • try to avoid the problems of traditional JavaScript programming
     
  • Progressive enhancement
<a class=”hide”>Click to hide me</a>
$('.hide').click(function() { $(this).hide(); } 

jQuery way:

Profit !

Right? Not exactly

So...

Clean, semantic HTML​!

Total separation!

you can’t change a line of markup without checking every single line of JavaScript to assure you’re not breaking a selector

Strictly separating HTML and JS actually led to applications that were harder to maintain and debug

MVC

 

 is a software architectural pattern

Trygve Reenskaug introduced MVC into Smalltalk-76 while visiting the Xerox Palo Alto Research Center (PARC) in the 1970s

A bit of history

 

Apple's WebObjects ("borrowed" from Smalltalk) in Objective-C

WebObjects was ported to Java

Ruby on Rails, Django, ASP.NET MVC

(Client) AngularJS, EmberJS, JavaScriptMVC, Backbone

Principes

MVC offers architectural benefits over standard JavaScript — it helps you write better organized, and therefore more maintainable code.

Parts:

  • Model is where the application’s data objects are stored. The model doesn’t know anything about views and controllers.
     
  • View is what's presented to the users and how users interact with the app. The view is made with HTML, CSS, JavaScript and often template

     
  • Controller is the decision maker and the glue between the model and view.
    The controller updates the view when the model changes. It also adds event listeners to the view and updates the model when the user manipulates the view.
var M = {}, 
    V = {},
    C = {};

M.data = "hello world";

V.render = function (M) { 
    alert(M.data); 
}

C.handleOnload = function () { 
    V.render(M); 
}

window.onload = C.handleOnLoad;

Tiny MCV application

  • View knows nothing about the Model apart from it implements some interface
     
  • Model knows nothing of the View and the Controller
     
  • Controller knows about both the Model and the View and tells the View to go do something with the data from the Model.

old MVC != new MVC

  • Model–View–Presenter
  • Model–View–ViewModel
  • Model–View–Adapter 
  • ...

traditional MVC pattern vs the modern interpretation in various programming languages:

some MVC–based frameworks will have the view observe the changes in the models while others will let the controller handle the view update

  • Reusable and extendable code
  • Separation of view logic from business logic
  • Allow simultaneous work between developers who are responsible for different components (such as UI layer and core logic)
  • Easier to maintain

MVC pattern brings modularity to application developers and it enables:

The Observer Pattern

This pattern implements a single object that maintains a reference to a collection of objects (known as "observers") and broadcasts notifications when a change to state occurs.

How it works?

 Observers register with the Subject  and wait for notification

Subject notify Observers about a change in state.

Observers take action

from http://www.slideshare.net/saifuddinmerchant/observer-pattern-15133603

var Subject = function() {
    this.observers = [];

    return {
        subscribeObserver: function(observer) {
            this.observers.push(observer);
        },
        unsubscribeObserver: function(observer) {
            var index = this.observers.indexOf(observer);
            if(index > -1) {
                this.observers.splice(index, 1);
            }
        },
        notifyObserver: function(observer) {
            var index = this.observers.indexOf(observer);
            if(index > -1) {
                this.observers[index].notify(index);
            }
        },
        notifyAllObservers: function() {
            for(var i = 0; i < this.observers.length; i++){
                this.observers[i].notify(i);
            };
        }
    };
};

var Observer = function() {
    return {
        notify: function(index) {
            console.log("Observer " + index + " is notified!");
        }
    }
}

var subject = new Subject();

var observer1 = new Observer();
var observer2 = new Observer();
var observer3 = new Observer();
var observer4 = new Observer();

subject.subscribeObserver(observer1);
subject.subscribeObserver(observer2);
subject.subscribeObserver(observer3);
subject.subscribeObserver(observer4);

subject.notifyObserver(observer2); // Observer 2 is notified!

subject.notifyAllObservers();

Publish–subscribe Pattern

is a variation of Observer pattern.

However PubSub uses a topic/event channel that sits between the objects wishing to receive notifications (subscribers) and the object firing the event (the publisher)

Differences

 

• there is no direct communication between objects

• objects exchange Events rather than share states of object

 

 

PubSub basic example

// create a function to subscribe to topics
var mySubscriber = function( msg, data ){
    console.log( msg, data );
};

// add the function to the list of subscribers for a particular topic
// we're keeping the returned token, in order to be able to unsubscribe
// from the topic later on
var token = PubSub.subscribe( 'MY TOPIC', mySubscriber );

// publish a topic asyncronously
PubSub.publish( 'MY TOPIC', 'hello world!' );

// publish a topic syncronously, which is faster in some environments,
// but will get confusing when one topic triggers new topics in the
// same execution chain
// USE WITH CAUTION, HERE BE DRAGONS!!!
PubSub.publishSync( 'MY TOPIC', 'hello world!' );

Cancel specific subscription

 

// create a function to receive the topic
var mySubscriber = function( msg, data ){
    console.log( msg, data );
};

// add the function to the list of subscribers to a particular topic
// we're keeping the returned token, in order to be able to unsubscribe
// from the topic later on
var token = PubSub.subscribe( 'MY TOPIC', mySubscriber );

// unsubscribe this subscriber from this topic
PubSub.unsubscribe( token );

Cancel all subscriptions for a function 

// create a function to receive the topic
var mySubscriber = function( msg, data ){
    console.log( msg, data );
};

// unsubscribe mySubscriber from ALL topics
PubSub.unsubscribe( mySubscriber );

Cancel all subscriptions

PubSub.clearAllSubscriptions();
// all subscriptions are removed

Resources

MVC. Patterns

By Nicholas Sorokin

MVC. Patterns

  • 626