Oct 29, 2014

Maybe the desire to control is the problem

I love to play tennis. Serve was the biggest weakness in my game. So I practice a lot, and now I am getting better and better in my serve. One of the most important techniques in serving is pronation which I struggled most with until I saw this video, The Serve Pronation Technique And 7 Drills To Learn It. Here is what strike me most in the article.

Control and letting go are, of course, at the opposite ends of the spectrum; the more you want to control, the less you will let go. While it makes logical sense to try to hit the court when you work on your serve, this desire is the BIGGEST OBSTACLE to improving your serve. You absolutely need to practice your serve technique and NOT aim in the court. Think speed, not hard. Let go, don’t control.

So why am I mention this? As a human being, we all hate to be controlled. Ironically, we all tend to love to control. This is why the world has so many conflicts. As a developer especially a front end developer, the desire to control is counter-productive. In the following, I will use a very simple example to illustrate why the controll mindset is so bad. This example was originally used by knockout.js. In the application, a user can click on a button, and two labels and another button can show or hide. It is simple but tricky enough for me illustrate my point. The following implementation in jsbin just uses vanilla jQuery. The following code is very bad, so I just want to show you part of it, I hope you can follow through.

 btnAdd.click(function () {  
    countClick++;     
    lblCount.text(countClick);
    
    if (countClick >= 3) {
      divWarning.show();
      btnAdd.attr("disabled", true);
    } else {
       divWarning.hide();
       btnAdd.attr("disabled", false);
    }
    
    lblPlural[countClick > 1 ? "show" : "hide"]();
    
  });

When I wrote this pieces of code, I was thinking from the perspective of CPU, and my desire to control is very strong. Why this code is bad? This is because a single handler has too many things to keep track. Even in this very simple application, the code is very smelly. Once the application grows bigger, the complexity of the handler will explode. One way to mitigate the problem is to use the "divide and conquer" strategy, where an upper controller delegates the control to a lower controller, until complexity is small enough to control, sometimes this works like MVC. But lots of times, this complexity is still hard to manage. Very often, Model, View, Controller still creates conflict, controller is still a bottleneck of communications.

hm.js

About three years ago, I was thinking whether it's possible to get rid of controller completely, so I developed a JavaScript library hm.js, I call it Model-View-Subscription library. The following is an implementation in jsbin using hm.js. The following is the view.

<div>You've clicked <span id="lblCount"></span> time
  <span id="lblPlural">s</span></div>

 <button id="btnClick" >Click me</button>

 <div id="divWarning">
  That's too many clicks! Please stop before you wear out your fingers.
  <button id="btnReset">Reset clicks</button>
 </div>

Here is the model

hm( "clickApp", {
  clickCount: 0, 
  overClicked: function() { 
    return this.get( "clickCount" ) >= 3; 
  }, 
  plural: function() { 
    return this.get( "clickCount" ) > 1; 
  } 
} );

Here are the subscriptions

$(function () {
  
  var model = hm("clickApp");
  
  //model subscribe view, handler change the subscriber
  model.cd("clickCount").sub($("#btnClick"), "click", function (e) {
      this.set(this.get() + 1);
  });
  
  //view subscribe model, handler change subscriber
  $("#btnClick").sub(model.cd("overClicked"), "afterUpdate", function (e) {    
    this.attr("disabled", e.publisher.get());
  });
  
  //view subscribe model, handler change subscriber
  $("#lblCount").sub(model.cd("clickCount"), "init afterUpdate", function (e) {
    this.text(e.publisher.get());
  });
  
  //view subscribe model, handler change subscriber
  $("#lblPlural").sub(model.cd("plural"), "init afterUpdate", function (e) {
    
    this[e.publisher.get() ? "show" : "hide"]();
  });
  
  //view subscribe model, handler change subscriber
  $("#divWarning").sub(model.cd("overClicked"), "init afterUpdate", function (e) {
    
     this[e.publisher.get() ? "show" : "hide"]();
  });
  
  //model subscribe view, handler change subscribe
  model.cd("clickCount").sub($("#btnReset"), "click", function () {
     this.set(0);
  });
  
});

