March 1, 2010 1

UCD And Agile Development since 1936

By duncanhall in General Development

After having very recently completed a 2 day session on web usability focussing on User Centered Design, I was struck by a passage in a book I’m currently reading:

It is true that we are infected with a spirit of conservatism and would rather make small alterations than large ones. It is disagreeable and troublesome for us to admit that our existing system is radically defective. And it is true that, other things being equal, we prefer simple to complex hypotheses, again from the desire to save ourselves trouble. But if experience leads us to suppose that radical changes are necessary, then we are prepared to make them, even though they do complicate our system. When an observation runs counter to our most confident expectations, the easiest course is to ignore it, or at any rate to explain it away. If we do not do this, it is because we think that, if we leave our system as it is, we shall suffer further disappointments. We think it will increase the efficiency of our system as an instrument of prediction if we make it compatible with the hypothesis that the unexpected observation occured. Whether we are right in thinking this is a question which cannot be settled by argument. We can only wait and see if our new system is successful in practice. If it is not, we alter it once again.

Ayer, A.J. (1936). Language, Truth and Logic, 99

While Ayer here is feeding us the information required to answer his question “What is the criterion by which we test the validity of an empirical proposition”, for me it encapsulates many of the key ideas behind philosophies such as User Centered Design and Agile Software Development. Taking a closer look it’s clear that Ayers words have a broader application than just software development (as you might well hope from a philosopher in the 1930s), but sticking to our chosen design and development methodologies, there are some interesting points to be made.

“[we] would rather make small alterations than larger ones”

“Can you just make the title red?” and “Can you just make it so the title is a spaceship?” would rarely elicit the same expression from your favourite developer. Agile is good for breaking big problems into small ones, and this happens on many levels. One such example is a ‘sprint backlog’, which represents a set of discreet, manageable tasks, with an estimate of how long each will take to complete. Rather than a vague cluster of requirements such as “build a registration form”, you might find a set of tasks such as “Send data to remote service” or “Validate input fields”.

Agile anticipates alterations and handles them with high visibility and a clear indication of what larger alterations will do to the system.

“It is disagreeable and troublesome for us to admit that our existing system is radically defective”

Clients change their mind, developers don’t read scopes of work and designers want triangular text inputs; it can be easy to disagree on whether what’s been created is what was asked for. Agile aims to ensure that everyone from client to project manager to developer and designer have the same vision for the project, with no one left to find the outcome “radically defective” in comparison with the system they were expecting.

User centered design helps align the goals of the product owner with the goals of the user, creating a relationship in which you are much less likely to find areas of your system are “radically defective” for either client or user.

“if experience leads us to suppose that radical changes are necessary, then we are prepared to make them, even though they do complicate our system”

Insight into contextual knowledge of where, why, when and how a user interacts with your system is carried out right from the very start when adopting a user centered design approach. The “experience” is the research, and it can often lead us to suppose that what we’ve designed might not be the best for us or our users. The key is that “we are prepared to make [radical changes], even though they do complicate our system”. Considering the users experience from the very beginning, at a point when the cost of change is relatively low, you avoid problems later when the cost of change could well be “radical”.

We often don’t think what we’re creating could be “radically” different from what a user wants or knows how to use. We know how we respond as a user and so can make some general assumptions about how others will behave. That is where you can find a radical difference. This problem of induction is reduced by identifying a handful of core personas from your user research, personable archetypes with realistic traits and behaviours that are used to base your design decisions around. Knowing the user better reduces the probability of the system being wrong for the user.

“We can only wait and see if our new system is successful in practice. If it is not, we alter it once again.”

Ultimately, we don’t know how well a system is going to perform or how a user will interact with it until either a) it performs, or b) a user interacts with it, so we should seek evidence for either of those things as soon as possible. Methods such as paper prototyping are great for quick, low cost iterations of early design and interaction guides. Agiles iterative nature and focus on regular, up-front communication between all parties breeds a process that’s open to changes while following a steady path to its completion.

I won’t do the hermeneutic runaround of wondering if any of the early User Centered Design or Agile pioneers were readers of Ayer, but I’d make a bet he’s at least indirectly influenced many areas of software development today. Later in the book Ayer goes on to state:

[T]he distinction between a conscious man and an unconscious machine resolves itself into a distinction between different types of perceptible behaviour. The only ground I can have for asserting that an object which appears to be a conscious being is not really a conscious being, but only a dummy or a machine, is that it fails to satisfy one of the empirical tests by which the presence or absence of consciousness is determined.

This was written a full 16 years before Alan Turing would publish his 1950 Computing Machinery and Intelligence containing the famous Turing Test. Ayer was 24.

For more on User Centered Design try User Focus.
For a slightly bizarre introduction to Agile, read the Agile Manifesto
For more an A.J. Ayer, I thoroughly recommend reading Language, Truth and Logic

Tags: , ,

February 28, 2010 5

Actionscript AS3 TextButton Class

By duncanhall in Actionscript

The TextButton Class provides a method for creating button components based on simple text labels. It’s something that’s often overlooked in many component sets, but since writing it I’ve found it to be invaluable in almost all of my projects.

