The Story So Far

I’ve been enjoying responses to Crystal Beasley’s post about how she got into tech/development. It got me thinking about the diversity of backgrounds and paths people take to progamming and tech work; I know it never ceases to amaze me. Here’s my story.

Bottle light update

I’ve been working on variations of the Joule-Thief -based bottle lights I’ve been making. I made a couple using strip board for the through-hole components but its clunky. Better yet would be SMD components stuck directly onto the structure…

Thoughts from Mozilla Summit 2013: Its about the Goal

This past weekend I was in Toronto for the Mozilla summit. It was one of three venues where mozillians - staff and volunteers - gathered to talk about the Mozilla project, what we’re doing, where we are going and most importantly, to meet members across the breadth of the community.

I started at Mozilla almost 2 years ago now, when I joined to work on the now-shelved Pancake project. Now I work on Firefox for Metro. I had at least dim awareness of all the projects and intiatives discussed over the last few days, but a few things were brought home to me. One is that success - which I’ll define as an open, universally accessible web - is far from assured. In many ways the open web is a solution to a problem lots of people don’t know they have, and as such it is vulnerable to erosion through public apathy as much as commercial and governmental influence. The right to a free and open platform for publishing, sharing, doing business and all the other ways the web has become critical infrastructure for our society - is not written or enshrined in any law. It is a thing we must all work at preserving and building.

Furthermore, Mozilla is just one of many communities that share these values. While we must compete with software giants, we must shouldn’t resemble one. We must guard against sacred cows and not-invented-here syndrome. We must proactively reach out and connect up with groups that share our values and vision, and frame our work as a collective effort, not a “Mozilla project.” This is especially true when many people only understand Mozilla to be a software company that produces a browser; nuances like it being a non-profit, mission-driven open source project can get lost in the mix.

Seeing the open web vision being driven forward by so many people, across so many countries and in so many ways was invigorating though. I’m proud to be playing a part in this and look forward to the future we can build.

Remove the blockages that keep IE6 around

With all the MS bashing and kill-IE6 sentiments I was wondering what are the actual impediments to upgrading? For the most part it is legacy applications in organizations that have no upgrade path. Stuff like timesheet apps, expense reporting and so on that was written eons ago that is critical to company operations, but has little or negative ROI to replace or fix.

Sure, there are cases where IE6 is in use simply because it was the browser that shipped with XP. Lets put aside the cost and difficulty of operating system upgrades, and focus on the part of the problem we can conceivably do something about. What prevents deployment of IE8 to these desktops? What compatibility problem with which applications are complicating this problem? Is there anything we can do to smooth the path to browser upgrades?

What’s needed is an audit. A big ugly audit of all the gnarly sticking points that IT organizations are faced with which cause the issue to be punted everytime it comes up. Odds are good that there are reasonable solutions to at least some of these problems if we only knew what they were. Perhaps its an upgrade or alternative with a tried and true migration path. Or just a simple code shim that can provide backwards-compatibility. I’m not discounting the ripple effect even a one-line code change can have, the risk and cost of regression, but we can offset that by connecting people in the same boat, by sharing gotchas and tried and tested solutions.

Imagine a clearing house kind of site that lists the offending applications & implementations and details the IE6 dependencies. The audit is crowd-sourced, built by the motivated individuals in every organization that deal with the problem every day but are powerless to fix it. Each problem once itemized, prioritized by the number of IE6 installs depending on it and paired with suggestions, known alternatives, actual patches and even bids or volunteers to fix it. It would be a pragmatic approach to unsticking the development of the web, as well as “naming-and-shaming” the sticking points. In the web development community we all share the burden of the continued existence of this browser, yet we are powerless to fix it. With information comes power.

Community pressure on browser vendors to support standards in their future browsers has started to yield results. But for the legacy browsers - to-date we’ve had a strategy of sitting and waiting. IE6 usage is dropping slowly but surely and for some the end is in sight - it is approaching the threshold where they can officially drop support. For many though this is still years away. What can we do to help?

AIR command line arguments

I’ve been working on the next release of the Dojo Toolbox - which is an Adobe AIR app, using the Dojo Toolkit. I’m taking a TDD kind of approach to get on a better footing for evolving this thing, and needed a quick way to run a particular set of unit tests.

