Kris Jordan

Kris Jordan

  • Mission
  • Students
  • Teaching
  • Thoughts

›Recent Posts

Recent Posts

  • OBS for On-line Teaching and Instructional Videos
  • New Website
  • Code Sketch - Paper Trail
  • Encryption with RSA Key Pairs
  • Log Indexing and Analysis with Logstash and Kibana

The Inverted Pyramid & other Tips on Making Demos

November 8, 2012

Kris Jordan

“Wiretap’s demo was fantastic. How’d you make it?”

I was pleasantly surprised to get asked this after releasing Wiretap's first demo video. (Embedded below.)

Good demos are hard.

It’s hard not to get lost in features and technical details. It’s hard to give enough context, but not too much. It’s hard to keep a good pace.

I was really afraid of falling into these traps. Wiretap is an HTTP debugger for mobile and web apps integrating with REST APIs. By default, these are the ingredients of a snoozer video.

Here’s how Wiretap’s demo avoided putting (most) people to sleep and some other fun, behind-the-scenes details.

Trust the ole Inverted Pyramid

Put your most important messages in the beginning. It’s all most people will see.

If someone stops watching after 30 seconds, will they know what they need to know?

News writers popularized the idea of an Inverted Pyramid, or, “Bottom Line Up Front”. The idea is readers should be able to leave a story halfway through and have a good enough understanding of it.

  • Who is this product for?
  • Why does it exist?
  • What does it do?
  • How is it used?
  • When is it useful?

The intro to Wiretap’s demo was something I struggled with. Luckily I got some good feedback on the first take from a friend. More on that in the next section.

In the body of a demo: tell a story.

Walk through scenarios that motivate features. Don’t give a feature tour. Reuse the scenarios you came up with to guide your app’s design and implementation. Heck, maybe even copy them straight from your BDD tests, if that’s your bag.

Don’t expect someone to watch your whole demo, but give them reasons to.

Show Friends, Act on Feedback

After hacking on a project for a while it’s really hard to describe it in a demo context-free.

You need fresh eyes.

Show someone who could be a user of your product but doesn’t know anything about it yet. Take action on their feedback.

The feedback I got on the first version of my demo was:

“The intro was missing the why? Why did you build this? Why is it useful?”

He was right.

I jumped straight into using the product. So I scratched it, recorded new audio, and rearranged the video clips to match. It wasn’t much work and the improvement was substantial. (It could be better yet: the current intro takes 50 seconds. Tsk, tsk.)

Use Bargain Tools that are Easy

Great recording software doesn’t make a great demo, but it can save you a lot of time. Since folks are always curious about tooling, here’s what I used.

Video Capture - QuickTime / iShowU HD - Yep, the QuickTime Player installed on every OSX can make screen recordings. Just go to File > New Screen Recording. You can record the screen or a specific bounded rectangle. It’s a little clunky, though, and lacks some nice features in commercial software like scaling and a better workflow. I’ve had an iShowU HD license ($30 and worth it) for a few years and used it for the Wiretap demo.

Audio Recording - Audacity - Awesome, free, open-source software for recording a narration track. This was the first time I wrote a script for a demo and recorded the video and audio independently. It allowed me to crop out places where I misspoke or had long pauses. This helped the pace of the demo. The downside was that the edits and scripting were noticeable at times, but it was good enough.

Post-production - iMovie - iMovie makes chopping up screen recordings and aligning them with an audio track easy. With software demos you can speed-up and slow-down screen captures to align events with the narration. I abused this freedom. In iMovie just go to ‘Clip Adjustments’, look for the speed section, convert the video, and enter the desired duration of your clip.

Have Fun, Keep it Light

Sprinkling in some spice won’t take away from your meat and potatoes.

With Wiretap I wanted to walk through a complete Mobile App + Server-side API + 3rd Party API scenario. Doing something that was the “AirBnB of _____” seemed pretty obvious and my dog was laying under my desk looking guilty at the time so I ran with “ShameKennelRnR”. I dropped in a few little easter eggs, as well.

Be excited to show off what you’ve been hacking on and have fun with it.

multimethod.js - Clojure-like Multimethods in JavaScript

December 15, 2011

Kris Jordan

What is a multimethod?

The quickest way to understand is by looking at a simple, familiar example implemented with a multimethod. So let's write a recursive Fibonacci function.

> var fib = multimethod()
                .when( 0, 0 )
                .when( 1, 1 )
                .default( function(n) {
                    return fib(n-1) + fib(n-2);
                });
