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
 })();

Dec 23, 2011

Why dynamic resource loading is so important for web application?

When I finished matrix.js 0.1, I asked for feedback from my friends. But the general response seems that I am trying to solve a problem which does not exist, so the library is useless. But I am not disappointed. I make it not because we have a pain point in my current projects, but because I see it is the way that we need to build future web application. It is better to explain what the problem is as I see, before I propose on a solution. I believe that, as we are developing web application, dynamic resource loading will be a essential function. The current way to import resource using <link> <script> tag statically and tools like combres will not be able to meet the needs of building web application.

The future web application? Isn't that we are a building web application. Yes, in a way we all building web application. There are two extreme of web application. On one extreme, web application completely depends of the <form> tags, all interaction depends on form postback, and page get re-rendered, one example are government web sites. On other extreme, web application does not have <form> tag, all interaction depends on ajax call, all UI is generated by JavaScript, template and the application stay in the same url until it is closed by user. This kind of application is fast and fluid, is as responsive as native desktop application. Gmail is an example close to this extreme. We are normally building web applications somewhere in between these two extreme.

To increase the loading speed of website, Minimize HTTP Requests is one of the rules listed in "Best Practise for Speeding Up Your Web Site". In .net, to minimize http requests, a popular approach is use tools like combres to combine, minified, gzip a set of resource, configure response header for client side caching. So that one big JavaScript file and one css file are generated and cached at client side. When we are building our current applications, the resource like JavaScript, css can be known more or less in advance. Because all pages in the website pretty much share some library like jQuery, a couple of widget plugin, like calendar, accordion, auto complete and so on. We can hand pick a set of resources required in specific page, or for the whole website. If we have a page require very different set of resources, we may need to pick another set of resources targeted for that page. So far so good.

As we are moving to an other extreme, building web application like Gmail, or even more complex, the architecture of our application changes. In this extreme, the application is responsive as desktop. The application compose and aggregate lots UI modules, or views, each views has their unique resource, and in a lot of case, we cannot anticipate which views will be used by user. All the views are built on demand of user. We need to load lots of client side template, view specific JavaScript, and unload them when view is not used, because the application is open for 8 hours a day continuously, memory management is critical for good client side performance. These requirements can not be solved by combres or statically resource loading. Combres can shorten the time to transfer resource from the server to browser. But it can not solve our architecture requirement like client side memory management, reusable, modular component design, dependencies tracking among resources. This resource is like Dynamic-link library, but it just happens at browser. Browser is our VM, not CLR not JVM. In .net, CLR is the run time. Assembly(DLL or EXE) is reusable unit. The loading of assembly is highly sophisticated. Here are some features.

  • Assembly Manifest contains of dependencies of dll/exe
  • Appdomain
  • Security check
  • Late binding
  • Dynamic loading

matrix.js is my starting point of building a true web application. I try to address similar issues we have like in assembly loading in .net, but I just do it for the browser vm not for CLR or JVM. Unlike CLR, browser vm has some advantage CLR does not have. In CLR, you can release your DLL, until you kill your AppDomain, in browser, you can unload everything dyanamically. You can remove DOM elements, you can unload a library , like jQuery by calling "delete window.jQuery", you can unload css by remove the link tag.

As we move to web application extreme more and more, preload two resource files (one js, one css) is like we load one gigantic EXE for a win32 application. Not only it is bad from the aspect of memory managemeent, it is even worse from the aspect of software engineering. It become monolithic artifact, while we want to have modular, reusable component.As HTML5 is ready, we will be building more and more application like Gmail and more complex, I believe dynamic resource loading is essential but not a fancy feature. Maybe you don't see the need to build a true web application right now, if you have, you can check out matrix.js

Dec 7, 2011

What does the size of a JavaScript Library say about it?

When people introduce a JavaScript library, they often mention that the size of the library is very small, like "it is small and light weight, xx K minified, in fact is about yy k when gzipped". Does this means a library runs fast or use less memory? Neither. We know that 1k size virus can use up all your machine resource, and make it dead slow, right? What it means the library can be transported to client side faster. Normally the more features a library provide, the bigger the size. You can use profiler (like the one built in Chrome) to collect data when using the library in real life scenario.

