Category Archives: Launchpad

Common mistakes that broke Launchpad’s browser compatibility

At this moment, Launchpad is providing all features to Opera, Internet Explorer (IE), and many other browsers. Many features like bug listings, bug tag auto-completion, changing bug status and privacy, choosing people, and editing subscriptions were broken in many browsers. Some features were broken for years because developers mistook their inexperience for something broken these browsers.

I am summarising what was wrong with Launchpad and how to avoid repeating the mistakes of the past. Launchpad reviewers, I urge you to read this so that bad code is not merged into Launchpad’s trunk again. Launchpad engineers commonly work with Firefox and Chromium, two browsers with great support the latests technologies, These browsers are also very good at correcting mistakes in markup, CSS, and JavaScript. The lesser browsers are less forgiving; developers must fix their mistakes and on rare occasion write alternate code to make a feature work. Launchpad developers were too quick to blame the browser. They failed to recognise their own inexperience, and they failed to find the root cause of the problem.

Why Do We Want to Support More Browsers?

One user, lazarus, responded to my A tale of two travesties post asking “why bother with IE? Those 4% of users should switch to a *DECENT* browser.”

Canonical’s partners often run older releases of Firefox and Chromium. Some partners are running IE. Their staff cannot install software onto their computers, they have no choice but to use the corporate browser. The people who help build Ubuntu, who help Canonical enable Ubuntu to run on new hardware, cannot use Launchpad to do their job.

Consider users who use their phone or tablet with Launchpad. These browsers are also locked down, and they are commonly older versions of browsers. There were several bugs in the past that prevented Canonical staff from using their phones to login to Launchpad. They, even myself, had to find another computer to respond to a notification received via phone. Mobiles devices are now commonly used to work on the Net; Launchpad risks loosing users and projects who can choose another service.

Servers often do not have a GUI. We assume Ubuntu server is running headless. Servers also tend to be LTS installs that might can be 2 to 5 years old. Tasks such as reporting a bugs, updating it, and adding a comment must work in a text-based browser without JavaScript.

What is the Cost of Supporting More Browsers?

Again lazarus stated in his reply to my struggle to run IE in Ubuntu, “I’m really sick of seeing all those work-arounds just to make it work for that damn browser.”

I wrote less than 20 lines of code to Support IE, yet I removed more than than 125 lines that disabled it or other browsers. I Also removed about 200 lines of duplicate or alternate code from <noscript> elements. It takes fewer lines of code to support older and mediocre browsers than to not support them!

For every bug that was tagged as affecting IE, I discovered it also affected Opera, Konqueror, Firefox 3, and even the latest version of chromium. Fixing one bug solved an issue for multiple browsers each time. I found many bugs overlapped with or were duplicates of other bugs that were listed as a higher priority, yet remained unsolved. Understanding the root cause of a problem allows us to make a single change that fixes many things. Honestly, the most common way to fix an issue was to read the YUI documentation to learn what Launchpad was doing wrong. Thus, the root cause of IE not working is rarely IE itself…the JavaScript bugs in Launchpad are caused by inexperience.

Running other browsers can be difficult as I reported in my Travesty post. I now have a custom apache configuration that cannot be copied to other developer machines. Running Microsoft’s official IE developer images take all my available RAM. I also run the VM image from an SD card because Windows is still bloatware. Installing Konqueror and all the KDE dependencies can also be a problem if you are short on disk space.

The maintenance savings by writing good code that supports all browsers are diminished by the days or weeks it takes to install all the browsers to reproduce a bug. If I cannot reproduce a bug, I cannot fix it. For many Launchpad developers, the best way to not fix a bug in a mediocre browser is to avoid introducing the bug. This is why we use YUI as our JS library, it reconciles the differences between browsers. This is why we have code standards and reviews, to ensure that we agree the code is correct and maintainable. We want to recognise bad code before it is merged into trunk and we absolutely must avoid dangerous code,

The Last Sign of Inexperience

This example of code is dangerous and unmaintainable:

if (Y.UA.ie) {
    return;
}

This is the last sign of inexperience. Bugs have already been slipped past review, merged into trunk, and are probably in production preventing user from completing their task. Why is IE not using the feature? Which browser versions and YUI versions were tested? This kind of guard often has an associated comment like:

# Usual IE brokenness.

I think the comment can also be interpreted to mean: “I do not have IE installed, I do not trust it, I do not trust my own code, I do not understand YUI”.

Do not let this kind of guard merge. If one browser does not work, there are probably 5 other browsers, like those shipped with an Ubuntu LTS, that also do not work. This branch needs fixing!

Is This a Presentation Problem?

Several bugs fixed by William Grant and myself were not JavaScript bugs as was reported. They were CSS or markup bugs. These bugs were trivially fixed in minutes when shown to the right person, yet some of these bugs were reported years ago. Your chances of fixing a presentation problem with JavaScript is similar to painting a house with a hammer. If the UI for a JavaScript feature does not look right, or not render at all, consider a CSS or markup change.

Non-conformant CSS the most common cause of broken presentation. I often uses Wikipedia’s Comparison of Layout Engines when researching differences in layout. Even the latest versions of Firefox and Chromium have inherited defects from their layout engine. Firefox was showing a scrollbar because the form overlay buttons had a text-indent property set to twice the width of the page. Though Chromium did not show the scrollbar, I think Firefox was right in this case; I fixed the issue by setting a text indent that was a few characters wide. Many issues can be fixed using alternate properties or additional CSS selectors to add properties to the problem elements. For example, IE has poor support for visibility (introduced by Netscape in 1998), but has better support for display (introduced by Microsoft in 1998). IE was always showing the fields in the overlay forms that change the page. Though the form overlays were visibility: hidden, IE requires a specific selector for .yui3-lazr-formoverlay-hidden input to be display: none.

Experimental CSS can be both the cause and the solution to a display problem. We want Launchpad to look good, and we often use CSS3 to define the styles. Many CSS3 properties are not fully implemented in browsers, but there are vendor properties (ones with a dash prefix) that do support the presentation. Launchpad has many of these for Gecko and Webkit. We also need to add them for KHtml, Opera and IE. While IE does not support the CSS3 box-shadow property, it has supported shadows since 1998 and we added its vendor property to give all overlays shadows.

Invalid Markup breaks older browsers, but newer browsers are better at fixing (and hiding) markup problems. You can read about how browsers work in depth, but I think I can summarise the issue in a few sentences. When browsers discover an error while parsing the markup, they pause to fix the markup then carry on. For example, paragraphs cannot contain lists. Most browsers assume that the author meant that there is a paragraph before and after the list. If you query the DOM using JS, you may discover it does not match the source. When I switched the Launchpad test suite to use a webkit-based test browser many tests failed. Developers were ignoring test failures because they passed in Firefox. I traced the errors to existing bug reports and discovered code was creating invalid tables and Chromium fixed the markup differently than Firefox. IE is very prone to choke on malformed tables. The lesson is clear, write what you mean, or else browsers are free to reinterpret your bogus markup and topple your scripts.

Launchpad users will soon loose their last line of defence against invalid markup when Launchpad switches to Ubuntu 12.04. My squad stopped development a few months ago to learn why Launchpad’s ec2 test runner failed a test that passed on all the other test runners. The reason is because the script used bad markup that toppled the Ubuntu 10.04 version of my test browser. The new webkit library in Ubuntu 12.04 is better at correcting markup, hiding from mistakes from tests, allowing the mistakes to be released to break older browsers.

Is This a Structural Problem?

Structural problems are issues where the choice in markup is brittle or unmaintainable.

Noscript is BAD. Netscape meant well by introducing the <noscript> element, but it leads to maintenance burdens and it assumes that all scripts run perfectly. The intent is to have two implementations and do not diverge. They do diverge though, leading to differing and confusing behaviours. If the script fails to initialise, the user gets no behaviour. This situation was exacerbated in Launchpad with the use of the if (Y.UA.ie) guards that meant IE users never saw the HTML or JavaScript links to change project roles or change blueprints. Launchpad prefers, and YUI recommends, progressive enhancement; write simple markup that does not need JavaScript, then modify the page to add the scripted features. Scripts that replace or hide the HTML feature should do that as the last step; If the script fails, there is still a usable link.