> fib(20);
6765

Multimethods are a functional programming "control structure" enabling you to dynamically build-up and manipulate the dispatching behavior of a polymorphic function. Inspired by Clojure's multimethods, multimethod.js provides a functional alternative to classical, prototype based polymorphism. The multimethod.js library is MIT licensed, is found on GitHub and npm with npm install multimethod, and its annotated source code is available here.

Motivating Examples

Let's use the node.js REPL to build a few multimethods and see what they are capable of doing. In this first example we'll create a mulimethod that calculates the area of shapes instantiated with object literals.

> var multimethod = require('multimethod');
> var area = multimethod()
                .dispatch(function(o) {
                    return o.shape;
                })
                .when("square", function(o) {
                    return Math.pow(o.side, 2);
                });
> var aSquare = { "shape":"square", "side": 2 };
> area( aSquare );
4

> var aCircle = { "shape":"circle", "radius": 5 };
> area( aCircle );
undefined

> area.default(function(o) { 
    throw "Unknown shape: " + o.shape;
  });
> area( aCircle );
Unknown Shape: circle

> area.when("circle", function(o) {
    return Math.PI * Math.pow(o.radius, 2);
  });
> area( aCircle );
78.53981633974483
> area( aSquare );
4

> area.remove("circle");
> area( aCircle );
Unknown Shape: circle

Notice how dispatch returns the value we'll match to a "method" registered with when. You can introduce, overwrite, and remove new methods dynamically at runtime. Fallback behavior can be established with a default function called when no methods match the dispatched value.

> var hitPoints = multimethod()
                    .dispatch(function(player){ return player.powerUp; })
                    .when( {"type":"star"} , Infinity)
                    .default(5);

> var starPower = { "type":"star" },
>     mario = { "powerUp": starPower };
> hitPoints(mario);
Infinity

> mario.powerUp = null;
> hitPoints(mario);
5

> var godModeCheat = function() { return starPower; };
> hitPoints.dispatch(godModeCheat);
> mario.powerUp;
null
> hitPoints(mario);
Infinity

In this last example notice how we are matching against an object. Matching is done using deep equality so objects and arrays are valid method matching criteria. Also notice how we can completely override our dispatch function to change the logic with which a multimethod evaluates its arguments for dispatch, or, in this case, ignores them!

Multimethod Dispatch Algorithm

  1. User calls multimethod with argument anArgument.
  2. Multimethod calls its dispatch function with anArgument. The returned value is stored in dispatchValue.
  3. Multimethod iterates through each 'method' registered with when and performs an equality test on the dispatchValue and each method's match value. If a match is found, set matchFunction to the method's function and go to step 5.
  4. If no method match found, set matchFunction to the multimethod's default function.
  5. Multimethod calls matchFunction with anArgument. The returned value is returned to the user who called the multimethod.

A More Detailed Walkthrough

The Basics

A multimethod is instantiated with the multimethod function.

var stopLightColor = multimethod();

A multimethod has methods. A method is has two parts, its match value and its implementation function. Methods are added using when.

stopLightColor.when("go",    function() { return "green"; })
              .when("stop",  function() { return "red"; });

You can call a multimethod just like any other function. It will dispatch based on the argument(s) passed in, invoke the matched method, and return the results of the method call.

console.log( stopLightColor("go") ); // "green"

When no method matches control can fallback to a default method.

stopLightColor.default( function() { return "unknown"; } );
console.log( stopLightColor("yield") ); // prints "unknown"

A multimethod can handle new cases dynamically at run time.

stopLightColor.when("yield", function() { return "yellow"; });

There is a shorter way for a method to return a plain value. Rather than passing an implementation function to when, pass the value.

stopLightColor.when("yield", "yellow");
console.log( stopLightColor("yield") ); // prints "yellow"

A method can be removed dynamically at run time, too.

stopLightColor.remove("go");
console.log( stopLightColor("go") ); // prints "unknown"

Dispatch Function

Each multimethod call first invokes a dispatch function whose return value is used to match the correct method to call. The dispatch function is passed the arguments the multimethod is invoked with and returns a value to match against.

The default dispatch function is an identity function. The basic stopLightColor examples could have been created with an explicit dispatch function.

var stopLightColor = multimethod()
      .dispatch(function(state){
         return state;
      })
      .when('go', 'green');
console.log( stopLightColor('go') ); // green