Sep 22, 2011

The design principle of viaProxy

[update: the library is now in github, and the sample code discussed in this post is here]

viaProxy is a client side JavaScript library that can be used to build complex, fast and fluid web UI yet in a manageable code complexity. It is a set of low-level api which is built on top of jQuery and enable you to synchronize your view and model using imperative programming (code only) or declarative programming ( mark-up only) or both. You can use it to write testable views, modules, plugins, and aggregate them into complex view.

About a year ago, that is after I wrote jquery-matirx, I had been thinking a problem in a project. We were developing a rich web UI using JavaScript intensively , but as the logic of application grows, the JavaScript code explode, and become buggy and spaghetti like, as our logic is distributed every where in the handler. Although, I create a solution to dynamically load view into the page at client side with some template, but does not solve the issue completely. So I think, is there a UI framework to address this issue systemically. I studied libraries like Backbone.js and knockoutjs , which seems to be good UI framework. Initially, I thought I had sufficient JavaScript competency to use them, it turned out I had lots of difficulties to write a "hello world" app with them, and even greater difficulties in solving a real world scenario. The syntax and convention are just too cryptic for me, and it is hard for me to do unit test and debug. So I decided to write my own, that is how I started viaProxy

Before I discuss how to use the library, I want to put the design principle of the library upfront, which is fundamentally important to use the library.

The principle is to separate model interaction from model presentation.

You can think of model interaction as CRUD(CREATE, READ, UPDATE, READ), and model presentation as view rendering. A view is the typically the UI that user can see and feel, a model is typically business object of your application. I want to use the word "typically", because sometimes, the difference between view and model can be blurred. A view can be just another model, we will discuss this in the future post.

Let's take a look at "Hello world" application to understand how model and view play together. The application allows user enter a name, and click a button, the application display a greeting message. Here is markup that defined the view.

<label>Please input your name: <input type="text" id="txtName"/>
 <input id="btnGet" value="Get message" type="button"/>
</label>

<div id="divMessage"/>

And here is a piece of javascript to implement the user story.

$(function () {                                       
                                                      
 $("#btnGet").click(function () {     
                
  var name = $("#txtName").val();                     
  if (name) {                                         
   $("#divMessage").text("Hello," + name);            
  } else {                                            
   $("#divMessage").text("");                         
  }
                                                   
 });                                                  
});

You might be laughing at how stupid the code it is. But there is nothing wrong with it, in fact, it is simple and elegant, if this is everything that the user want from the app. However what user want is far more complex web application. If you have a little bit web UI programming experience, you probably agree that, by applying this style of implementation to develop complex UI, the code will soon explode and become spaghetti.

Let's take a closer look. In the click handler, it by-pass the model and directly update the view, in fact it does not even define a model, it just directly convert user's click action into updating view. When user stories grows, we need to create more viewsto implement them, and we need more view handlers to take care of user interaction. Our view handler will have hundreds or thousands lines code doing thing like "If user input this, do this, if input that do that, because of this change, we also update an this view, because that change, we also need to update that." Very soon, the code complexity will grow out of control. So what is wrong? The fundamental fault is mixing model interaction with model presentation, because our view handler has too much thing to worry.

Let's refactor the above code using viaProxy. At first sight, the refactory may require you to write more code, what I show is how viaProxy works under the hood, I will introduce higher level viaProxy API which can reduce your code to minimum or no code at all. The first step is to define a model, which is missing from the previous implementation. Without model, we can not possibly separate a model interaction from model presentation. Model is center of an app. So here is the model.

var rootProxy = via();            
var helloAppModel = {                                     
   name: null,                                                        
   greeting: "Hello",                                                 
   message: function() {                                              
     return this.name ? this.greeting + "," + this.name : "";          
   }
};                                                                 
rootProxy.insert( "helloApp",  helloAppModel);