Mutating parent markup while parsing is dangerous. Several widgets like the TextAreaEditor were mutating their parent element before the parent element had closed itself. Only the mad and the brave mutate the thing they are iterating over. Chromium and Firefox handled the insane situation with grace, but other browsers threw a wobbly. IE 8 could not render the bug page, it stopped at the bug description. This situation is hard to see in a review. In general the script block must be outside of the elements it changes, but several widgets enhance parent and grandparent nodes, which means the markup appears to have redundantly nested elements. Some of this madness can be averted by running the script on DOMReady. There are many scripts that load as the page is parsed; I suspect these could all be changed to run at DOMReady.

Is This a YUI Problem?

YUI also has bugs. Has this issue been reported in YUI’s bug tracker? Which version of YUI is Launchpad using? Does upgrading fix the issue? Maybe an issue needs to be reported?

There were several hacks in the Launchpad bug pages to load scripts during parsing or after the load event because DOMReady was buggy during YUI3 preview releases. Both Opera and IE had difficulty during running scripts during parse time, and running the scripts after the load event caused the page to flash. Launchpad has been running YUI3+ for almost two years, the hacks should have been removed. The code required a proper XXX comment to remind developers to update the scripts.

# XXX: 2010-03-12 bingo bug=234567:
# DOMReady is bug in YUI3 PR3. Test DOMReady again in YUI 3.0.

There was also a case where Launchpad ran a version of YUI that miswired the event handling in IE. Several if (Y.UA.ie) guards were added without a comment explaining the issue, nor a stating the bug number in YUI’s bug tracker. I do not know when when these issues were fixed, but they are fixed in YUI 3.3.

Is This a EcmaScript or DOM Problem?

Launchpad was created in the age of EcmaScript 3 (ES3). This is now the age of ES5, and Launchpad developers are using ES5 browsers like Firefox and Chromium. Browser that the developers once used to build launchpad stopped working. Launchpad stopped working with the browsers available to Ubuntu LTS such as 08.04. Launchpad developers use jslint and YUI to ensure that code works in old and new browsers.

Was the lint report ignored? Launchpad’s make lint command uses jslint to prevent known issues before they are merged into trunk. There are still a lot is issues reported in the old lazr modules that need fixing. We fixed coercion mistakes and unnested functions created in loops to address bugs in older browsers.

Which version of EcmaScript? There were a lot of failures caused by unsafe ES5 calls. William fixed many script failures in older browsers by ensuring that Y.Array() is called properly. It is very important to understand that Y.Array() returns a native array. This call is pointless:

var finklesnarks = Y.Array([]);

This call is dangerous because it creates a native ES3 array in older browsers, then calls an ES5 method:

Y.Array(finklesnarks).indexOf(fnord);

I was the author of some of these bad calls. The safe way to use ES5 array with YUI is:

Y.Array.indexOf(finklesnarks, fnord);

Are events happening in a different order? Are links doing both script actions and standard actions? YUI docs describe event bubbling, capturing is never mentioned. I thought this meant that YUI had disabled the capture phase of event propagation, simplifying how we work with events. No, this is not the case. Firefox and Chromium still prefer capture propagation, and IE uses bubbling propagation exclusively. Actions that work in the former browsers often have secondary, and wrong, actions happening in IE. This is because Firefox and Chromium are done propagating, but IE is just starting. Most Launchpad click handlers use e.preventDefault(), which means “stop the default action, continue propagating”. IE does continue propagating and unexpected things happen. A lot of Launchpad links work more by accident rather than by design. The correct method to call is e.halt() which stops the default action and propagation. We want to use halt() most of the time. In cases where we want multiple subscribers to respond to an event, we are using a custom event.

Does YUI docs demonstrate that the code will work? This is an odd point to check, but a lot of code was merged into Launchpad trunk without regard to YUI documentation. The bug status widgets did not appear on click in some browsers because they are designed to only display if you used the left mouse button. But YUI documentation states that the button can only be known in the mouseup event…the mouse property explicitly states that it is not for use with click. Removing the unsupported check of event.button fixed a bug that has been open for 3 years.

Is This a Broken Browser Problem?

These are the cases where developers must write code to reconcile the differences between browser implementations, or choose to not support the browser.

