Tags:

Many articles have been written about some unacceptable elitist behaviors of software maintainers and other project leaders. I couldn’t agree more, I think nobody should be a jerk. On the other side of the story, do you ever wonder what kind of problems a maintainer usually encounters in his daily routines?

This question is harder to answer, particularly since not everyone ever maintains a software project (while almost everybody is a user of one or more software). From years of observing many different communities, and also from my own experience, this a typical list I can come up with. Note that some parts are biased towards FOSS (free/open-source software).

Demanding users. As soon as an application gains some traction, it is almost guaranteed that some users will start to ask for unreasonable things. Many times a maintainer will be requested to solve the design or architectural problem of the user’s project. The line which defines the responsibility often gets blurred.

Impatient (potential) contributors. Just because a project is hosted on GitHub, it does not mean somebody can create a patch, submit a pull request, and expect it to be immediately accepted. There are still house rules, everything from the testing workflow to the commit log format.

Opinionated, non-constructive rant. Someone looks at the project for 10 minutes, decides that it doesn’t satisfy him, and then ends up writing a philosophical dissertation about it. Aggressiveness and drama do not bring anything anywhere.

Note that some activities above can be still helpful, it always depends on the context. And obviously, there is no strong reason to be extremely upset if such things occur in our life.

Being Positive

If you are a project maintainer, what would be the best strategy to handle such an influx of negative energy? Here are my tips, feel free to share yours.

Establish an explicit contract. For example, if you are doing this on your spare time, simply state the situation. Who am I to judge when you prefer to spend time with the family instead of fixing a bug?

Never take it personally. When an expectation is not fulfilled, it is very natural to find a scapegoat. Human has a knack for passing the frustrating problem to someone else down the food chain. Often, you just happen to be in the wrong place at the wrong time.

Focus on things that matter. If you are tempted to respond to every single attack on Hacker News, you are doing a disservice to your happy users. Critics are important but they should never redefine who you are or even reschedule your priorities.

Take some time off. Surprisingly, life goes on even if you stop doing anything anymore. It’s just a piece of software, if it gets abandoned then someone will pick it up and continue where you left off. No pressure!

Software maintenance is a nice exercise to self-restraint. As with any other emotional exercises, it will make you a better person. Remember that maintaining a software project is an honor. For an open-source project, it is an important mission to the community.

Stay hungry, stay passionate!

Tags:


Photo by christopher goodband CC BY-SA 2.0.

Winter is coming. The recent December solstice occurred on Dec 21 where I also tagged version of 1.8.0 of PhantomJS, headless WebKit for page automation. The code name for this release is Blue Winter Rose, as chosen by Ivan:

Bael the Bard climbed the Wall.
Took the Kingsroad and entered Winterfell.
He made himself known as Sygerrik of Skagos, a singer.
He sang until midnight for the Lord’s pleasure.
Impressed by his skills, Lord Brandon Stark asked him what rewarded he wanted.
Bael asked for the most beautiful flower in Winterfell’s gardens.
Blue winter roses were just blooming.
Brandon Stark agreed to offer him one.

One of major highlights in this 1.8 release is the integration of Ivan’s excellent project Ghost Driver. It is an implementation of WebDriver Wire Protocol on top of PhantomJS. Selenium users might be excited because now there is also an easy way to run your tests without launching a browser. Thanks to the integration, setting up PhantomJS as a remote WebDriver is ridiculously trivial:

phantomjs --webdriver=9134

You can control this from many different environments, from Ruby to Java. As also mentioned in the release notes, here is a Ruby example (pardon my slight deviation from the classic Cheese example):

require "selenium-webdriver"
driver = Selenium::WebDriver.for(:remote, :url => "http://localhost:9134")
driver.navigate.to "http://google.com"
element = driver.find_element(:name, 'q')
element.send_keys "PhantomJS"
element.submit
puts driver.title
driver.quit