In it’s simplest form, all you need to define for a new TextButton instance is the text you want it to display:

var button:TextButton = new TextButton("Home");
addChild(button);

This will create a button with the word “Home” rendered in the system default font. I find this can be useful for very early prototyping to get some quick navigation items on the screen. However, the various states of the button will all use the same default font to style the label, and so it wont visually appear to respond to mouse events.

Defning the styles you want applied to each state is as simple as providing a TextFormat object for each one.

var upFmt:TextFormat = new TextFormat("Tahoma", 12, 0x000000, false);
var overFmt:TextFormat = new TextFormat("Tahoma", 12, 0xFF0000, true);
var downFmt:TextFormat = new TextFormat("Tahoma", 12, 0x00CC99, true);
 
var button:TextButton = new TextButton("Click Me!", upFmt, overFmt, downFmt);
addChild(button);

Example 1:


TextButton Example 1

The TextButton class extends SimpleButton and can be treated like one for all other intents and purposes. The example below shows an event listener being added for the MouseEvent.CLICK event, and also shows that the styles and hit area are automatically updated whenever the value of the text changes.

var upFmt:TextFormat = new TextFormat("Tahoma", 12, 0x000000, false);
var overFmt:TextFormat = new TextFormat("Tahoma", 12, 0xFF0000, true);
var downFmt:TextFormat = new TextFormat("Tahoma", 12, 0x00CC99, true);
 
var button:TextButton = new TextButton("How many times can you click this?", upFmt, overFmt, downFmt);
button.addEventListener(MouseEvent.CLICK, button_clickHandler);
addChild(button);
 
var c:int;
 
function button_clickHandler (event:MouseEvent) : void
{
	c++;
	button.text = "That's " + c + " clicks";
}

Example 2:


TextButton Example 2

The last argument accepted by the constructor is embedFonts which you should set to true if any of your TextFormat objects use an embedded font. Note that if embedFonts is true, all your TextFormat objects must have the relevant fonts embedded.

I have kept all non-public properties and methods as protected so you can subclass TextButton and add any functionality you need.

View source for TextButtonas.as
Download TextButton
View TextButton Documentatation

Tags: , , ,

February 27, 2010 6

AS3 Encoded Polyline Algorithm For Google Maps

By duncanhall in Actionscript

The Google Maps API uses Polyline objects to represent a series of straight lines between a set of latitude and longitude points. Long and complicated lines can become quite cumbersome to describe (especially when needing to send Polyline data to a remote service for example). For this reason, Google provides a method for encoding a Polyline as a series of ASCII characters, with each vertex defined by its distance from the last, rather than the absolute location of each one.

The Encoded Polyline Algorithm Format page documents the steps necessary to encode a set of lat/long points in the required format. For those of us working with the Google Maps API for Flash, I have written an Actionscript 3 implementation of the encoder, in the form of the PolylineEncoder Class.

PolylineEncoder.fromPoints()
Takes a Vector of LatLng objects and returns the encoded string representation:

var points:Vector. = new Vector.();
points.push(new LatLng(38.5, -120.2), new LatLng(40.7, -120.95), new LatLng(43.252, -126.453))
var encoded:String = PolylineEncoder.fromPoints(points);
trace(encoded); //Outputs _p~iF~ps|U_ulLnnqC_mqNvxq`@

PolylineEncoder.fromPolyline()
Takes an existing IPolyline object and returns the encoded string representation:

var poly:Polyline = new Polyline([new LatLng(38.5, -120.2), new LatLng(40.7, -120.95), new LatLng(43.252, -126.453)]);
var encoded:String = PolylineEncoder.fromPolyline(poly);
trace(encoded); //Outputs _p~iF~ps|U_ulLnnqC_mqNvxq`@

PolylineEncoder.encodeLevels()
Takes an Array of uint level values and returns the encoded string representation:

var encodedLevels:String = PolylineEncoder.encodeLevels([174, 100, 100, 174]);
trace(levels); //Outputs mDcBcBmD

The use of the ‘level’ value is described by Google:

An encoded polyline also stores information specifying the precision when drawing the polyline. This information allows the map to ignore drawing segments at zoom levels where that precision is not necessary. Each point in an encoded polyline stores this information in a levels string which is also encoded alongside the encoded points.

Note: this encoded “level” does not correspond directly to a zoom level, though they are related. More accurately, the numLevels parameter divides up the existing zoom levels (currently 18) into groups of zoom levels.

In other words, if you are encoding a Polyline purely for storing locational data, it’s not necessary to encode a level value for each point on the line. The lat/lng of the original point is unaffected by its level value.

var encodedPoints:String = PolylineEncoder.encodeFromPolyline(existingPolyline);
var encodedLevels:String = PoylineEncoder.encodeLevels([100]);
var encodedPolyline:EncodedPolylineData = new EncodedPolylineData(encodedPoints, 4, encodedLevels, 16)
var decodedPolyline:Polyline = Polyline.fromEncoded(encodedPolyline);
trace(existingPolyline.getLength() == decodedPolyline.getLength()); //true!

View source for PolylineEncoder.as
Download PolylineEncoder.as
View PolylineEncoder Documentatation

Tags: , , ,