28 May 2008 - 8:39Edit Middle Add-on for AwesomeBar

I’ve made a simple add-on to let you see results immediately when you fix typos or edit search terms in the location bar. The difference from what you get in Firefox 3 is that with this add-on, you’ll see results when editing in the middle.

For example, if you accidentally type “mozzilla” you can correct the typo to be “mozilla” and see the pages you were looking for right away. Or if you type “addons” but meant to type “add ons”. Or maybe you searched for “ginger carrot cake” [dria.org] and want to search for “orange carrot cake” instead.

Edit Middle Add-on

Fixing “midle” typo to “middle” instantly shows results

Download Edit Middle [addons.mozilla.org] from the add-ons website or use the add-ons search from within Firefox 3. “Edit Middle” works for Firefox 3 including those using release candidates as well as nightly builds.

Very helpful for those with less than 100% keyboard accuracy!” “Search relies on keyboard input and typos are a fact of life; this just makes the smart location bar that much smarter.” – bharuch2, Harlequin99 [addons.mozilla.org]

Thanks everyone who helped test, provided feedback, and reviewed my first add-on. 🙂

18 Comments | Tags: Add-on, AwesomeBar, Mozilla

15 April 2008 - 22:45A Different Development Process

It seems that Mercurial and Mozilla have quite different patch/review process, but then again they’re two very different projects. I just found out today that Bug 394650 – Make line numbers linkable when viewing files/annotate for hg.mozilla.org [bugzilla.mozilla.org] was “works for me.” I was confused for a little bit; but yes indeed, annotate/changeset views on hg.mozilla.org have linkable line numbers for each file… just like how I would have coded it. 😉

Turns out that the patch that I sent in to the dev list ended up making it in to Mercurial 1.0 [hg.intevation.org]. No official reviews, no comments. They just checked in the patch to their “crew” (trunk) repository and let it bake for several months. Seems like nobody complained enough to have it backed out and here it is now in Mercurial 1.0 as we can see on hg.mozilla.org.

But this post isn’t about the differences between Mercurial and Mozilla. It’s about the current Mozilla CVS development process vs Mozilla with Mercurial.

One main difference is changesets. Instead of having a separate version number for each file as in CVS, all related changes are grouped together for a changeset. These are the steps one needs to do right now to see all related changes of a patch: 1) use mxr to find the file you’re editing 2) switch to blame to find the checkin 3) click the bug number if provided 4) hope there’s a clearly marked patch as the one checked in to see what else was changed. 🙁

With Mercurial, you can just look at the changeset which contains everything; e.g., patch to not need to click the page to use gmail keyboard commands [hg.mozilla.org]. Additionally, now with my patch for showing line numbers in changesets, you can link people to a specific line in a patch [hg.mozilla.org]. This could be useful if you need to point to a particular line in a bugzilla comment about why it broke something. Or especially useful with a stack of patches on mq and you’re collecting feedback on it from other people.

Another aspect of changesets is that there’s a “global version” for the whole repository. You can jump back in time to an earlier revision and view the whole repository as it was before a particular patch was checked in. We currently have something like this on a per-file basis with bonsai, but you need to do so much more work to look at “the right version” of other files. E.g., going back to when adaptive learning was checked in [hg.mozilla.org], you can see that the autocomplete was still only emphasizing the first match in the url and title [hg.mozilla.org].

Of course, you can just use the mercurial web interface to view the latest version of the file. Just take http://hg.mozilla.org/cvs-trunk-mirror/index.cgi/file/tip/ and append the file you want. (Normally “tip” would be a changeset/revision hex number, but you can put in “tip” because it’s an alias (tag) for the latest version.) And from there, you can look at the whole patch for the current version (changeset), browse the checkin history of that file (revisions), or look at the blame (annotate) [unfortunately it doesn’t have checkin comments on hover yet].

Typing out that whole url might be cumbersome, but good thing we have the AwesomeBar with multi-word search on word boundaries (with camel case) plus adaptive learning. 😉 “hg. auto” [hg.mozilla.org]

I’m not sure how distributed the development process will become for Mozilla, but these neat tools provided by default with Mercurial will make it easier to track changes and refer to them in bugzilla comments or over IRC. (Oh, and if you’re using mercurial and haven’t looked into mq yet, you should do so. It’s a great (builtin) extension to track/reorder multiple patches that you’re working on. And for those curious how I send changes for try-server builds, I apply the stack of patches and hg export firstpatch:lastpatch > combined.patch 😀 )

4 Comments | Tags: AwesomeBar, Development, Mercurial, Mozilla

