Tags:

summer2013conf

Just like last year, summer means I’ll hit the road and do some evangelism work.

First, I’m scheduled for O’Reilly VelocityConf 2013, June 20 in Santa Clara. This will be my third time speaking at Velocity and I’m quite thrilled about that. This time, my talk (Thursday, 1:15pm) is about Emerging Language Tools to Track JavaScript Quality and Performance.

Next, Waltham, MA should be my next visit. Engineers4Engineers (June 28) will be pretty exciting, I pick the topic of Next-Generation JavaScript Language Tooling for my 45-minute talk. This conference is also top-notch, you’ll see a few amazing rockstars, including Charles Nutter (JRuby) and Mitchell Hashimoto (Vagrant). I’m a big fan of them and can’t wait to learn some magic tricks from their sessions.

Mid July, I’ll be doing several talks at SenchaCon 2013 in Orlando, FL (disclosure: Sencha is my employer). One of them is ECMAScript 6: JavaScript of the Future. If you are an avid follower of this blog, you probably can guess what this is all about just by reading my past posts on ECMAScript 6.

If you will be around in any of these places, let’s chat!

Tags:

Lumia 920 is Nokia’s smartphone running Windows Phone 8 that is getting quite popular these days. When using this phone for browsing the web and running web applications, how does it stack up against its competitors?

First of all, let’s check its browser user agent:

Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)

Hardly a surprise, it is running the mobile version of Internet Explorer 10. This is good news since it is expected that many web pages out there will be supported just fine. With respect to the new HTML5 features however, it doesn’t seem that many of them are support yet since HTML5Test gives the score of 320, quite behind other competing mobile platforms.

One thing that I did quickly check is the browser’s ability to process lots of data by running a simple pixel crossfader using HTML5 canvas. This simple test exercises the CPU and its collaboration with the rest of the graphic stack. For this test and other subsequent ones, Lumia 920 will be compared against Nexus 4 running Chrome 26 on Android 4.2 and iPhone 5 with iOS 6′s Mobile Safari.

lumia920_crossfading

From the outcome, it seems that iPhone 5 is still the king here. While both Lumia 920 and Nexus 4 are powered by Krait (dual-core and quad-core, respectively), there must be another factor in iPhone 5 which makes it extremely fast. Could be the high-performance A6 SoC, or maybe it’s just the tight software hardware integration.

Speaking about performance, what about running JavaScript-intensive applications? We turn to Octane benchmark to find the answer:

lumia920_octane

Again, the CPU differences certainly contributes to the varying score. It seems however that IE 10′s JavaScript engine (often known as Chakra) is still behind its competitor particularly for this ARM platform.

Last but not least, DOM performance has been always my favorite (check the past performance checks with Nexus 4, Nexus 7, Kindle Fire). I do believe that high-performance DOM access has a profound (positive) impact on the browsing experience. Armed with the collection of DOM core tests from Dromaeo, here is what we got:

lumia920_dromaeo

Unfortunately, this combination of Lumia 920, Windows Phone 8, and IE 10 doesn’t really deliver the same cutting-edge DOM performance as its immediate market competitors. This might be related to the rather abysmal DOM speed of its desktop cousin, Internet Explorer 10.

What to expect with IE 11 on the next Windows Phone? Better web performance!

Tags:

Complicated code is difficult to digest and hard to maintain. The best way to avoid it is by not having it at the first place. For web applications written in JavaScript, fortunately we have enough tooling machinery to detect complex code and block it from the source repository.

Analyzing code complexity is rather easy these days with the project like JSComplexity. Even better, the complexity metrics can be visualized in a good-looking and interactive report showing different metrics from McCabes cyclomatic complexity to Halstead complexity measures. Both these tools are easy to setup, they run quite well on the command-line (using Node.js).

A preventive approach to force a complexity threshold on a new code is by using complexity comparison. With JSComplexity, this can be done via its --maxcc argument (there are other useful options as well, refer to its README for more details). If the package complexity-report is installed globally, this checking is easy as:

cr --maxcc 15 index.js

To inject this in the multilayer defense workflow, simply include that check as part of e.g. Git precommit hook. If your project relies on Node.js for the test (i.e. via npm test), it is also useful to integrate this check. First of all, ensure that complexity-report package is within the devDependencies section of your package.json and then add a new entry for the scripts section, such as:

"complex": "node node_modules/complexity-report/src/cli.js --maxcc 15 index.js"