Non-conformant surprises are cases where browsers claim do support a feature but do not. Launchpad new bug listing UI depends on history management to sort columns and show batches. History management depends on URLs, but IE’s Link.pathname is missing the leading slash so URLs were not relative from root. The fix is trivial once you see the invalid paths in Launchpad’s oops reports and then look at the code that makes URLs. As we do in Launchpad’s python code, the method that wraps the pathname ensures there is a leading slash.

Alternate API nuisances are cases where the browser doesn’t support the methods the script uses, and neither does YUI. The bug tag autocomplete feature never worked in IE, but there was code checking for it. I first refactored the method to check for the methods Launchpad prefers, then checks for the alternate methods. This was hard to fix, I spent an hour reading about how IE creates selection ranges before I could write a 5-line block to do what element.endSelection does.

Unsupported nightmares are cases where neither the browser or YUI support the method. There is one case in Launchpad were this happens. The series timelines use canvas to draw the series, milestones, and releases. It was disabled for all IE version, but IE 9 does support canvas if the page states it is HTML5 . Instead of checking for browser version, I created a method that checks if the browser can create the canvas, and if so, the series timeline is rendered. IE 8 and below do not get the interactive image. Other browsers that I have not planned for will show the canvas if they pass the check.

How do I ensure a browser falls back to working code?

At this moment, there is only one guard that prevents KHtml browsers using a feature. There might come a time to add more guards because Launchpad, YUI, and a kind of browser do not work, and no one has time to make it work. We need to know the browser version that was tested and the version of YUI, for example:

if (Y.UI.ie < 6 && Y.version <= 3.3)

I think we want several experienced YUI developers to agree that this is the proper course before giving up though. When a new version of the browser or YUI is released, we know to check the feature. Does the guard need to be revised, or can it be removed?

Face painting and historical Web development

I spent my last two weekends working with ancient web technologies. Anne decided she wanted to update her Happy Faces web to attract more face painting business. I agreed to create a form for customers to inquire about rates and availability. The hosting service only offered Python 2.4,  CGI, and sendmail.

I really did not want to write a script that I knew others had written. I just wanted to make a pretty little form to help Anne. I found one library that almost worked.  I knew I could write a better library, and I would not trust any library without a test suite. I decided to write my own that would manage the request and response form, sending emails, and storing them if sendmail failed. I wrote a simple means to define a schema of what fields are in the form and how to validate them. The test module even provides a test web server that runs the CGIs you place in the root directory. This was a fine meditative exercise, but I would not describe it as fun.

I did have fun creating Anne’s contact form. Defining the schema for her form took minutes, and it was painless to make changes as we discussed what was optional and what the wording should be. The web page is not historical, it is very modern in fact. It uses HTML 5 form inputs and JavaScript to collect the information. The new  form inputs work in HTML 4 browsers like IE and FireFox, but HTML 5 browsers like Chromium and Safari see widgets that require less typing, less thinking about what to input.

I posted my CGI contact library on Launchpad for anyone who finds they need to work with historical technology.

Karma means action

I not only hack on Launchpad, I use it everyday for my personal projects and for the 1100+ projects I maintain as a registry administrator. I see hundreds of pages each week where my first question is “what has this user or project done recently”? Launchpad cannot easily tell me that, and what it does say requires interpretation. I am very disappointed. I think the most important information I need to see on Launchpad pages is an activity log.  I want to see something like a wall or stream presentation to understand how a person contributes to projects, what kinds of contributions are made, and is a project vital or dormant? My disappointment is compounded by Launchpad’s karma mechanism. I happen to know that “karma” is a Sanskrit word meaning “action”, which is not how Launchpad users or engineers interpret it.

I not writing an argument to fix Launchpad’s karma. It is fundamentally corrupt. Discussions about it become bike shed arguments. I like the name “karma” because I know it’s essential meaning, and that is all that I want to preserve.