The power of the multimethod paradigm is the ability to dispatch with a user-defined function. This gives a multimethod its "polymorphic" powers. Unlike classical, object-oriented polymorphism where the compiler dispatches based on the type hierarchy, a multimethod can dispatch on any criteria.

var contacts = [
  {"name":"Jack", "service":"Twitter","handle": "@jack"},
  {"name":"Diane","service":"Email",  "address":"d@g.com"},
  {"name":"John", "service":"Phone",  "number": "919-919-9191"}
];

var sendMessage = multimethod()
     .dispatch(function(contact, msg) {
       return contact.service;
     })
     .when("Twitter", function(contact, msg) {
       console.log("Tweet @"+contact.handle+":"+msg);
     })
     .when("Email", function(contact, msg) {
       console.log("Emailing "+contact.address+":"+msg);
     })
     .default(function(contact, msg) {
       console.log("Could not message " + contact.name);
     });

// Blast a message
contacts.forEach( function(contact) {
  sendMessage(contact, "Hello, world."); 
});

Plucking a single property from an object is so commonly used as a dispatch function, like in the example above, there is a shortcut for this pattern. The following dispatch call is equivalent to above.

sendMessage.dispatch( 'service' );

A multimethod's dispatch is usually specified when constructed.

var sendMessage = multimethod('service');

Just like methods can be added and removed from a multimethod at run time, the dispatch function can also be redefined at run time. Ponder the implications of that for a minute. It is really powerful and really dangerous. Don't shoot your eye out.

Deep Equality Matching

A method's match value is compared to dispatch's return value using the underscore.js isEqual function. Deep equality method matching enables concise expressivity. Contrast this with a traditional switch statement that is limited by JavaScript's === equality behavior.

var greatPairs = multimethod()
      .when( ["Salt", "Pepper"], "Shakers" )
      .when( [{"name":"Bonnie"}, {"name":"Clyde"}], "Robbers" );
console.log( greatPairs( ["Salt", "Pepper"] ) ); // Shakers

API Recap

Constructor: multimethod( [fn | string] ): No arg constructor uses an identity function for dispatch. Single arg constructor is a shortcut for calling dispatch with the same argument.

dispatch(fn | string): Sets the multimethod's dispatch function. String values are transformed into a pluck function which projects a single property value from the first argurment.

when(match, fn | value): Add a method to be invoked when the dispatch return value matches 'match'. If a non-function value is provided it will be returned directly. Calling when with the same match value twice will override the previously registered method.

remove(match): Remove a method by it's match value.

default(fn | value): Catch-all case when no method match is found.

Installation

Install with npm for use in node.js based projects.

npm install multimethod node

var multimethod = require('multimethod');

Fixing WebKit's Accept Header

March 10, 2011

Kris Jordan

WebKit has been on the forefront of web browser innovation for years, but their HTTP Accept header has lagged behind. (tl;dr it is fixed now.) The Accept header is how the web browser says to the web server "these are the content-types I can understand and the order in which I prefer them."

The Accept header allows a single object or resource to have a single URI with multiple representations, such as HTML, XML, or JSON. It is a fundamental component of the HTTP spec and REST style web services. Unfortunately, today's web services rarely use content-negotiation, because browsers have historically chosen bad Accept headers. WebKit's was the last serious offender:

application/xml,
application/xhtml+xml,
text/html;q=0.9,
text/plain;q=0.8,
image/png,
*/*;q=0.5      

Parsed and prioritized:

1. application/xml
2. application/xhtml+xml
3. image/png
4. text/html
5. text/plain
6. */*

WebKit's Accept header preferred XML over HTML prior to my fix landing in trunk today. Web services could not offer both HTML and XML for a single resource and use content negotiation because WebKit based browsers (Safari, Chrome, et. al.) would be served the XML data not the HTML web page. Developers have had to hack around the issue. Twitter's API, for example, uses a common work around that changes the URI by appending a format extension.

http://api.twitter.com/version/statuses/friends_timeline.format
format ::= json | xml | rss | atom

The goal of the fix for WebKit's Accept header was straightforward: prefer HTML over XML. The ultimate solution was to minimize risk and take Firefox's lead. Here is the Accept header, already in order of preference, WebKit-based browsers will be using in the future:

text/html,
application/xhtml+xml,
application/xml;q=0.9,
*.*;q=0.8

Contributing to Open Source Software