which permits running the check by npm run-script complex. Now it is a matter of inserting this step in the main test of the scripts section. If there is a function in index.js which has a cyclomatic complexity more than 15, that tool will complain and therefore cause the entire test to fail.

While this already serves as a good complexity filter, we can bring it to the next level. For a start, it would be better if we have a clear understanding of the most complex functions. That way, it is easier to spot the worse offenders and have them fixed first. Again, this just requires a quite simple script, as illustrated from Esprima’s implementation of tools/list-complexity.js.

var cr = require('complexity-report'),
    content = require('fs').readFileSync('index.js', 'utf-8'),
    list = [];
 
cr.run(content).functions.forEach(function (entry) {
    list.push({ name: entry.name, value: entry.complexity.cyclomatic });
});
 
list.sort(function (x, y) {
    return y.value - x.value;
});
 
console.log('Most cyclomatic-complex functions:');
list.slice(0, 6).forEach(function (entry) {
    console.log(' ', entry.name, entry.value);
});

Running the above script will list 6 functions which have the highest cyclomatic complexity. An example output is illustrated in the following screenshot, taken verbatim from Travis CI build report of Esprima.

travis_complexity

Because Travis CI can run the tests on every GitHub pull request, such a report becomes very valuable when doing code review. If someone introduces a complex piece of code, it will be blatantly obvious. This preemptive defensive layer avoids unintentional merge of unreadable handiwork.

Complexity analysis costs almost nothing. Why not always doing it where it makes sense?

Tags:

With the popularity of test-driven development (TDD), running a project which does not include an automated test workflow is often frown upon. The recent trend pushes it further: if the code coverage is not measured and monitored during that testing, the confidence level will not be very high. For JavaScript projects, how do we keep track of the coverage and prevent any regressions?

If the project is using Istanbul, the comprehensive code coverage tool for JavaScript, tracking is almost trivial. This holds even for a simple project. As an illustration, let’s have a quick look at esrefactor, a microlibrary which I created for assisting semi-automatic JavaScript refactoring, and its test suite. Running the unit tests (via Node.js) is a simple as node test/run.js (the tests are so simple, no external test framework is being used). Should we want to see the code coverage (and its report), istanbul is our best friend:

istanbul cover test/run.js

Once the coverage metrics are obtained, we can compare them against our predefined thresholds, serving as the baseline coverage limits. For example, the following line means that the statement coverage should be 90% or more. If it is less than the specified limit, Istanbul will complain aloud.

istanbul check-coverage --statement 90

While this is already very nice, this percentage threshold is often not what you want. In another scenario, we know the unit tests cover 45 statements and miss just 5 statements. How do we ensure that any future modification to this project does not degrade that coverage further to 6 or more uncovered statements? This is where Istanbul’s negative threshold feature becomes really handy. All we need to do is to tweak the coverage check like the following:

istanbul check-coverage --statement -5

Next time someone checks in a new piece of code which doesn’t come with a set of suitable unit tests, the above Istanbul invocation will warn that poor fellow that a coverage regression happens. Even better, enlarge the safety net by including the thresholds for function coverage and branch coverage (read also my past blog post on the significance of branch coverage):

istanbul check-coverage --statement -5 --branch -3 --function 100

Obligatory screenshot showing the situation where the threshold wasn’t hit:

istanbul_limits

As described in my multiple-layer defense approach, running coverage check manually is not the most optimal protection. We can bump up the coolness factor by using the powerful Git precommit hook feature. Now, don’t even try to sneak in untested code!

For many projects which rely on Node.js and npm, coverage check can be injected in the test ritual as well. First, add istanbul package into devDependencies section in package.json. To complete the typical npm install && npm test workflow, we need to involve coverage threshold check in the last step. The simplest way is by taking advantage of scripts section, illustrated here:

"scripts": {
"test": "node test/run.js && npm run-script coverage",
"coverage": "npm run-script analyze-coverage && npm run-script check-coverage",
"analyze-coverage": "node node_modules/istanbul/lib/cli.js cover test/run.js",
"check-coverage": "node node_modules/istanbul/lib/cli.js check-coverage --branch -2"
}

For a more serious project, using additional tools such as Grunt.js is highly recommended, particularly if some testing framework and/or test runner are also involved. There are already packages out there which integrates Istanbul with e.g. Mocha and QUnit. Thanks to this composibility technique, you can also find helper packages for test runners like Karma (née Testacular) and BusterJS, or even for CoffeeScript (via ibrik). Skipping coverage analysis should not be an excuse anymore!