For your edification, the value attributed to your action in Launchpad was arbitrarily set by an engineer, then a mechanism “balanced” the number against values in rarely used features.  These rules were created to in an effort to bring fairness to actions. We know that some actions help more people than other actions, but what is happening is that someone was awarded a tremendous number of points for some action that will never help someone else. For example, You can work for a year to build and release an app to earn 10 points, then Launchpad slaps you in the face when I register a blueprint that will never be implemented…awarding me with 300 points. Launchpad is misinforming you and everyone else about the value of your contributions. The numbers will always be subjective. Stop reading those karma numbers, stop trying to raise them; you will not win anything for having a high score.

  • I want to stop recording values for action, at the very least, never show them.
  • I want to stop expending valuable CPU time balancing karma.
  • I want to stop expiring karma.

Once we stop talking about value and fairness, we are free to add new kinds of actions that we want Launchpad to record. I hope to know that someone has registered a project, set the branch used as development focus, added a recipe to build it, and made an official release.

  • I want to see a listing of all the things I register or change in Launchpad.
  • I want to see a list of actions that someone has done today, this week, this month, this year, and maybe even last year.
  • I want to filter the actions by to specific categories that pertain to bugs, code, or planning.
  • I want see a link to the thing the action was about.

 

Misadventures with gnome Javascript

I recently updated pocket-lint to require gjs instead of seed because the latter has been 100% broken for 6 weeks. The best thing I can say about this experience is that I am very happy there are two competing implementations of GObject Introspection bindings for JavaScript. I am disappointed that the two implementations are not 100% compatible. Most of my changes to pocket-lint were to hide the deficiencies of gjc.

There are small but important differences between gjc and seed that developers will want to be mindful of. Gjs is older, based on Spider Monkey, and servers a simple need: JavaScript is the most common development language, and GNOME should support it. Seed is newer, based on Webkit, and serves subtly different need: I know JavaScript and I want to develop GNOME applications. Gjs works though you might not know it given the lack of documentation, and you might be disappointed to see that it recommit’s JavaScript’s original sin of namespace pollution. Seed is well documented and its extensions are in a separate namespace. Seed’s documentation is 99% compatible with gjs, so I can forgive the oversight. I learned missing crucial 1% of gjs by reading the C source. I was appalled to discover that gjs creates print, log, and argv functions in the global namespace. Seed, being an implementation for developers who really use JS, place the extensions in the Seed object.

I want to use seed, but given that it is broken in Ubuntu Oneiric, I decided to support gjs. I chose to check for the existence of the Seed object, and construct one from gjs when it is not present. The namespace is still polluted. The interpreters have different command lines, though they are similar enough for my purposes.

I think the GNOME community could do better by updating the gjs and seed to share the same command line, and add extensions to a common namespace, such as System. Thus an app that wants to call System.print() will not care about which interpreter is used. This permits developer and distros to choose the backend of their choice. It also lets us change our minds.

PS. I know that some developers want to use gjs to use the JavaScript advances developed by the Mozilla community, but this is a fools pursuit. JS has been fragmented since the release of IE 3.0 in 1996. JS developers know they have to write for a common language, and use libs to provide extensions. I am very aware of the failure of ES4. I hope Mozilla can get its extensions into the official language.

Creating a signed release file with setup.py

I recently created https://launchpad.net/lp-release-manager-tools for some videos I am making about how to use Launchpad. One aspect of creating a release is to upload the source tarball and a detached gpg signature verifying it. This is somewhat ironic, since lp-release-manager-tools exists to automate repetitive tasks that release managers do in Launchpad. I really do not like creating the signature. I cannot remember how to do it. I need to read the instruction on the form to upload the tarball each time. So I added a feature to my example project that any project hat uses python distutils can copy to make the signature with the source tarball.

I subclassed the sdist command and added an extra step to create the detached signature of the tarball. I then register the new command as signed_dist. This is the content of my setup.py:


#!/usr/bin/python
import subprocess

from distutils.core import setup
from distutils.command.sdist import sdist