The code may be a bit long, but it is actually very straightforward. When I wrote the above code, I was thinking from the perspective of subscribers, where I have not desire to control others, I just want to control myself. Unlike normal event handling, all subscription has explicit publisher and subscriber. Unlike normal event handler, subscription handlers all update the subscriber but never update the publisher or any other object. Also inside of the handler, there is no hard reference to DOM or model, this make the handler very portable. Because of the loose coupling between model and view, the library can handle a very complicated view. The library also supports declarative subscription. The implementation of declarative subscription is in JSBIN. And you can remove the above subscription code.

 <div>You've clicked <span text='clickCount'></span> time<span
  show="clickCount|>1">s</span></div>
 <button ++='clickCount' disable='overClicked'>Click me</button>
 <div show="overClicked">
  That's too many clicks! Please stop before you wear out your fingers.
  <button 0="clickCount">Reset clicks</button>
 </div>

AngularJs

AngularJs is the most popular Single Page Application framework nowadays. But some people complain that the learning curve is deep. But if you appreciate the benefit of subscription, you can easily avoid the pitfall and adopt the best practice.

People call AngularJs a MVC framework, I don't know why. Is it because it has a component call controller? If you have enough experience in using Angular, you will find that controller actually does not control anything. It is just a place you write code to expose model to views and directives via an object called scope. I don't know why Angular call it controller, maybe they are running out of good name, or maybe they want to stick with popular name "controller". I would rather call it "model exposer". The model is purely Plain old JavaScript Object (POJO), it does not contain any view related code. The interaction between view and model is through subscriptions, which is created in directives. In the following demo implemented using Angular, I don't use any built-in directive "ng-xxx" and use custom directive in order to illustrate this subscription concepts in AngularJs.

Here is the model exposed by controller.

var app = angular.module("myApp", []);
  
  app.controller("modelExposer", function ($scope) {
    angular.extend($scope, {
      clickCount: 0,
      overClicked: function () {
        return this.clickCount >= 3;
      },
      plural: function () {
        return this.clickCount > 1;
      }      
    });
  });

Here are the directives, which create the subscriptions between model and view.

app.directive("myClick", function () {
    return function (scope, $elem, attrs) {
      var expression = attrs.myClick;      
    
      
      /*
      model subscribe view, handler change subscriber only
      the pseudo code that I want to write is 
      
      scope.subscribe($elem, "click", function () {
        this.$eval(expression)
       });
       
       */
      $elem.click(function () {
        scope.$apply(function () {
          scope.$eval(expression);
        });
      });      
    };    
  });
  
  app.directive("myText", function () {    
    return function (scope, $elem, attrs) {      
      /*
      view subscribe model, handler change subscriber
       the pseudo code that I want to write is 
      
      $elem.subscribe(scope, attrs.myText, "change", function (value) {
        this.text(value)
       });
       
      */
      scope.$watch(attrs.myText, function (value) {
        $elem.text(value);
      });      
    };
  });
  

  app.directive("myShow", function () {
    return function (scope, $elem, attrs) {      
         /*
      view subscribe model, handler change subscriber
       the pseudo code that I want to write is 
      
    $elem.subscribe(scope, attrs.myShow, "change", function (value) {
        this[value ? "show" : "hide"]();
       });
       
      */
        scope.$watch(attrs.myShow, function (value) {          
          $elem[value ? "show" : "hide"]();      
        });   
    };    
  });
  
  app.directive("myDisabled", function () {
    
    return function (scope, $elem, attrs) {      
      /*
      view subscribe model, handler change subscriber
       the pseudo code that I want to write is 
      
 $elem.subscribe(scope, attrs.myDisabled, "change", function (value) {
        this[value ? "show" : "hide"]();
       });
       
      */
      scope.$watch(attrs.myDisabled, function (value) {
        $elem.attr("disabled", value);
      });    
    };
    
  });