The fix may have been committed today, but the initial bug report was filed in July 2009, almost two years ago! What took such a simple, but important, fix so long to be made? I would like to say it was the need for five other people to chime in on the ticket, someone on the WebKit team to notice, or a duplicate bug request to be filed 15,000 tickets later. But no, all the WebKit team needed was for someone, anyone, to submit a patch. So I checked out the subversion repository, made a patch, submitted it, and boom, I have contributed code to WebKit and fixed its Accept header woes. Very cool, but I feel horrible for not doing so with the original bug report in 2009; content negotiation would be more usable today.

Lesson learned: no matter how big or small an open source project is, when you find a bug and know the fix just do it. Do not assume code to be sacred or untouchable; just fix it and let the committers make the call. Bug reports are helpful, but patches and pull requests are gold. Discussions get read, code gets committed. Code speaks louder than words.

Refactoring Cache Tables using Memoize

March 6, 2011

Kris Jordan

Have you ever written code that feels like this?

var byKey = function (key) {
    ... do slow, expensive stuff ...
    return { value: “something expensive” };
};

And later optimized it to feel like this?

var lookup = {};
var byKey = function (key) {
    if ( lookup[key] === undefined ) {
        ... do slow, expensive stuff ...
        lookup[key] = { value: “something expensive” };
    }
    return lookup[key];
};

I certainly have. The lookup table is a trusty pattern for caching the results of expensive calls. With four additional lines of code you can dramatically improve the performance of an often called function. Sprinkle these lines around your most expensive, referentially transparent functions and you have a nicely optimized program, right?

With a functional language this pattern is considered harmful; an anti-pattern to refactor. It may be four lines of code, but it is redundant when used over and over. Your function’s intentions become conflated with performance concerns. It would be best to keep our intentions and optimizations separate.

Can we simply write “cache this function’s return values”? It would feel like this,

var byKey = cache(function(key) {
    ... do expensive stuff ...
    return { name: “something expensive” };
});

That feels much better. Although, not knowing what the cache function actually does is a little off-putting. Let’s implement it.

If you are unfamiliar with anonymous functions and closures in JavaScript this is about to get slightly hairy. Understanding those concepts will make writing JavaScript much more interesting, and little blog posts like this more palatable. I suggest Crockford, but there are plenty of good on-line resources, too.

We need our cache function to take any function we throw at it and return a new function. The returned function must accomplish what our imperative lookup table code did: remember the arguments of previous invocations and cache their return values.

var cache = function( expensiveFn ) {
    var lookup = { };
    return function(key) {
        if(lookup[key] === undefined) {
            lookup[key] = expensiveFn(key);
        }
        return lookup[key];
    };
};

Let's walk through this. We have defined cache as a function that takes expensiveFn as a parameter. Within this function we setup the variable lookup to be our hash/cache table. Then we return a function that encapsulates the lookup table pattern used earlier. Do you see how the structure has been extracted and the state hidden within the closure?

In computer science this function is conventionally named memoize. It is often demonstrated using a recursive function like factorial. Factorial is a more beautiful application of memoization than basic key-value caching, but this is an anti-patterm you are more likely to find in real code.

An Exercise for the Reader

The most obvious shortcoming to cache, our implementation of memoize, is that it does not generalize to functions of more than one argument. If you have a few minutes, pop open your browser’s JavaScript console in Firebug or Webkit Inspector and try writing it. Hints: 1) The arguments keyword provides an array of all arguments a function is called with. 2) A function can be invoked with an array of arguments by using Function's apply method.

Refactor one-off caching via lookup tables with memoize

Plenty of libraries provide a generic memoize function, including underscore in JavaScript. The next time you catch yourself writing a naive in-memory cache lookup table around a function stop and consider memoizing it instead. Using memoize is faster to write and less bug-prone than a one-off cache, it separates intentional concerns from optimization concerns, and it keeps your code a little cleaner.

Towards RESTful PHP - 5 Basic Tips

December 2, 2008

Kris Jordan

What is REST?

REST is an architectural style, or set of conventions, for web applications and services that centers itself around resource manipulation and the HTTP spec. Web apps have traditionally ignored the HTTP spec and moved forward using a subset of the protocol: GET and POST, 200 OKs and 404 NOT FOUNDs. As we entered a programmable web of applications with APIs the decision to ignore HTTP gave us problems we're still dealing with today. We have an internet full of applications with different interfaces (GET /user/1/delete vs. POST /user/delete {id=1}). With REST we can say /user/1 is a resource and use the HTTP DELETE verb to delete it. For more detail on REST check out wikipedia and "quick pitch".

Tip #1 Using PUT and DELETE methods