class SignedSDistCommand(sdist):
    """Sign the source archive with a detached signature."""

    description = "Sign the source archive after it is generated."

    def run(self):
        sdist.run(self)
        gpg_args = [
            'gpg', '--armor', '--sign', '--detach-sig', self.archive_files[0]]
        gpg = subprocess.Popen(
            gpg_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        gpg.communicate()

setup(
    name="lp-release-manager-tools",
    description="Launchpad release manager API scripts.",
    version="0.0.2",
    license="MIT",
    maintainer="Curtis C. Hovey",
    maintainer_email="sinzui.is@verizon.net",
    scripts=['close_released_bugs.py'],
    cmdclass={
        'signed_sdist': SignedSDistCommand,
        }
    )

A Practical Guide to Bug Triage

Or: “Why I don’t classify bugs as medium”

The process of triaging issues (bugs, features, and tasks) has one crucial principle: Prioritise the work according to need and certainty.

Work is prioritised because there are not enough engineers to do all the work. Some features will never be completed, some bugs will never be fixed. Triage determines which bugs can and will be fixed, which features can and will be implemented. Need is generally understood, when planning work, but certainty is not, and that often leads to wasted work and unmet expectations.

By need, I mean a measure of severity. What percentage of users does the issue affect, and how severely does it impede them from completing their task.

By certainty, I mean a measure of how certain the engineers are that they can address the issue. Time is also a factor in this measure, the longer an issue takes to address, the more likely that the conditions that were first judged will change.

The act of triage is separating work into groups that are being worked on now, next and last. There can only be as many “now” bugs or features as there are engineers. The number of “next” work is limited to the velocity of the engineers and how infrequently plans change. The bugs that are last will probably never be addressed, the last features may never be started.

The corollary to this rule is that there are a finite number of bugs or features in the first two groups. There cannot be more work in these groups than there are engineers to do for the given period of time; otherwise the engineers, businesses and users are being misinformed about when issues will be addressed.

An Example

Consider there is one engineer and two bugs. He can only work one bug at a time. One bug is more important than the other. The risk is that he may not be able to fix one of the bugs before users are disappointed and abandon the application. He risks disappointing all users if he does not fix either bug because he choose the one with the most need over the one he was certain he could address.

If he does not know how to fix the bug with the most need, or that the fix takes a long time, he is wasting time he could have spent fixing the bug with more certainty. The only way he can address the bug with the most need is to employ a hack to reduce the need, to meet the expectations of some users. The hack is also used to gain time to understand the problem, thus increase certainty.

Only Assign Work that You Are Committing to do in the Near Future

When a work is assigned to an engineer, he is committing to complete the work in the near future. What the “near future” means is different for each project. I suggest 3 releases is the “near future”, because when work is planned, the engineer is thinking about now, next, and last. For some projects this period might be 6 weeks, for others, 6 months.

I prefer to plan for the current release, and the next one. As work is reprioritised, it may be rescheduled to the third release. I do not think it is wise to plan a bug or feature to be completed in the third releases because if it slips to the fourth or fifth released, I doubt the it was correctly prioritized as high.

Any high work that is assigned to a engineer for more than 3 releases was not high. If it were, the work would have been reassigned to someone who could complete it in the scheduled time. Any other work that is assigned for more than 1 release is also misprioritised. You are lying to yourself, and the the project’s users, when you assign work that you are not committing to fixing.

Practical Classifications of Importance

Work is often classified in relative terms. It is better to classify work according to how it are managed to convey when and under what terms the bug will be fixed or a feature will be complete. There are three priorities that work can be classified as:

Critical
The bug dramatically impairs users. Users may lose their data. Users cannot complete crucial tasks. The feature is needed to encourage adoption or prevent abandonment of the project.

Synonyms: required, essential, now, must do

The work is immediately assigned to a engineer. It is his top priority to fix. Team members help the engineer to plan and do the work. The work is released as soon as it is deployable; in the case of a bug, it is released outside of the release schedule.
High
The bug prevents users from completing their tasks. The feature provides new kinds of tasks or new ways of completing tasks.

Synonyms: expected, next, can do, should do

The work is assigned to a engineer to be completed in the next 3 releases. The engineer may choose to do other work if he believes it is within the scope of the high priority work.
Medium
The bug is inconvenience for many users. The feature provides new ways of completing tasks.

Synonyms: preferred

The work is not scheduled, though it is intended to be completed. When the work is assigned, it may also be scheduled, but there is no commitment to complete it for the stated release. The engineer may choose to postpone the work in favour of more important work.
Low
The bug is an inconvenience to users, but it does not prevent them from completing their tasks. The feature is a convenience to users.

Synonyms: optional, last, may do

The engineer may assign the work to himself while working on a high priority work because the high work provides an opportunity to complete the low priority work at less cost. If the low work in any way jeopardises the high priority work, the low work is unassigned. The engineer is thus certain that the work can be fixed quickly and without difficulty. A corollary to this rule is that low work that is assigned to a engineer must be “in progress” or “fixed” states.

The Problem with “Medium”

It might be argued that when the engineer has an opportunity to fix a low or a medium bug, he must choose the medium one. This rules does not define a practical distinction between medium and low. There is no commitment to fix the medium bug; it will not be scheduled for fixing. A engineer chooses to undertake a low bug because he sees an opportunity to fix it while working in the affected code. The engineer is choosing to do unscheduled work because he is certain it does not jeopardise his scheduled work. The engineer might see an opportunity to fix a medium and a low bug at the same time, but that is unlikely.

It can also be argued that ‘critical’ is ‘high’ and that ‘high’ is ‘medium’. True, that is a matter of semantics. The crux of the issue is that there are three practical classifications of work. The words chosen to describe the classifications could use the tofu scale of hard, firm, and soft. People who are unfamiliar with triage will appreciate names that convey the kind of attention the issue will receive.

Some teams with a large number of bugs prefer to keep a pool of medium work from which releases are planned. Items in the pool may be escalated to high if it is perceived that once work is started, there should be a commitment to complete it as scheduled. This work is different from low work because the work makes a substantial improvement to the application, but like low, there is no commitment when the work will be completed. It can be argued that work starts on medium bugs and features because of changes to other priorities, certainties, or the number of users it affects.

Consequences of Misprioritised Work

Stakeholders often use reports that list the prioritised work for a release and for each engineer. When work is misclassified there are two commonly observed consequences: a decreased in certainty, and a decrease in communication.

In the first consequence, the engineer’s effort may be wasted; there are issues that have more need and certainty. Engineers, and other stakeholders, are often tempted to complete the misdirected work after the misclassification is discovered because it is assumed that it is better to always deliver something finished than nothing at all. This is a risky choice, because it jeopardises work in future releases. By working on less important work, the engineer is decreasing the certainty of the more important work.

The second consequence is that the engineer ignores the list and he works on issues according to some other source, such as the opinion of another stakeholder. While the engineer is working on the correct issue, it is unclear to other parties what work is going on and when will it be completed. Users may abandon the project in frustration. Planners cannot coordinate all the stakeholders.

The first consequence is possibly a failure to do re-prioritisation during the triage process, but second consequence is a total failure in the triage process. Why would anyone do triage if the prioritisation will be ignored? How can work be coordinated if the work is unknown to all stakeholders? Why would users trust a project if it does not do what it says it will do?

Work must be reprioritised during the triage process to ensure that engineers are working on the issues with the most need and certainty. Engineers must work from the list or prioritised issues.

Indicators of Misprioritised Work

The rules of practical classification provide tests for misprioritised bugs, features, or tasks.

  • The work is critical, but it is not assigned and targeted for release.
  • The work prioritised as high, but it is not assigned and for a release.
  • The work is high, but have not been worked on in 3 releases.
  • The work is low and unassigned, yet it is targeted for a release.
  • The work is low and assigned, but the engineer is not working on it.
  • The work is considered to be triaged, but it’s priority is not critical, high, or low.
  • An engineer is assigned more work than he can accomplish in 3 releases, and it cannot be reassigned.

Launchpad font-size broken by design

I looked at Launchpad bug #523189 today. This bug cannot be fixed until Launchpad abandoned YUI-Font rules — percentages have unpredictable results when pages are constructed from fragment. Canonical own Web guidelines specify the use of pixels.

Launchpad uses YUI-Font to normaize font sizes across browser and OSes. It stipulates that all font sizes must be expressed in specific precentages to get the expected point size. This is difficult to use because browsers know that percentages are relative; nesting classes have surprising results.

The following text uses nesting with the same percentages that Launchpad uses.

An example of broken font-sizes in Launchpad

An example of broken font-sizes in Launchpad

Launchpd pages are constructed from many html fragments. The fragments are intended to be usable in many places on a page and display the the same way. Launchpad cannot use percentages for font-size.

Encouraging contribution on the project page

I met with Vish at UDS-N to discuss encouraging contributions to the One Hundred Paper Cuts project. The issues he raised demonstrate that the page design is not meeting the requirements we set in the Launchpad 3.0 UI designs. You will see a common layout in Launchpad pages where a wide narrative block is above two blocks.

Who, what, where, when, and hows of a project

The narrative blocks on a project page (and any Launchpad page using the same layout) must explain what the you are seeing and why it exists. This information is entirely dependant on the project owner.  One Hundred Paper Cuts does this very well. I can read that the project chooses 100 small bugs that can be fixed to improve the common Ubuntu user experience. The project summary says everything in one sentence. The projects description elaborates and explains the value.

The left block below the narrative provides information about who works with the project, and where is the code for the project. Some projects have information about the organisation that the project belongs too. In the case of One Hundred Paper Cuts, the information about “where” is missing and there is no way for Vish to provide it. This project does not have code, it organises work to fix the code in other projects. This is a legitimate use case. Launchpad does not require projects to have source code, but it does not let project owners state what it does as an alternative. I do not know how to solve this.

I would like to tell contributors that this project is affiliated with Ubuntu and User Experience, but Launchpad does not have a concept of project affiliation or tags. I would like to see similar projects that I could contribute to. There are no plans to provide this feature, but we are discussing what needs to be done to fix project groups which has overlapping issues. We may have an opportunity to build this feature next year.

The right block under the narrative is intended to be a call to action. Every page that uses this layout should using this block to encourage users to contribute. For distro series, this block shows the packages that need upstream information. For projects, this should summarise the planned work and what needs to be done. I see a fragment of the series and milestone time line, but it does not tell me what is being done.  The milestones names are not informative. The name implies that the milestones are a sequence, but the 10 milestones are worked concurrently. One Hundred Paper Cuts uses feature-directed milestones. Launchpad supports this work pattern, but the time line does not describe it. Vish could rename the milestone to reveal the theme of the feature, eg rename maverick-round-10-sc-metadata to software-centre-metadata.

Fixing the name is easy, but the information about the work will still not appear on this page. The project index page used to show a summary of the active milestones. I have pondered adding the current milestone to the page so that contributors can see what they can do right now…but how do I show 10 concurrent milestones? Pages that work with milestones are prone to timeouts. I cannot consider restoring milestone information until we solve the long python computation times needs to summarise them.

We can fix some of issues that the project index page has in the next few months, but I think some larger feature and design work is needed to really make the page work for all projects.

Launchpad Answers at UDS-n

While attending UDS-n, I was invited to two separate and contradictory conversations about Launchpad Answers.

Jorge Castro is considering Ask Ubuntu as the official Ubuntu service for managing user questions. It is a nice service. The question refining and member reputation features are compelling. I think there are two changes that need to happen to make this happen:

  1. Launchpad should let project register an external support service. I already have plans do this this later this month. Projects will be able to specify the URL of a site or email address of a list where support can be found. The external service can be used with Launchpad Answers, or by itself. This will permit communities to register the service they are already using, or allow end-users to choose the service that meets their needs.
  2. The Get help online page accessed by Ubuntu desktop applications must be updated to point users to the service the Ubuntu community chooses.

David Planella lead a discussion about internationalising Launchpad Answers. This is a feature we have long wanted to do, but it has never been a priority. This certainly can be done with the community’s help. While examining how users discover Launchpad Answers, we saw that the Get help online page accessed from Ubuntu desktop applications is a complete failure for non-English speaking users. The general steps to fix the non-English-speaker’s experience are:

  1. Automate POT extraction for code and templates.
  2. Add support to localise pages based on your preferred language or browser languages.
  3. Mark the translatable messages in the page templates, and this may require restructuring the information.
  4. Replace the ugly plural hacks in the view code–Zope markup does not support plurals.
  5. Enable translations for the Launchpad project.

Both David’s and George’s intentions are contradictory. The Ubuntu community needs to make a final decision regarding the future of community support before we can proceed. Stack Exchange does not support localisation either, and they do not have plans to support it.  We often talk about replace karma, no one will argue a case to support it, but replacing it is not a priority. Launchpad has an incomplete feature called standing that is like reputation; I am consider removing it because I do not like to maintain unused code.