The model is a javascript object which has 3 members name, greeting, and message. The message function combines greeting and message. It is very pure and simple, that it does not inherit from anything other than object, it does not use hard-to-understand concepts like "Observerable", "viewModel", which are used in other framework. As your can see, we put our model into a repository using a proxy with a namespace "helloApp", this prevents you from direct access to the model, all access must be via the proxy, this is why the library is named viaProxy.

Now let's take on model interaction. Instead of using raw DOM event directly, we wrap it into higher abstraction, view event. View event can be one-to-one mapped to DOM event, but it can be customized event. For example, we can create an "enter" event which will trigger when "keypress and keycode === 13" event triggers, I will cover that later. Here is how we attach a view handler to the view event, like below.

$( "#btnGet" ).addViewHandler( "click", "helloApp.name", 
  function( viewContext ) {
    var value = $( "#txtName" ).val();  
    viewContext.updateModel( value );
    //or 
    //via("helloApp.message").update(value);
} );

The view handler is also associated with a path("helloApp.name") which is pointer to the model in repository. In the view handler, it does only one thing, updating the model with the user's input, however it does not care about updating the divMessage, because this is the job of model handler. This is a big difference from the previous implementation. Remember, model handler is only place do model presentation. Here is the model handler to update the divMessage.

$( "#divMessage" ).addModelHandler( "helloApp.message", "afterUpdate", 
   function ( modelContext ) {
     var value = modelContext.currentValue();
     //or 
     //var value = via("helloApp.message").get();
     //"this" refer the divMessage
     $( this ).text( value);
} );

The semantics here is when model event "afterUpdate" happens to "helloApp.message" in the repository, call this handler to update view "divMessage". In the model handler, it also does only one thing, update the view. You maybe notice that the previous view handler update "name" property, why the event of "afterUpdate" is raised for "message" property, this is because viaProxy knows this dependencies between "name" and "message". Here you don't need to write some thing like "observerable()" which is used by other library. After creating the model, adding a viewHandler, a modelHandler, your "hello world" application is up and running.

So what is the big deal of separation model interaction from model presentation. It might not be obvious for you right now. But here is a few things that I can think of. Firstly the separation can reduce code complexities to be manageable. As your application complexities grow, your code will grow linearly but not exponentially. You can add more view handlers to a view event to update more model, and add more model handler to model handler to update more views.

Secondly, the separation make each handler focus on one thing, so that code is more reliable, more testable. Yes, we can unit test our UI. I will cover that later. The idea is that we can test our view handler by triggering fake mouse event without a real mouse click. Because view is rendered by model handler, to test a view is to test model handler. We can test model handler by updating our model using via proxy.

Thirdly, you have a explicit, complete model, a single copy of logic, not a duplicated partial model distributed in spaghetti code. And the model can scale, you can add more model into different name space. The model the king of your UI, which rules the application. Different parts of model become shareable, and connected. The code become more easy to understand because of this.

There are other creative uses of viaProxy. For example, in our ajax callback, instead of update the UI directly, ajax callback update model using viaProxy, and your UI will be updated indirectly in a model handler. Instead of making ajax call directly in your view handler, your view handler can update model using proxy, that will trigger model handler, which will make the ajax call.

Through the "hello world" example, we can see that the design principle of viaProxy is to separate model interaction from model presentation. Essentially, it provides three following mechanisms to facilitate the separation.

  1. A proxy to build and access models
  2. An extensible model event mechanism to connect model to view
  3. An extensible view event mechanism (based on jQuery event) to connect view to model

Now that we know the design principle behind viaProxy, what is next. There are still lots of challenge. Does it work in a real world scenario or in large scale implementation, does it work with other existing controls or plugins, what if my model is complex object like array instead of simple string or number, is it extensible, how about validation, does it encapsulate too much or too little, is it too automatic, how easy is it to customize it, can I continue to use my programming style while using viaProxy, what about learning curve? I have considered all these when I develop the library, and I will discuss more in the future posts. Let me a comment, tell me what you think and stay tuned.