Here is another simpler example in JavaScript using Node.js and the WebDriver module:

var wd = require('wd');
var driver = wd.remote('localhost', 9134);
 
driver.init(function() {
    driver.get("http://casperjs.org", function() {
        driver.title(function(err, title) {
            console.log(title);
        });
    });
});

Because of the setup, running via PhantomJS is typically faster for many types of test scenarios. Of course, it does not eliminate the need for a comprehensive cross-browser testing. Rather, use it as an additional development helper, particularly with the strategy of multiple layers of defense.

Last but not least, here is the chart comparing the total downloads of some recent releases.

I’m fairly sure that some of the downloads are caused by automatic PhantomJS installation for some continuous integration workflow. Nothing is wrong about that of course. On the other hand, looking at tons of recent blog posts/articles about PhantomJS, obviously we get more and more (happy) users.

Many thanks to everyone who contributed to this release. You guys rock!

Tags:

Nobody likes to read complex code, especially if it’s someone’s else code. A preventive approach to block any complex code entering the application is by watching its complexity carefully.

There are many measures of code complexity, the popular ones are McCabes cyclomatic complexity and Halsteads complexity. For JavaScript applications, there is a new tool from Phil Booth called JSComplexity which can be used to analyze your code and find out the complexity measures. Besides the above two code metrics, JSComplexity also produces the logical line of code (LOC) and the overall maintainability index. There is a whole page dedicated to explain the definition of these metrics and how they are computed.

JSComplexity can be used online via its web interface. Just paste your code and it will show you the analysis result. Under the hood, JSComplexity uses Esprima to parse your code and get the abstract syntax tree (AST). The syntax tree is then traversed according to the complexity analysis algorithm. For command-line use, you can use complexity-report package for Node.js.

Cyclomatic complexity is particularly interesting because (in laymen’s terms) it maps to the craziness of your program flow. If the code has tons of branches and paths, your cyclomatic complexity is catapulted to the sky. For the fun of it, here is the chart showing the cyclomatic complexity of some popular JavaScript libraries.

Of course, just like any other code metrics, code complexity should not be treated religiously. We also don’t have to think about complexity only in a one-dimensional way. In fact, correlating complexity with other variables usually reveals a much more useful insight. For example, plotting cyclomatic complexity vs time will display the dynamics of the code as the engineers refactor some parts or rewrite other stuff. Mapping complexity with different modules may give some hints as to which modules still need more TLC.

Use complexity measures to your advantage and hopefully you are better prepared in the battle zone!

Tags:

Apache Ant is quite popular for automating build-related tasks, especially in the enterprise environment and continuous integration systems. Many organizations which already standardized on Ant and start to adopt web application development would want to explore the possibility of keeping Ant for a variety of JavaScript-related workflow. One of the tasks is to ensure that the JavaScript program is syntactically valid. It turns out that this is not difficult at all.

A few weeks ago, I have written about validating JavaScript files from the command-line, text editor, git pre commit hook, or continuous integration system. In this installment, we will expand the approach so that the syntax verification can be invoked as an Ant task. So that you can follow along, I have prepared a git repository, github.com/ariya/ant-javascript-validate, which serves as a complete example.

The working principle is very similar as the previous blog post. We utilize the power of Ant scripting feature and ince Bean Scripting Framework (BSF) supports running JavaScript code (using
Mozilla Rhino under the hood), we will use it to run Esprima-based syntax validator. For convenience, this will be wrapped as an Ant task called jsvalidate.

The example repository demonstrates the usage. After you clone the repo, all you need to do is running:

ant validate-javascript

which will give an output similar to this:

validate-javascript:
[jsvalidate] /Users/ariya/ant-jsvalidate/src/invalid.js:
[jsvalidate]   Error: Line 1: Missing catch or finally after try
[jsvalidate] /Users/ariya/ant-jsvalidate/src/strictmode-invalid.js:
[jsvalidate]   Line 3: Octal literals are not allowed in strict mode.
[jsvalidate]   Line 4: Parameter name eval or arguments is not allowed in strict mode
[jsvalidate]   Line 5: Parameter name eval or arguments is not allowed in strict mode
[jsvalidate]   Line 6: Strict mode function may not have duplicate parameter names
[jsvalidate]   Line 7: Parameter name eval or arguments is not allowed in strict mode
[jsvalidate]   Line 8: Function name may not be eval or arguments in strict mode
[jsvalidate]   Line 9: Function name may not be eval or arguments in strict mode
[jsvalidate]   Line 10: Use of future reserved word in strict mode
[jsvalidate]   Line 10: Strict mode code may not include a with statement

If you open build.xml, here it is obvious that validate-javascript is the target which uses jsvalidate task to run the syntax validation on every *.js files under a specific directory. Obviously, you can tweak it to suit your application configuration.

The implementation of jsvalidate task itself is very simple, just about 50 lines. The spirit its very much the same like the command-line tool esvalidate (part of Esprima). Given the file set, read the content of every file, check the syntax, and shows the errors (if any). Esprima code is loaded by reading lib/esprima.js and evaluate it. The included report is minimalistic but informative. If there is at least one syntax error, the task will be marked as failed. As an exercise for the reader, tweak the task so that you can output the validation result in the format of JUnit XML.

Who says Java and JavaScript can’t live together in harmony?

Tags:

Achieving a good code coverage is a useful practice in today’s software craftsmanship. For JavaScript applications, whether it is for the browser or for the server, many tools to check the statement coverage are available. What about branch coverage? Fortunately, such a tool is finally available: Istanbul.

Made by Krishnan Anantheswaran from the YUI team Yahoo! Cocktail team, Istanbul is extremely easy to use. It is suitable for both browser-based instrumentation or Node.js application analysis. Under the hood, Istanbul uses Esprima to parse JavaScript code and Escodegen to generate the instrumented version of the code. Istanbul is pure JavaScript, there is no native code or other kind of native libraries wrapper involved.

Istanbul requires Node.js, the package can be installed as:

npm install istanbul

Using Istanbul with command-line Node.js application is fairly straightforward. Assuming you have test.js like this:

x =42;
if(false)
     x =-1;

We can analyze the coverage by running:

istanbul cover test.js

which gives the following outcome:

=============================== Coverage summary ===============================
Statements   : 66.67% ( 2/3 )
Branches     : 50% ( 1/2 )
Functions    : 100% ( 0/0 )
Lines        : 66.67% ( 2/3 )
================================================================================

Even if you put all the above code in just one line, Istanbul can still give the correct coverage result. This is because Istanbul does not work based on line-by-line coverage, it does fully understands JavaScript syntax. Beside the quick text-based report, Istanbul also produces the coverage report in LCOV format. This way, the coverage report can be nicely shown, with color coding and other fancy features:

What about something more complicated? I wrote some time ago about the trap of checking only statement coverage, the example which demonstrated that is the following fragment. Now, if your unit test only verify the result of running inc(4) and you forgot you also need the check for inc(4,2), you won’t see the bug easily. This example is of course just an oversimplified example, in real-world application the problem is much harder to spotted.

function inc(p, q){
    if(q ==undefined) q =1;
    return p + q/q;
}

However, if we run Istanbul so that we can see the branch coverage, the report reveals the issue. Here the marker ‘E’ indicates that the else path of the branch is never executed and that should provoke a suspicion.

How does Istanbul work under the hood? It takes a JavaScript program and passes it through Esprima to get the syntax tree. Then, it injects some instrumentation by wrapping various syntax constructs. After that, a new JavaScript program is generated from the syntax tree by using Escodegen. When the program runs, the injected annotation is also executed accordingly and thereby the statistics of the program execution can be gathered.