Here is the view, which is decorated with the directives above.

<div ng-app="myApp" ng-controller="modelExposer">

 <div>You've clicked <span my-text="clickCount"></span> time
  <span my-show="plural()">s</span></div>

 <button my-click="clickCount = clickCount + 1" 
     my-disabled="overClicked()">Click me</button>

 <div my-show="overClicked()">
  That's too many clicks! Please stop before you wear out your fingers.
  <button my-click="clickCount = 0">Reset clicks</button>
 </div>
</div>

AngularJs does not mention that view and model are connected by subscriptions, it uses traditional event handling. Neither does it explicitly suggest that the handler should only change subscriber, because there is no explicit subscriber in event handling. So I have put some pseudo code in the comment of directives. The pseudo code is the subscription code that I want to write, but AngularJs does not support them. However, Misko Hevery, the father of AngularJs does understand that subscription is good. He gave a talk of AngularJS MTV Meetup: Best Practices, he mentioned that

  • Treat the scope as read-only in views
  • Treat the scope as write-only in controllers

If you don't have the subscription concept, it may confuse you. But once you understand the subscription concept as shown above, it is very easy to understand. Let's modify it a little bit.

  • Treat the scope as read-only in handler when view subscribes model
  • Treat the scope as write-only in handler when controller (model) subscribes view

What this means is that, when view subscribes scope (exposing model) change event, the handler should not change model, so it is read-only (it should change view). When model subscribes view event, handler should change model, so it is write-only (it should not change view).

In summary, subscription is good, because it forces you to think from the perspective of subscriber, and you tend to write handlers which only affect subscribers and don't control on others. And we can live without controller.

May 4, 2014

service in angularjs

AngularJs is different from other JavaScript client-side framework in that it use dependency injection to manage its components. Although dependency injection is not a new method, in fact it has been very successful for many years, it is a new approach in JavaScript client-side framework. So if you never use dependency injection in other language before, it is pretty confusing. The following is my notes on this topic.