I wanted to be able to do something like this:

$ adl runTests.xml testModule=toolbox.tests.SomeThing

Getting command line arguments in AIR is via the invoke event, it looks something like this:

air.NativeApplication.nativeApplication.addEventListener(
air.InvokeEvent.INVOKE, function(evt){
window.scriptArgs = getScriptArgs(evt);
}
)

…But when I tried it, I just got a console error:

initial content not found

It turns out that command line arguments to an AIR application are expected to be filenames - like if you dropped a file onto the app’s icon. To pass through parameters and switches you first need

1
--
, like so:

$ adl runTests.xml -- testModule=toolbox.tests.all

The event your handler is passed has an arguments array property, and from there its straightforward to process what you’ve got to do the right thing. I’ll get more into how I’m doing the unit tests in another post, but as this took a little digging I thought I’d share.

A rhino prompt

I’m tinkering with another ill-conceived friday night project that may or may not see the light of day. But in the meantime, I just put together this little snippet that illustrates a lot of what’s to like about rhino:

var getInput = function() {
var br = new java.io.BufferedReader(
new java.io.InputStreamReader(java.lang.System["in"])
);
return br.readLine();
};

var greetUser = function() {
// use out.print for the prompt
// instead of rhino's print - which is really println
java.lang.System.out.print("Your name? ");
var name = getInput();
print("Hello " + name);
};

greetUser();
quit();

Arguably (and laughably if that’s your attitude) there’s exactly nothing special here - a whole lot of lines of code to do what in a browser (not to mention any other self-respecting scripting language) is done with one:

alert("Hello: " + prompt("Your name? ", ""))

But the point is that Rhino doesn’t provide a prompt function, and it doesnt matter because you can easily make one. I’ll take flexibility and potential like this over cute predefined functions every time.

Setting up Rhino

I've been using the Rhino engine more and more to run command-line scripts, fiddle and try things out. But my setup has taken shape slowly, and it wasn't much fun to be honest when I first got started.

I'm on a mac (Leopard), and here's how I've got it now:

  1. Download the Rhino .jar file, you'll find it inside the latest (binary) release.
  2. Drop it in your {user}/Library/java/Extensions folder (create it if it doesnt already exist). That way its automatically added to your classpath whenever you run java, so no need for -jar cmdline params to pull it in (and the classpath insanity that brings).
  3. I made a shell script to invoke rhino and aliased that, but actually you could simply alias the one-liner it contains:
    1
    java jline.ConsoleRunner org.mozilla.javascript.tools.shell.Main "$@"

    To make an alias, in my ~/.profile I've got the following:
    1
    alias rhino='~/utils/runjs.sh'
  4. Now, in your terminal, you just type '
    1
    rhino
    ' and it puts you into an interactive shell where you can load files, write js statements and see the results instantly.

But, Rhino's shell is frankly, a crappy user experience. Its got no history, no cursor movement at all. You can just type and hit enter. If you screw something up you have to type it all over again. And the whole beauty of writing *javascript* like this is that you can load a .js library repeatedly as you work on it and try calling its functions. But its a PITA out of the box.

Look again at that java cmd-line I'm using to run rhino and you'll see its using jline. This enlightening post on Taming the Rhino finally brought happiness to my rhino shell by introducing me to jline

You download jline and again, drop the .jar file into your Library/java/Extensions folder. Now the interactive shell is much more shell-like. You have a history on the up arrow, you can back up and move around the current line to edit, and do more scripting and less typing in general.

To run a particular .js file and exit, you do '

1
rhino yourfile.js
'. Further cmd-line parameters populate the
1
arguments
object in your script, so
1
rhino script.js filename1 filename2 myoption=true
would populate
1
arguments
like this:

[
filename1,
filename2,
myoption=true
]

FWIW I use a pattern like this to wrap my script body:

(function(scriptArgs) {
function main() {
// process scriptArgs,
// e.g. split on = to get name/value pairs
// and populate an options object
}
main();
})(Array.prototype.slice.apply(arguments));

Back in the shell, you can load, try, load again, try again:

$ jeltz:trunk sfoster$ rhino
Rhino 1.7 release 1 2008 03 06
js> load("lib/docblock.js");
js: "lib/docblock.js", line 7: uncaught JavaScript runtime exception: ReferenceError:\
"lang" is not defined. at lib/docblock.js:7 at lib/docblock.js:5 at <stdin>:2

js> load(“lib/langUtils.js”);
js: “<stdin>”, line 3: Couldn’t open file “lib/langUtils.js”.
js> load(“lib/langUtil.js”);
js> load(“lib/docblock.js”);
js> var p = docblock.getParser();
js> p.parse(“/** @author sfoster */“);
TAG:author:sfoster
js> quit();
jeltz:trunk sfoster$

Try it, I think you'll like it.

Barcamp Liverpool

I took in the first day of BarCamp Liverpool. It was Liverpool’s first, and my second, and went off well I thought. I learnt some things, saw some new and familiar stuff and felt it was time extremely well spent. It was great to see people coming out of the woodwork and talking about what they are doing.

There was much talk of iPhone apps, and the economic opportunities (or not) that presents for the developer, lots of startup hobnobbing and general feel-good about being in the industry. Something was missing though, and I’ve been trying to put my finger on it. In the evening there was a partly-for-fun “pitching” event in which people presented startup ideas to a panel. I think it was significant that the idea that got everyone most excited about was a hardware project - to monitor power consumption of a device at the socket and chart and aggregate data to build consumer awareness of energy usage and perhaps drive usage and purchase decisions. The Web2.0 narcissism is wearing thin I think - the web is maturing as a platform for real work and useful stuff to take place, but it needs more of this grounding in the practical, tangible and meaningful. I hope future barcamps and other events are able to draw more from the “fringes” of the web community, where it less about web technology and culture as a topic in itself, and more about the internet as a component in projects that touch peoples lives in tangible and practical ways.

My talk (in direct contradiction to all that) was on maturing client-side development techniques and practices, to introduce more rigour to the discipline. It was a response to the need for repeatable, reliable client-side output that is highlighted by ever more complex demands in web-based UIs. The front-end is a part of a product development process that needs just as much attention as server-side development, and as Steve Souders has being pointing out, in lot of cases, when you actual break down the experience from the user’s point of view - warrants more.

I introduced a few techniques and tools for testing and profiling client-side tech, but the topic was too big to fit in the 45 minute slot and probably left more questions than answers. I need to either break it out into complementary pieces or take a different approach to a high-level overview. My slides are posted to geekup though, and if you were there or have thoughts, please comment.

String repetition in javascript

This is about a little snippet I came up with the other month, while a colleague and I were talking about string building and its performance in javascript. I was looking for a neat way to front-pad or indent a string, and missing the

1
x
operator in perl.

It turns out there is a succinct, one-line idiom:

var indent = new Array(10).join(" ")

That gets you a 9-spaces-long string. Using the formal Array constructor (rather than the array literal

1
[ ]
) you can specify what the initial size or length of the array should be, and we leverage that when joining our otherwise empty array. The string we provide to
1
join
with ends up being repeated n-1 times. Cute huh. It also turns out to be pretty fast. Not quite as fast as the equivalent loop using += to build the string, but much faster in many cases than pushing each character into an array and joining to produce the string.

Of course if you already know something about what string you are looking to create here, its definately fastest to declare a long string like

var spacePadding = "          ";
and then
1
var indent = spacePadding.substring(indentLevel)
, and cross your fingers that spacePadding will always be long enough. That’s going to be a pain, though, when you need to output something like
»»»»level 1
»»»»»»level 2

Or, worse (or better) if you need to repeat something like

1
<span class="indent">
. Its trivial with our
1
join
trick:

var indent = new Array(indentLevel+1).join('<span class="indent">');

You can see the test file I used to time various options. new Array(n).join performs worst when n is a small number - like 20 - and its a short or single character string you are repeating. Frankly, for the use case I’ve outlined - front-padding something - that’s also a likely range. As you scale up, and start repeating 100s or 1000s of times, and also increase the length of the string you are repeating, then this margin disappears.