While Istanbul has a mechanism to automate running Node.js application with instrumentation, nothing stops you from using the instrumented code in other JavaScript environments (such as web browsers). For this purpose, Istanbul has a special instrument command to perform only the instrumentation. It is up to you to process the coverage hooks and reports.

With Istanbul, tracking JavaScript code coverage has never been easier!

Tags:

Performance optimization of web applications is a hot topic these days. One of the related areas is of course optimizing the application code itself. For client-side application running in the web browser, this means speeding-up JavaScript code whenever possible. Premature optimization is not a good practice, it is crucial to locate which parts cause the slow down and need some improvement. Enter the logical first step of every optimization: initial performance analysis.

Sampling

Are you familiar with a JavaScript profiler? Many modern browsers already include a very useful profiler to look for JavaScript performance problem. The workflow is like this. First, you press a button to start the full performance monitoring of your application. After the application runs for a while, you can press another button to stop the monitoring. The outcome is something top-down like the following screenshot, the breakdown gives a very useful information on where your application spends the most time.

Under the hood, activating the monitoring causes the JavaScript engine to kick an sampling profiler. It is named that way because the profiler will look at the state of the virtual machine at a predefined interval, e.g. 1 ms in case of V8. The important state information will be collected and later it will be used to construct the profiling view as depicted in the above screenshot.

When carrying out a profiling like this, be advised of the observer effect. The extra monitoring adds a certain overhead to the code execution and hence, the actual timing would be different to the case where there is no instrumentation at all. The difference is usually minimal, in particular since the entire application is affected. Yet, take that into account as you move forward to make any conclusion.

Tracing

While timing information obtained from the profiler is useful, sometimes you are also interested not in how fast a certain operation is carried out, but also what happens during that time. This is like doing an X-ray on your program execution. Fortunately most modern browsers support the console API console.trace will give you exactly that information:

Another way to gather the traces is by instrumenting the JavaScript source. This is a technique I’ve used to find out the exact execution sequence when an application starts. For example, in that experiment I found out that a simple jQuery Mobile site will invoke over 4000 function calls. Note that the number of calls itself does not tell you much. However, tracking this over time, or even for every check in, can be really helpful. For example, if suddenly someone commits a bug fix which brings the function calls to 8000, this should trigger a red flag. That can be one of your protective multilayer defense.

Scalability is another excellent area of application tracing. If you have an address book application, sorting the contacts the alphabetically can be really fast if you only have 10 entries. However, here you are not interested in the absolute time of the sorting. You also want to know how it handles the address book with 100 entries, 1000 entries, and so on.

Formal analysis of the complexity can be complicated or prohibitively expensive. This is where empirical run-time analysis kicks in. For example, you can instrument Array#swap and plot the number of function calls vs address book entries. If your team member implemented it using bubble sort instead of something faster like binary sort, that chart will reveal it.

Timing

After you locate the problematic spot in the performance, the next step is obviously to fix it. In many cases, speeding up some parts of the application is not really difficult. In other cases, you have to try different strategies and see which one fits the performance criteria. Often, it is as simple as figuring out which implementation is the fastest. This is where timing the execution of a function is useful.

Accurate timing is far from trivial, this has been covered in many articles, e.g. Bulletproof JavaScript benchmarks. Unless you have a lot of time to learn statistics and uncover cross-browser secrets, it is easier to use a ready-made benchmark library such as Benchmark.js. For a quick comparison, using the popular JSPerf (which uses Benchmark.js under the hood) is highly recommended. You would also have the chance to try it on different browsers and devices, just to ensure that your strategy is not biased towards a particular implementation.

Beside careful timing, it is also important to pay attention to the benchmark corpus. Whenever possible, choose something which resembles its real-world usage. For example, if you try different ways to sort the contacts in the address book application, make sure you supply a representative list for the benchmarks, more than just a useless array of ['a', 'b', 'c'].

Last but not least, remember that optimization is not the destination, it is a journey!