In PHP you can determine which HTTP method was used with: $_SERVER['REQUEST_METHOD']; From web browsers this will be either GET or POST. For RESTful clients applications need to support PUT and DELETE (and ideally OPTIONS, etc.) as well. Unfortunately PHP doesn't have $_PUT and $_DELETE variables like it does $_POST and $_GET. Here's how to access the content of a PUT request in PHP:

$_PUT  = array();
if($_SERVER['REQUEST_METHOD'] == 'PUT') {
    $putdata = file_get_contents('php://input');
    $exploded = explode('&', $putdata); 
    foreach($exploded as $pair) {
        $item = explode('=', $pair);
        if(count($item) == 2) {
            $_PUT[urldecode($item[0])] = urldecode($item[1]);
        }
    }
}

Tip #2: Send Custom HTTP/1.1 Headers

PHP's header function allows custom HTTP headers to be sent to the client. The HTTP/1.x header contains the response code from the server. PHP will, by default, send back a 200 OK status code which suggests that the request has succeeded even if it has die()'ed or a new resource has been created. There are two ways to change the status code of your response:

header('HTTP/1.1 404 Not Found');
/* OR */
header('Location: http://www.foo.com/bar', true, 201); // 201 CREATED

The first line is a generic way of setting the response status code. If your response requires another header, like the Location header to the resource of a '201 Created' or '301 Moved Permanently', placing the integer status code in the third parameter of header is a shortcut. It is the logical equivalent of the following example, which is easier to read at the cost of being an extra line of code.

header('HTTP/1.1 201 Created');
header('Location: http://www.foo.com/bar');

Tip #3: Send Meaningful HTTP Headers

Policy for deciding when it is appropriate to send each HTTP status code is a full post on its own and the HTTP spec leaves room for ambiguity. There are many other resources on the net which provide insights so I'll just touch on a few.

201 Created

Used when a new resource has been created. It should include a Location header which specifies the URL for the resource (i.e. books/1). The inclusion of a location header does not automatically forward the client to the resource, rather, 201 Created responses should include an entity (message body) which lists the location of the resource.

202 Accepted

Allows the server to tell the client "yeah, we heard your order, we'll get to it soon." Think the Twitter API on a busy day. Where 202 Created implies the resource has been created before a response returns, 202 Accepted implies the request is ok and in a queue somewhere.

304 Not Modified

Used in conjunction with caching and conditional GET requests (requests with If-Modified-Since / If-None-Match headers) allows web applications to say "the content hasn't changed, continue using the cached version" without having to re-render and send the cached content down the pipe.

401 Unauthorized

Used when attempting to access a resource which requires authentication credentials the request does not carry. This is used in conjunction with www-authentication.

500 Internal Server Error

Better than OK when your PHP script dies or reaches an exception. Informs the other end that the problem was on the server side and avoids potential for caching the response.

Tip #4: Don't Use $_SESSION

A truly RESTful PHP application should be entirely stateless- all requests should contain enough information to be handled without additional server side state. In practice this means storing authentication information in a cookie with a timestamp and a checksum. Additional data can also be stored in a cookie. In the event you need more than a cookie's worth of data fall back to storing it in a central database with the authentication still in the cookie. This is how Flickr approaches statelessness.

Tip #5: Test with cURL or rest-client

cURL makes it easy to execute any HTTP METHOD on a resource URL. You can pass request parameters and headers as well as inspect response headers and data. The command line tool 'curl' is standard on many *nix distros. Windows users should check out MinGW/MSYS which supports cURL. Even PHP has cURL functions which are enabled on most hosts (php/curl install page). cURL Example Usage & Common Parameters:

curl -X PUT \
     http://www.foo.com/bar/1 \
     -d "some=var" \
     -d "other=var2" \
     -H "Accept: text/json" \
     -I

-X [METHOD] Specify the HTTP method. -d "name=value" Set a POST/PUT field name and value. -H [HEADER] Set a header. -I Only display response's headers.

Tip #6 - Use a RESTful PHP Framework

Frankly, developers shouldn't have to worry about many of these low-level details of REST when writing PHP apps. REST is based on conventions and conventions, by nature, involve a lot of boilerplate. This is right up a framework's alley (as Rails has shown). What options exist for PHP? CodeIgniter's routing completely ignores the HTTP METHOD so there is serious hacking that needs to be done. Cake has REST support but wasn't designed to make specifying useful response status codes a part of the framework. Konstruct appears to have a very well thought out architecture for a controllers framework built around HTTP and REST. Unfortunately it is not easily approached and lacking (intentionally) many components, like an ORM layer, developers have come to expect in a modern web framework.