8 April 2008 - 8:53Awesomeness in Beta 5

I’ve been busy preparing for a conference talk, so I didn’t get around to reporting AwesomeBar improvements for Beta 5 sooner. (But for those curious, I presented Branch-on-Random [pdf, uiuc.edu] at CGO 2008 [cgo.org] (Code Generation and Optimization). Basically, it’s an instruction that’s really cheap to implement and allows for a factor of 10 times less overhead than traditional sampling techniques. I think it went well, and I even got asked during Q&A.. “When can I buy one of these?” 🙂 )

As we’re winding down to ship Firefox 3, there aren’t as many more big features, but there’s still some useful changes in Beta 5 in terms of functionality, display, and performance. So those of you who have installed extensions to make the auto-complete smaller might want to turn it off to try out the new look.

Functionality

To better accommodate people’s expectations of results in the auto-complete, there are frecency tweaks to better prefer pages you’ve typed — by default, before adaptive learning. This helps address concerns that the top level site’s main page should appear high in the list because typically people are typing in the domain.

Another common complaint is that results seemed to be returning useless results when typing 1-2 characters. This stemmed from results being matched in the middle of words instead of at the start of the domain, for example. The adaptive learning helps avoid this problem because you’re typing words and selecting results that matched the word you wanted. The learning system then knows to show that selected page over others when you just type a single letter of the word — effectively showing a result that matches at the beginning of the word.

So to improve things for Beta 5, words that you type in the location bar will try to match on word boundaries e.g., matching after a forward slash or space. This even works for CamelCase (capitalizing the first letter of words instead of putting spaces) which is common for wikis.

Word boundary matching

Searching for “wik m” matching on word boundaries

Display

The first thing people will probably notice is that the list doesn’t feel as overpowering anymore. The number of results shown on the screen has been reduced to 6. Additionally the font size of the title text is smaller which felt unnecessarily large on some platforms like OS X. Ideally, the fewer number of results will help users scan results quickly instead of feeling overwhelmed. Combined with better functionality of multi-word search, adaptive learning, and word boundary matching, finding the page you want should be a happy experience. 🙂

Another set of changes is for how words you type get emphasized. Instead of only showing the first match in the title and url, it’ll emphasize all matches. Additionally, it’ll show matches when you type multiple words as well, so each word gets emphasized instead of nothing at all. For browser skin designers, there’s a new css class to alternatively emphasize matches, but the main purpose is to avoid styling bold which breaks common ligatures in some languages.

Emphasize islam

Bold/underline for english, just underline for ligatures

Performance

There has been improvements in browser responsiveness in Beta 5, so now it no longer eats up all of your CPU power for every letter that you type. In Beta 4, every single letter you typed caused the browser to start searching through your whole history

To optimize for users typing letters one by one for a whole word, we now reuse the results that are currently being shown in the list as well as continuing the search from where the last one left off. This has 2 main effects outside of reduced CPU usage: 1) existing matching results show up immediately instead of disappearing momentarily then reappearing and 2) not-as-frecently visited results can be found faster as you continue to type.

CPU Search Usage

CPU usage when searching in Beta 4 and Beta 5

The picture shows a CPU usage graph where high bars means the CPU is doing a lot of work (and potentially not letting it update the UI). The horizontal axis is time and each set of 5 bars shows the 5 seconds after typing a letter one by one. So comparing the two graphs, we find the same results with a lot less work.

As an informal poll, I was wondering how many people are using the unofficial tryserver builds that I’ve been making. There’s some features like showing keyword searches, restricting searches, etc., that might not make it into Firefox 3 final, but I could potentially start a build near ship time, so you can get Firefox 3 + some extra awesomeness.

15 Comments | Tags: AwesomeBar, Conference, Mozilla

31 March 2008 - 9:18Why You Should Write Unit Tests

Requiring unit tests for code review isn’t the greatest motivation for people to write unit tests. Sure, it tries to make sure unit tests are written, but it doesn’t give the reason to write them.

In general, I like to ask “why?” to figure out why things are done, why they should be done, what are other ways to achieve the same goal?

I don’t remembering ever getting an explanation on why there was a requirement. I suppose the obvious answer was that we now have a testing infrastructure, and we don’t have many unit tests, so you need to write them. But still, that’s not a great motivation for writing tests.

So, why should you write unit tests?

  1. Make sure your code does what you want it to do
  2. Speed up development and optimizations/refactoring
  3. Create better interfaces and functionality
  4. Get other people to use your contribution
  5. Make sure nobody else breaks your feature