There are basically two step to develop your angularjs application.

  1. package and register your components using module like the following.

    (function () {
      var module = angular.module("mymodule", ["ng"]);
      module.value("user", { firstName: "Johe", lastName: "Doe" };
      module.directive("userWidget",  function (user) {
          //user is injected here.
          return {};
      });
    })();
    
  2. Let angularjs run the show by using an injector inject the components you created.

    <body ng-app="mymodule">
      <user-widget></user-widget>
    </body>
    

In the first step, when the page is loaded, angualar bootstrap the application. In the process of bootstraping application, one important object called "injector" is created which is shared across the application. Normally your don't need to access the injector programatically, or manually create an injector by yourself, so you may have never heard about it, or you might think that module and injector are the same thing. But they are not. In fact, you can create multiple injectors, each of them use different modules. But in the following exercise, I will manually create one, because I want to know internals of module and injector.

For now, there are 5 kinds of components you write in angularjs, service, animation, filter, directive, controller. Anything which is not animation, filter, directive, or controller, is service. If the name service confuse you, you can call service as injectable. It can be anything like a string, a number, an object, a dom element or whatever. An "injectable" is not injected by module, but injected by a injector, which has information from modules. The following code create an injector.

var modules = ["ng"];
var injector = angular.injector(modules);

The services we created using module is not really service instance, but service provider. During the creation of injector, angularjs import the service provider we created. However the instance of service is not automatically created. In the following, I have modified angularjs's source code to expose the cached service providers in injector as injector._providerCache and expose the cached service instance as injector._instanceCache, in the following screen shot we can confirm this.

When the injector is asked for an component instance, the injector will firstly check whether the component instance is in cache, if it is true, then return it , if not, ask the corresponding component provider to create an instance, cache the instance, and return it like the following.

AngularJs allows your to create your service provider in several ways. module.provider() is the most flexible way among them. The provider passed into the method need be an object with "$get" method which return to the service.

module.provider()

var module = angular.module("module", []);
module.provider("greeter", function () {
  return {
    greeting: "hello",
    $get: function () {
      //here this refer to the service provider
      var greeting = this.greeting;
      return function (name) {
        console.log(greeting + "," + name);
      };
    }
  };
});
var injector = angular.injector(["module"]);
var greeter = injector.get("greeter");
greeter("Fred"); //output hello,Fred

The flexibility of module.provider() is that you customize customize it later. Let's say, the "greeter" provider is created by a third party company. And you want to customize it's behavior before it get injected. You can write the following code.

var mymodule = angular.module("mymodule", ["module"]);

mymodule.config(function (greeterProvider) {
  greeterProvider.greeting = "hi";
});

var injector = angular.injector(["mymodule"]);
var greeter = injector.get("greeter");
greeter("Fred"); //output hi,Fred

module.factory()

If you don't need such flexibility of service provider, you can use module.factory() method, which is a simplified version of module.provider() method.

var module = angular.module("module", []);
module.factory("greeter", function () {
  return function (name) {
    console.log("hello," + name);
  }
});

var injector = angular.injector(["module"]);
var greeter = injector.get("greeter");
greeter("Fred");

Behind the scene, the module.factory() still create service provider internally exactly like created by the module.provider(), the result of the following is identical to the result of above code.

module.provider("greeter", function () {
  return {
    $get: function () {
      return function (name) {
        console.log("hello," + name);
      };
    }
  };
});

module.service() -- don't use

AngularJs also has a module.service() method which is very similar to module.factory(). In fact, in the above example, you can replace the module.factory() method with module.service(), the final result is the same (but the calling method is different), like the following.

module.service("greeter", function () {
  return function (name) {
    console.log("hello," + name);
  }
});

So why do we need a service method? How is the difference between this two. The source code angularjs show that the service method internally call factory method like the following.

function service(name, constructor) {
  return factory(name, ['$injector', function ($injector) {
    return $injector.instantiate(constructor);
  }]);
} 

This means that the factory method can do all the thing that that service method can do. The difference is that provider function is treated as constructor, it is called like "new constructor()". The following shows the difference

module.service("user", function () {
  this.firstName = "John";
  this.lastName = "Doe";
});

module.factory("user", function () {
  return {
     firstName: "John",
     lastName: "Doe"
  };
});

So when should we use service method, when should we use factory method. So far I never encounter a case when I have to use service method, and factory method is not able to do so. So my opinion is that, never use "service" method, always use "factory" method, because "factory" method simpler and more capable.

module.value()

If you look at the factory method, the "$get" member of real provider is a function which return a instance of the provider. Why can't the "$get" member be just the instance itself? Ok, angulajs has another method "module.value()" which try to meed this need. The value method simply return the instance like the following.

module.value("greeter", funnction (name) {
  console.log("hello," + name);
});

module.value("user", {
 firstName: "John",
 lastName: "Doe"
});

However, internally, the value method is like the following

function value( name, val ) {
 return factory( name, function() {
   return val;
 });
}

So the value method still convert the value into a provider which provide the value internally. But the question, "Why can't the "$get" member be just the instance itself instead of a function which provide the value?" is still not answered. What is the benefit of doing that. Let's look at the following code.

module.value("user", {
 firstName: "John",
 lastName: "Doe"
});

module.factory("greeter", function (user) {
  return function () {
   console.log("hello," + user.firstName + "," + user.lastName;
  };
});

In the above code, the greeter depends on user, the user is passed in the factory method by the injector. If the "$get" is the instance, but not a function, the "user" dependency will not be able to injected. However, if your instance does not have external dependencies which need to be injected by injector, you should use "value" method, which is more expressive, otherwise use "factory" method instead.

module.constant()

All the method above create service provider, which can return a service instance. module.constant() is different in that it does not create service provider, but it create the service instance directly. What this means is that it cannot be configurable using module.config(fn). Before you use injector.get(constantKey) to get the instance, it is already created and cached, like the following.

module.config(fn)

AngularJs has one more method module.config(fn) allow you config imported service provider. When an injector is being created, all the service providers created by the module.provider(), module.factory(), module.service(), module.value() is imported first using $provide. Then the config functions will run. The $provide dependencies can also be injected into the functions, the service providers created can also be injected into the functions. For example, if you create a service call "greeter", the "greeterProvider" can be injected into the config functions, but not the "greeter", because at this stage you are about to customize "greeterProvider" to create "greeter", that is why "greeter" can not be injected. This has been shown in previous demo

Also module.config allow you to create service provider using $provide object. The $provide object has the following method

$provide.provider(key, value); 
$provide.factory(key, value);
$provide.service(key, value);
$provide.value(key, value);
$provide.constant(key, value);

$provide.decorator(key, value);

AngularJs use the first 5 methods to import the service provider created using module method. For example, $provide.provider(key, value) is used to import the provider created by module.provider(key, value), so far and so on. But the question is why we want to use $provide in config function to create service provider directly instead of using the method of module, as they looks like do the same thing? In fact, in AngularJs use the config method the directly create service provider, like the following, but not using module methods.

var ng = angular.module("ng", []);
ng.config(function ($provide) {
$provide.provider({                              
    $anchorScroll: $AnchorScrollProvider,        
    $animate: $AnimateProvider,                  
    $browser: $BrowserProvider,                  
    $cacheFactory: $CacheFactoryProvider,        
    $controller: $ControllerProvider,            
    //..and more 
});                            
});                  

Honestly, I don't have an definite answer. But I think it is different way to organize your code, maybe AngularJs team think that is better for code minification or file organization. But the module method is good enough to organize application level development (vs framework development).

The $provide.decorator() is most interesting method of $provide object. You can use it to extend existing service provider. The following is an example

var module1 = angular.module("module1", []);
module1.value("name", "John");


var module2 = angular.module("module2", ["module1"]);
module2.config(function ($provide) {
  $provide.decorator("name", ["$delegate", function (oldInstance) {
    return oldInstance + "," + "Doe";
  }]);
});


var injector = angular.injector(["module2"]);
injector.get("name"); //name is John,Doe

If you have question about service dependency injection in angular, please leave me a note below.

Apr 3, 2014

Aliasing angular key concepts

AngularJS is a single page application framework. Although, it never markets itself as a "MVC" framework, it uses lots concept of MVC, like model, view, controller. Once you start using it, you will find the concepts it use does not map 100% to your concepts. So I feel that I need to alias these key concepts to align to my understanding. If you don't understand these concept correctly, you can use them in a wrong way very easily, because AngualrJS allow you to do so. In the following, I try to explain them by giving each of them an alias. Although an alias is not trendy, but at lease it helps me to understand. Hopefully, it helps you too.

service : injectable singleton

The term "Service" is a used every where, it means different things to different people in different context. AngularJs uses dependency injection to create almost all the reusable objects. Angularjs call this kind of object service. So the name service is probably not your concept of service, technically service is injectable singleton. It can be a piece of data, a method, or anything. A injectable object has lots of benefit, such as it is easy to test, customize, extend. In a word, angularjs recommend you to create all your reusable of "things" as service. The following artifacts such directive, scope, controller everything is kind of "service" internally in angularjs.

directive : behavior builder

AngularJS turns a static html document into an application. The application is still composed by DOM elements, but these elements has behavior. When the page loaded, AngularJS parsed the html document recursively for some special tag, attribute, or class name which map to something called "directive", which attach behavior to the DOM elements. The behavior can be reflected as the following.

  • Handle data event of scope, and change DOM
  • Handle DOM event, and change the data of scope
  • Handle change event of scope, and change other data of scope. This is not good practice, you can do it by other means
  • Handle DOM event, and change DOM. This is necessary sometimes, but it is not a good practice in general.

scope : model context

On the view site, there is DOM, which is a tree of html elements and attributes. On the model side, there is scope which is organized as tree. Angularjs attach each DOM element with a scope, so scope is like a context to describe model. When you stand on a DOM node, and talk about a model concept such as "customer", the concept "customer" is within a context (scope). When you stand on another node, the same concept of "customer" may or may not be the same thing depending on the whether two node sharing the same context (scope)

  • The most important functionality of model context is change detection. When data change, implement behavior in directive.
  • Expose read/write access to data to view.
  • Generate custom data event which can be passed up to ascendant model contexts
  • Generate custom data event which can be passed down to descendant model contexts

controller : scope builder

A DOM element is associated with one and only one scope. This scope can be inherited from the scope of parent DOM element, or it can be explicitly created by directive ng-controller or other directive. Directive ng-controller is implemented by module.controller() method. Other directive which create a new scope is implemented by module.directive

Apr 16, 2013

angularjs-sugar

The normal way to to creating anguarjs component is like the following.

var sugar = angular.module('sugar', []);
sugar.controller('controller1', function($scope) {
  $scope.m1 = m1;
  $scope.m2 = m2;
});
sugar.config(configFn);
sugar.constant("constant1", object);
sugar.directive("directive1", directiveFactory);
sugar.factory("factory1", providerFunction);

sugar.filter("filter1", filterFactory);
sugar.service("service1", constructor);
sugar.value("value1", object);
//....

I have created a script to simplify the process, so that you can write code like the following.

//angular.m("sugar", [dep1, dep2], definition);
angular.m("sugar", {
  controller: {
    test: function ($scope) {
      $scope.$extend({
        m1: m1,
        m2: m2
        };
      });
    }   
  },
  constant: {
    constant1: object
  },
  directive: {
       directive1: directiveFactory
   },
  factory: {
     factory1: providerFunction
   }
   //....
});

//you can split the definition in to multiple piece
angular.m("sugar", definition1)
angular.m("sugar", definition2);

The good things about it are:

  1. It is not easy to create global variable
  2. The code is more readable
  3. You can create all module components in a single call, this is useful for simple application.

You can get the code at https://github.com/fredyang/angularjs-sugar. And there is an example at Plunker.

Feb 9, 2013

Harmony.js

I haven't updated the blog for some time. Because I am working on an interesting JavaScript UI Library, Harmony. Like other JavaScript library such backbone.js, knockout.js, it tries to build HTML application in a structured way. What is unique is that it does not a have controller or binder. The models and views are pretty much on their own. They all take care about themselves by subscriptions. Are we going back to the age that we have tons of event handlers like spaghetti? Far from it. There are really lots of subscriptions and their handlers, but they are structured in a way that feels like object-oriented. The subscriptions and handlers are part of the objects (views and models). The views and models are treated like Human being in Harmony, they make decisions on their own, they respect each others, they are not manipulating or commanding each others.

It does not feel like programming. I agree. I have written an introduction and some documentations. I also wrote a evaluation app, todos, I am satisfied in that the views and models are shorter and more semantics than other implementations in todomvc.com. But it is just my personal feelings, let me know what you feel about it.

Apr 24, 2012

"use strict" and "this" in ES5

"this" is a special variable in JavaScript. If a Constructor function is called without "new", the "this" variable inside the constructor will reference the Global object. We can use "use strict" in ES5 to prevent this happening.

(function () {
  "use strict";
  console.log(this === window); //false
 })();

You can also use the "use strict" in global, but this will affect all module

 "use strict";
 console.log(this === window); //true
 (function () {
  console.log(this === window); //false
 })();