(Disclaimer: Shameless Plug!) The lack of a solid, RESTful PHP framework was one of my primary motivations for creating the Recess! Framework. Recess is a full-stack, open source (MIT), RESTful PHP framework. If you're interested in writing RESTful PHP applications check it out and sign-up to be notified of its upcoming release.

Dynamic Properties in PHP and StdClass

November 27, 2008

Kris Jordan

Languages like JavaScript and Python allow object instances to have dynamic properties. As it turns out, PHP does too. Looking at the official PHP documentation on objects and classes you might be lead to believe dynamic instance properties require custom __get and __set magic methods. They don't.

Simple, Built-in Dynamic Properties

Check out the following code listing:

class DynamicProperties { }
$object = new DynamicProperties;
print isset($object->foo) ? 't' : 'f'; // f

// Set Dynamic Properties foo and fooz
$object->foo = 'bar';
$object->fooz = 'baz';

// Isset and Unset work
isset($object->foo); // true
unset($object->foo);

// Iterate through Properties and Values
foreach($object as $property => $value)  { 
     print($property . ' = ' . $value . '<br />'); 
}

// Prints:
//   fooz = baz

Using the built-in dynamic instance properties is an order of magnitude faster (30x, by my profiling) than using magic __get and __set methods. Built in dynamic property accesses happen without invoking a method call back to PHP script.

So when does it make sense to use __get and __set? If you need more complex behavior, like calculated properties, you must use __get and __set. Also, as an astute comment points out, if you would prefer not to have dynamic properties on a class you can throw errors from __get and __set.

StdClass: Anonymous Objects

Sometimes all that is necessary is a property bag to throw key value pairs into. One way is to use array, but this requires quoting all keys. Another way is to use dynamic properties on an instance of StdClass. StdClass is a sparsely documented class in PHP which has no predefined members.

$object = new StdClass;
$object->foo = 'bar';
json_encode($object);

Next I'll touch on the SPL's Countable and ArrayAccess as a means of being able to accomplish the following in PHP:

class MyClass implements Countable, ArrayAccess { ... }
$myObject = new MyClass();
// Using array access notation
$myObject[0] = 'hello';
$myObject[1] = 'world';
$myObject['foo'] = 'bar';

Building Recess - A RESTful PHP Framework

October 8, 2008

Kris Jordan

Hello Again, Old Friend

I'm in the process of replumbing the lightweight PHP application framework I wrote in college over three years ago. Its original design was inspired by the Java Struts Framework. It enabled us to rapidly develop the first version of New Media Campaigns' website management software. Two summers ago we did a major redesign inspired by the DRY nature of Ruby on Rails.

Energized by what I saw at the Web 2.0 Expo in NY I'm back at it again. My three big goals with this take:

1) Get it in the wild: Open source with an MIT license.

This is going to happen before the New Year. Hopefully sooner. We intended to do this with V2. It actually was publicly available in 2006 for a brief period of time but without any real plan for evangelism. I've been using open source software for a long time and its high time to give back.

2) Play nice in the new RESTful world.

If I had to bet on a paradigm for interacting with web APIs I would bet the farm on REST. It is perfectly aligned with the grain of the web. Most existing frameworks written without an emphasis on REST have made awkward face lifts to adapt. When revisiting our own framework and considering how to make it properly RESTful this would have held true if not for...

3) Signficantly Improving the Architecture.

Revisiting old code is a joy. It's easy to forget how clever you were and how much work you did. Yet it's very disturbing to realize how hacked some of the fundamental design was. As mentioned, the current version was influenced significantly by what Rails plumbing looked like circa-2006. Since then two really important things have changed: 1) the emphasis on tying closer to HTTP protocol, and 2) two additional years of experience with systems design under the belt.

So, here's to take 3! Bits available for download in upcoming months. E-mail me at krisjordan/gmail if interested in being copied on barely functional, pre-release bits in the mean time. Otherwise, stay tuned.

Persona-Driven Development: Meet Customers First, Write Unit Tests Later

September 12, 2008

Kris Jordan

“When was the last time you even met a customer?”