This isn’t an exhaustive list, but these are things I’ve noticed from my own experiences.

Make sure your code does what you want it to do. The first reason is somewhat obvious, but it’s effect isn’t. I believe one big benefit is that it lets you change how you write code. Specifically, it speeds up your development in that you don’t have to completely think through what you’re doing. That might not sound too great, so I’ll try to give an example.

When working on word boundary matching for the AwesomeBar, I had automated unit tests set up with a set of pages and a set of searches, and it made sure searches matched on word boundaries (like spaces, dots, slashes and not after other characters). I needed to write a string processing utility that matched on word boundaries that would work for standard word boundaries as well as CamelCase and not break search for ideograph languages like Chinese.

I was never one for too much theory, so instead of sitting around and explicitly drawing out all the boundary conditions, I made simple code changes, recompiled, checked if the tests passed. Instead of sitting around for 10 minutes thinking deeply about how to deal with multiple word boundaries in a row, I made a 1 second change and ran the test to see that it passed.

The point there is that you can spend less time trying to reason about if the code will do what you want and just let the computer automatically do the checking. You already specified what the code should do with your test, and the computer can quickly make sure that they pass. This also relates to speeding up development (or perhaps avoiding my impatientness) because I don’t need to go through the long process of firing up a debug build to make sure my manually typed search terms find the expected pages — I don’t even need to make sure I have the right profile with the right set of test pages.

Speed up development and optimizations/refactoring. I mentioned speeding up optimizations and refactoring, but the former is basically a special case of the latter. Both tasks are making changes to the code without changing functionality. With automated unit tests set up, you can be sure that your refactoring changes don’t break expected functionality. For example, as I was optimizing the AwesomeBar to go faster and use less CPU cycles, I relied on the unit tests to make sure searches still provided the same list of urls.

In fact, one of my unit tests caught a bug in my first optimization because I forgot to check for javascript: URIs. The optimization reuses previous search results if the new search begins with the same text as the previous one, but we also do some special processing for javascript: URIs. Namely, we don’t show javascript: results unless you explicitly type out “javascript:” at the beginning of the query. So if you were searching for “javascript” and then typed “javascript:”, the optimization wouldn’t have shown any javascript: URIs because the previous result couldn’t have contained javascript: results.

Create better interfaces and functionality. Good APIs are fun to test. I enjoy writing AwesomeBar tests because I just need to provide some search words and a set of expected results. Simple. But you can also have better functionality because the process of writing tests makes you a user of the API. You start thinking about “what else” or “how could this be better.”

For a might-not-make-it-to-Firefox-3 feature of being able to restrict results to non-bookmarked pages or forcing matches on the url (by default), I wasn’t sure at first how things should interact if you have multiple “restricts” or “matches”. By writing the unit tests, I was able to easily look at all possible combinations such as “must match url and must match title”. Because I was writing the test, I noticed this potential issue and got it clarified; otherwise, it might have remained a not-well defined feature.

Get other people to use your contribution. I like to learn by example, so if I want to use something that I don’t know how to use, I search for existing uses of it in the codebase. A good description of a class/method is nice and all in the interface description, but seeing it actually used is much more helpful for me. Ideally test cases are written to test representative usages of a feature, so someone looking at the test code should be able to reason about how they should use the interface.

I’ve written up a couple unit tests for the PluralForm module, and they serve as additional examples of how to use PluralForm. I’ve written up some PluralForm documentation [developer.mozilla.org] on how to use it in Firefox and extensions, but without the unit tests, someone searching for PluralForm would have to rely on the current usage in the Download Manager. And relying on that would make things more confusing as one would have to look through a lot of unrelated-to-PluralForm download manager code.

Make sure nobody breaks your feature. You just worked really hard on adding a new feature. You don’t want it broken. I suppose an alternate motivation is that the blame goes to whoever breaks your test. If you didn’t have the test, potentially you would be stuck fixing it some weeks/months later. Also, with unit tests, it’s easier to see how the code is being used, so the person breaking the test should be able to fix it faster.

Tests aren’t just “for the future.” They help fix things now and help you go faster. And if you’re doing a lot of development and frequently touching the same piece of code such as having a huge stack of patches for a single file, unit tests help make sure patches can be applied without other patches, and if not, you know it wasn’t going to be safe to “cherry pick” a patch out of the stack and check it in.

I’m sure there are other benefits of writing automated unit tests, but I think this is a good starting list of motivations. Hopefully better than “why didn’t you write a test?!” 😉

1 Comment | Tags: AwesomeBar, Development, Mozilla