I’d like to close this blog post with a brilliant statement from @davglass:

“If you think JSLint hurts your feelings, wait until you use Istanbul”

Protect yourself against code coverage regression, you’ll sleep better every night.

Tags:

Modern Android applications tend to follow certain user interface patterns, primarily as described in the official Android UI Guidelines. However, not every application is designed equally. Here we see how three news applications have the overall same look, yet the significant detailed differences are immediately obvious.

BBC News application feels like the most polished. The top navigation bar looks and behaves as expected. Horizontal swipe works perfectly. The landing screen offers high-resolution photos, perfect for the new class of high-end Android smartphones. In my opinion, if someone uses many popular Android applications, BBC News application gives the least amount of surprises.

news_apps

On the other hand, CNN application only adopts some of the best practices. Surprisingly it feels more like many Facebook-y applications, with the side bar which slides in and out. Tapping on its big “CNN Headlines” also does not bring you back to the landing screen. The news list shows the individual list items with this glaring dark gradient, quite hard on the eyes. There is no possible tweak to disable news update or even choose the update frequency. Last but not least, the “This is CNN” audio message when starting the application is fancy and welcoming, but it is kind of annoying (fortunately you can disable it, which you should do right away).

How about NBC News? Its application does not support horizontal swipe, there are only left and right arrows you can tap to move to the previous or next story. The landing screen is not special at all, many down arrows just add the clutter with no immediate benefit. Also, in the story list, you tend to see ad banners inserted here and there, another noisy elements. Finally, choosing the news section involves the use of this colorful rotary menu, complete with some animation and sound effect. This menu looks interesting at first, but the novelty wears off pretty quickly.

The above three applications were random samples, I picked them from the recommended ones in the Play Store. I also deliberately tested channel-specific applications and not the aggregator ones (maybe for some other time).

What is your favorite news application? How is the user interface?

Tags:

One of the common refactoring activities is variable renaming. Many respectable IDEs have such a language-aware renaming feature. In some other cases, this is carried out via a simple search and replace. Manual search replace is error-prone and hence why a syntactically-correct rename refactoring tool can be useful.

We have seen how identifier highlighting is implemented in a simple Orion-based code editor. Renaming is the obvious next step, instead of just highlighting now we need to monitor any possible change to the code and appropriately rename the other identical references as well. For this purpose, there is a live rename refactoring demo you can try yourself at esprima.org/demo/rename.html.

Assume we have the following function. It is extremely simple, the function returns true if the specified character is a hexadecimal digit.

before_renaming

Later on, somebody decides that the name of the function parameter needs to change. All he needs to do is to place the cursor on any occurrence of that parameter (note the yellow highlight in two places) and start typing in the new name. Voila! Now both references get the new name. This renaming also works for normal declared variable as well as function name.

after_renaming

Because this demo uses escope (GitHub: github.com/Constellation/escope) from Yusuke Suzuki, the scope analysis follows the ECMAScript 5.1 specification faithfully. If there are other variables with the same name, if they are out of scope, those won’t be touched and got renamed. This is something that a blind search and replace will not recognize.

In a real-world application, functions are very likely more than just one-liner. Doing a renaming via an automated tool will save a lot of time, no need to hunt every single reference and to ensure that the scope is correct. The latter is practically quite tedious, especially for a deeply nested code polluted with some callbacks.

Be advised that JavaScript is a flexible and dynamic language. Because of that, automagic application-wide renaming is often not always possible, in particular because resolving of an identifier can’t be correctly carried out until the code is executed. Many strategies have been developed to mitigate the issues, from a comprehensive type analysis to a convention-based approach. This will push the renaming refactoring further to the best-effort level.

For programmatic renaming (perhaps you want to replace all obj into the more descriptive object or something more logical than that), you can use a convenient microlibrary called esrefactor (GitHub: github.com/ariya/esrefactor). This library internally uses escope to analyze the scope after the syntax tree is obtained via Esprima. For Node.js users, there is the new esrefactor package ready to use.

Once it is set up, the real renaming action is usually just taking just a few lines of code:

var ctx = new esrefactor.Context('var x; x = 42');
var id = ctx.identify(4);
var code = ctx.rename(id, 'answer');

In the above code fragment, we first locate the identifier (in this case, it is a variable) at the index position of 4 (right before x in var x). After that, we use the rename() function to have it renamed to the new name. Predictably, what you get from code is var answer; answer = 42.

Next time you plan a semi-automatic renaming refactoring to your code, you know what to do!