(Jeff Atwood wants to know)[http://www.codinghorror.com/blog/archives/001013.html]. Can you picture their face? When was the last time you used their name in a design discussion? Or had them on the phone?

Jeff talks from a post-development, post-launch, post-adoption perspective. Right now the software project I’m brewing up is in the pre-development, pre-launch, pre-adoption stage. So putting engineers on support duty, Jeff’s remedy for not knowing The Customer’s pain, doesn’t quite work (yet).

Paul Graham’s essay “(How to Start a Startup)[http://www.paulgraham.com/start.html]” asserts that creating something customers “actually want” is one of the three fundamental pillars of successful startups. This echoes the first commandment of Business 101, Know thy Customer. On first glance there’s a Catch-22 here, right? You cannot know what your customers actually want if you do not have any customers and you will not have any customers if you don’t have what they actually want.

There are three approaches to jumping out of this strange loop. You can ignore the problem, you can make yourself The Customer, or you can get out from behind your desk and go talk to folks who could be The Customer.

Approach #1: If You Build It, They Will Come.

This has the allure of a Siren’s song, the whispers of Shoeless Joe Jackson in the back of your head. If someone were to ask you to “name a customer that needs your product” would you answer with specific names? If asked “how did their reactions to your ideas, mock-ups, and early prototypes impact what you’re doing” would you have a response? If not, you’re probably ignoring the Knowing The Customer problem.

I’ve fallen for this Lorelei song of ignorant bliss myself, but never again. Three years ago I took a semester leave from college, leased an incubation office, and was off to the races building my killer app. 6 months, 2 part-time employees, a twice-architected and half-implemented J2EE/Hibernate/MySQL ‘enterprise’-grade solution, $7,000 of personal savings, and a broken relationship later I could not concretely personify The Customer. In hindsight, I could not produce a list of names of people who would use my product as soon as it went live. The venture was a spectacular failure and a spectacular learning experience.

Approach #2: Mirror, Mirror on the Wall.

Making yourself The Customer is part of the magical formula behind 37Signals’ Getting Real book, specifically the second short essay in Chapter Two: (What’s Your Problem?)[http://gettingreal.37signals.com/ch02_Whats_Your_Problem.php] Fried's reasoning is simple. If you have an itch, you’re not alone in this world, so you’ve got a market. There are some hidden dangers to this approach, though. As Graham points out, “this is just the kind [of software] that tends to be open source: operating systems, programming languages, editors, and so on. So if you're developing technology for money, you're probably not going to be developing it for people like you.”

Other problems are that it is easy to become lazy and lose focus. When you're the customer and the creator you're more likely to be forgiving of yourself. It is too easy negotiate yourself out of writing the truly useful but challenging stuff ("oh, I don't really need that"). It is easier to get lost in implementation details only you perceive. It is easier to lose focus of what’s big and important and get caught up on the small stuff.

Approach #3: Meet “Likely” Customers, Show ‘em your Stuff, Listen, Rinse, Repeat. This is obvious but underutilized. Why? Sitting down with non-hackers and sharing ideas and paper prototypes is anxiety inducing! What if they don’t like it? What if they don’t get it? What if they think it sucks? Better to find answers now than after you’ve sunk a lot of time into building your “next big thing”. It is easy to put this off because you don’t have enough to show. This is why I’ve gotten into mocking in PowerPoint. It’s quick and cheap. Graham states it pretty plainly, “The only way to make something customers want is to get a prototype in front of them and refine it based on their reactions”.

The big wins of getting out from behind the desk and in-front of The (Potential) Customer are you get to know your product better. By forcing yourself to explain your stuff you get to know your pitch better. Talking about new ideas and new products is one of the most difficult skills to learn. The second big win is you learn who The Customer is and who The Customer is not. You can put a name with a face with a role. You can craft personas that concretely name and characterize The Customer. This shared vocabulary and understanding of The Customers helps teams empathize with and rally around real people.

Persona-Driven Development

From my brief experience in the Developer Division at Microsoft (the folks behind Visual Studio, C#, IronPython, IronRuby, etc.) I couldn’t help but be impressed with how well they know The Customer. Before serious development revs up the program managers do a lot of homework on The Customer. Face-to-face interviews, phone calls, focus groups, surveys, they do it all.

What is the result? Concrete persona profiles. Science-fair like posters hung in the walls which give names to the primary customer personas, talk about their day-to-day lives, exemplify their pains, and show pictures of their faces. It’s hard to lose sight of The Customers you code for when you see their face on your wall every day. It also leads to more effective discussions when the question is “Would Jill use this?” and you know exactly who Jill is and what her problems are, than “Would our ‘customers’ use this?”

If the mantra of test-driven development states it is sacrilegious to write a single line of implementation before writing your unit-tests then the mantra of Persona-Driven Development states it is blasphemous to write a single unit-test before you write The Customer personas that represent real people you’ve talked to who need your product.

10 Minute Mock Prototyping - Tips for Powerpoint

September 7, 2008

Kris Jordan

Mocking up user-experience designs needn’t be time a huge time-sink. This is especially true for sketchy, early-stage designs. First draft mockups are about exploring as many promising directions possible before picking just one. Agility and speed are the overarching goals when laying out a new vision, brainstorming a screen flow, or mocking a renovated experience. The goal is not pixel perfection it’s proof-of-concept.

YouTube Demo:

Jason Fried of 37 Signals is spot on when he says Photoshop is not the right tool for the job. In Photoshop it’s too easy to get lost in the details. In Photoshop you can’t simulate clicking around, it’s just static images. That said I would argue there are flaws with the Jason's method of starting in XHTML / CSS. The proclaimed upside in working towards something ‘real’ is worthless if you’re working towards something real bad but don’t realize it until hours have been invested in an oxymoronic real mockup. The time to dive into XHTML / CSS is after the direction your design is heading in is clear, the wire framing and interaction flow set.

PowerPoint is great for fleshing out quick and dirty UX Design Mockups. You can whip screen flows together, make important elements interactive and clickable, share with other people, and quickly iterate on the mock.

When I'm mocking/prototyping in PowerPoint there are a couple of short-cuts I take to make the work go fast. To see the following 5 tips illustrated, check out the YouTube screen cast.

1.Use a Pallet PowerPoint File and Ctrl + Tab

The number one waste of time when mocking UX in PowerPoint is to have to go to Insert > Shape, pick the shape, and correctly style it or Insert > Picture, and have to go find an icon, etc. When mocking designs there are a handful of things you’ll often need: shapes, styles, UI controls, icons, images, container screens, and action templates. Create a PowerPoint file which contains all of your commonly used elements and have it open in the background.

Have a pallet file open while you’re working on your prototype design file and Ctrl-Tab between the two for quickly getting at your design elements.

2. Create Master Slides First and Duplicate with Ctrl + D

In PowerPoint each slide is independent of the rest. So if you create a layout on one slide then duplicate it and rearrange the layout the result is a different layout on each. This is addressed in two ways, one by keeping your screens as simple as possible, and two by creating master slides and doing some forethought around the elements that will be present on every screen. Once you’ve got your template you can quickly duplicate by selecting the slide and using the Ctrl+D shortcut.

3. Copy and Paste Styles (Ctrl + Shift + C / V)

Maintaining a consistent UI is a lot easier with a catalog of styles. The coloring and text styles used throughout your mockup should be kept on a slide in your pallet file. Want to change from one style to another? Easy, just select the style you want, use Ctrl + Shift + C shortcut, then select the items you want to apply the style to and use the Ctrl + Shift + V shortcut. Voila! Fun hack: on my pallet file I’ve got styles and then a group of shapes. By copying a style and selecting any object in the group I apply the style to all shapes and then copy the shape I need out.

4. Use Hyperlinks for Interactivity (Ctrl + K)

To simulate interaction in PowerPoint use hyperlinks that jump non-linearly through the presentation. Select the item you want to be made clickable and use the Ctrl + K shortcut. Then select the ‘Places in this Document’ and finally slide in which you want the click to bring you to. Sure, it is ‘spaghetti’ like ‘GoTo’ in programming, but it works. Additionally, you usually want to turn off the ability to click anywhere on the slide and move to the next slide. This can be accomplished by going to the ‘Animations’ tab in PowerPoint 2007 and unselecting ‘Advance Slide on Mouse Click’.

5. When Feigning Mouse Over (Use Action Templates)

Believe it or not you can get mouse over effects in PowerPoint. Warning: it’s hacky. The premise is you place a very transparent box on top of what you want to be able to hover over and give it ‘mouse over’ action of moving to the next slide. The following, nearly duplicate slide, then uses a transparent ‘Border’ shape (hollowed out rectangle) which surrounds the hoverable area and moves to the previous slide when it’s mouse over action is triggered. I use a template for this, located in the example pallet, which simplifies the process.

Do you use PowerPoint for Mock-ups?

If so, what are your short-cuts, speed-ups, and tactics? If not, what do you use and why?

← Prev
Kris Jordan
Kris Jordan
MissionStudentsTeachingThoughts
Connect
YouTubeTwitterInstagramLinkedInGitHub
Copyright © 2022 Kris Jordan