The Devel!

choonkeat on programming & software

Nokia Lumia 800

Finally gotten my hands on the Nokia Lumia 800. It looks gorgeous.

Nokia Lumia 800 Black

Touch

The Metro UI is sleek, and very responsive to touch. In fact, the touch could be described as too sensitive - it often mistaken my “mousedown” (if I may call it that) for a “tap” (as if I’d let go). This isn’t as big a problem in the normal menu navigation; when in the browser I’ll accidentally trigger zoom in/out surprisingly often. Perhaps it is a MSIE thing.

In any case, it is not laggy.

[6 days in] The gesture misreads is getting rather irritating. Reading and scrolling a webpage very often trigger the zooms or even unintended click on links YMMV, but I don’t even think about the worrying about such accidents on iOS; Perhaps they err on the side of less destructive gesture or something smart. Regardless, my experience is that even the original iPhone interprets gestures generations ahead of Lumia 800.

There is also inconsistent treatment of “mousedown” style on links. e.g. In Google Mail tile, the links are helpfully highlighted when “mousedown” - like on iOS. Whereas in People tile, reading a tweet and clicking on a url is tricky - the whole tweet gets a “3d mousedown” treatment (like tapping a wooden plank floating on water) and only when you release then do you find out if you’ve tapped the link or done nothing useful.

Readability

[6 days in] Metro, a typography-based design, renders itself (home, menu, native apps) very well. I’ve initially commented to my wife that the fonts look sharp & I didn’t even miss the “retina display” (unlike when I look at older iPhones).

Sadly, the same cannot be said for webpages in the browser - where fonts tend to be smaller. Text look ugly there.

Web Browsing

[6 days in] On Mobile Safari, if the web page doesn’t render well I’ll [double-tap] zoom & scroll as I read, or I’ll tap “Safari Reader”, if that still doesn’t work I’ll tap my Instapaper bookmarklet & read it later on my Instapaper app. On the Lumia, due to touch gesture issues, the “zoom & scroll” route has 50% chance of taking me through an article. If that doesn’t work, then there’s no redress: No readability feature, no Instapaper app (unless I pay monthly subscription).

With the various faults combined, I’ve caught myself dreading to visit a link, go search for something on the web or generally using the browser. This is quite unlike the general sentiment of web browsing on the iOS.

Transitions

Stark changes to rectangular areas on the screen is often confusing. When tastefully used, subtle animation can help explain to a user where something came from or went (e.g. [dis]appearance of dialog boxes).

In Metro, pages often peek at you from beyond the screen edge, elements at the top/bottom bounces around, and things in the middle often swirl & flip themselves silly, tapping on buttons sometimes give you that a slight vibrating buzz (a poor attempt at tactile feedback).

(Regarding the part where pages peek: unfortunately Metro chose to wrap you around as you swipe toward the page on the right, instead of ending on the “last page”. Thus making it lose all the spatial benefit of having a view port in a big space metaphor)

Though much better than Vista days, I continue to get the feeling that Microsoft interfaces enjoy telling the user, ”Hey, look at ME!” more than removing distractions from the task at hand or leaving limelight for the user’s content.

A case in point is the hardware “search” button. When you want to search for something on the web, e.g. “metro ui”, tap and it will bring up Bing.

The beautiful background photo is sprinkled with tiny animated boxes - if you tap on them, will show you a trivia of some sort. This eye candy obviously speaks well of whoever had put it together, “Look at our new search page, mum!”. However, the task at hand is to search - not marvel at the search page. A better flow would be to bring up the keyboard for the user to immediately type whatever he’d want to search for before he’d forgotten it (which is “metro ui” in the previous paragraph).

Bing Bing, after tapping on search bar

To make it worse, the search button is located below the bottom of the screen, whereas the obvious next step is to tap something at the top of the screen.

What’s nice though, is their sidestep of Apple’s rubber band (bounce scrolling) patent. This might have changed, but I recall Android to have a lame, abrupt halt when a scrolling window reaches the end. Metro, however, implements an equally effective [to Apple’s rubber band] effect by squeezing the height of elements into the edge of the scroll window, like passengers pressing onto each other (and bouncing back) when the train screeches to a sudden stop.

Buttons

Not something I’m conscious of before this, but I realize pick up my phone by the sides. Unfortunately this means I’ll accidentally hit the sleep/wake button on the Lumia 800 - that button is smack in the middle on the right side. A reference for iPhone 4 users, the equivalent would be having that button just above your sim card slot. Yea, go figure.

[6 days in] The issue with a hardware back button is the lack of a hardware forward button (when combined with the fact that websites just love redirecting you to their mobile version).

For example,

Tap on People tile > Read news feed > Tap on tweet > Tap on url in tweet > Loading link > Redirected to mobile version > Page loads

After reading, you tap back to Tweet screen to reply that tweet, but you see Loading link > Redirected to mobile version > Damn, you tap twice but the redirect was faster than you, you’re still at mobile tweet page, then you tap faster, tap.. You’ve tapped too many times and you’re back at news feed screen (or worse: home screen).

Without a forward button, it’ll take you some effort (depending on how far you’ve scrolled earlier) to get back to the correct place, to reply that tweet. Especially since re-entering some of these screens will refresh and thus change positions of items in lists. At this time, it begins to feel like a chore.

[3 weeks in] To make things worse, the “Home button” on WP7 does not bring you back to the Home screen. Instead, it launches the Home screen app. This is a subtle, but important difference to where you thought the “Back” button will bring you.

On more than one occasion, tapping the “Back” button had unexpectedly brought me past the Home screen and [back] into a screen that I’d forgotten about, lost for a moment, and not sure what I’m supposed to do since the screen is totally irrelevant now.

Flipboard

I like the “People” tile. If you’re willing to let Microsoft in to your world of Facebook, Twitter & Google, you’ll basically get a Flipboard phone. Their [addressbook] integration extends into the “Calendar” and “Pictures” tile. Tweeted pictures, Facebook photos shared to you will all show up promptly neatly organized into albums.

I don’t actually have the urge to download a Twitter or Facebook client for this phone. Yet.

It would’ve been even better if the randomly chosen background photo (in Pictures app) could get some just-in-time blur / contrast treatment applied (like Path). Currently, the slim, white text can be a tad difficult to read.

[6 days in] I’m finding the People tile integration / presentation of Facebook newsfeed (which impressed me earlier) to be shallow - messages spammed by friends playing games appears unfiltered, listing purely by recency isn’t as interesting as how Facebook interleave activity, uselessly small thumbnails are also tiring to look through. As a result, I’ve been looking at far less shared videos… which could be a good thing.

Camera

Scenes: auto, backlight, beach, candlelight… White Balance: auto, incandescent, cloudy… Exposure Value: -0.5, 0, 0.5, 1.0… ISO: auto, 100, 200… Metering Mode: Centre Weighted, Frame Average, Centre Spot… Effects: Normal, Black & White, Sepia…

Settings that reads like an actual point & shoot camera. I hate it.

Also, having Press the screen to take pictures = On as default is sure to trip up migrants from iPhone. But maybe they are only trying to poach adopters from the market size leader.

Computer

The phone told me there was software update available, instructing me to “connect to a computer”. Obviously, that simplistic instruction wouldn’t work on my mac. After a bit of googling, I concluded that I need to install “zune” on my mac - which brings me to this page.

The download is a .txt file. Inside the file, is the instruction to go to another URL (itunes.apple.com) to download the app. WTF? Instructions inside a text file? Did they steal that awesome user experience from some random bittorrent site? Where’s my ascii art?

FWIW, Paypal is worse for doing such 302 Redirect with a PDF file.

Copy Paste

[3 weeks in] You tap on a word and the copy-paste icon immediate jumps up. Tapping on the icon will prepend the icon into the list of auto-complete words. Now, whenever the keyboard shows up, the [paste] icon is there, ready for you to tap and paste into the text field. I find this reuse of the existing auto-complete mechanism very elegant.

Select Copy

After pasting once, the icon goes into partial hiding into the left of the screen. Tapping on it will reveal it in full, and tapping it again will paste the content into the text field (and the icon goes into partial hiding again). I find this dance slightly unnecessary, since it doesn’t save a lot of pixels. Moreover, you can “throw” the icon left and it will completely disappear from the autocomplete list and save even more space (only to re-appear when focusing on a new text field)

Also unfortunate, is if you turn off the screen (easily by accident, as mentioned earlier), the clipboard is completely deleted. This is either due to security concerns, or (more likely) due to the need to have a way of free-ing up the autocomplete screen space.

End

The OS appeals to me and I attribute all hiccups encountered to the relative youth of the platform. I’m hoping to use it, at least for the next few weeks, as my full-time phone.

But I sure miss Instagram already.

[6 days in] Though I paid for my iOS Instapaper app, I’m not a paid subscriber for Instapaper, thus no Instapaper app for me; I’m very much missing the relatively new (and relatively minor) feature on iOS: Safari Reader.

Ruby for Rails Beginners

I've been doing this exercise for a few Rails beginners (or non-rubyists who glanced at Rails a bit before) and the general feedback is that they learn Rails but not Ruby, and this is new to them. So I suppose I should just write it down to save future effort.

If you already know Ruby you'd want to stop reading here.

"Computer, book me on the cheapest flight to Mexico for tomorrow!"

The unfortunate thing is, most folks' first contact with Rails will be some short code snippets like

class Comment < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :comments
  validates_uniqueness_of :username, :case_sensitive => false
end

Very succinct. Looks like english and could even appear friendly to non-programmers. It doesn't look "real" and has "toy" written all over it. The jaded programmer will see "config file", "no real syntax", "fragile", "abitrary subset", "haml" (zing!) or "not powerful" as if a guy in grey suit just demoed how he told his computer what to do verbally - "How sustainable can such fake syntax be?". And perhaps beginners might go, "Rails lets me write english-ish code! Wow wee!"

Let's start somewhere else

In mainstream OO languages like Java, you can't really write Java code anywhere you like. "Huh?" Yes, you just don't usually think about it this way. For example you can't simply insert Java code anywhere, say…

System.out.println("here?");
public class Hello {
  public static void main(String [] argv) {
    System.out.println("world!");
  }
  System.out.println("or here!");
}

It's not allowed and you'd get errors

$ javac Hello.java 
Hello.java:1: class, interface, or enum expected
System.out.println("here?");
^
Hello.java:6: <identifier> expected
  System.out.println("or here!");
                    ^
Hello.java:6: illegal start of type
  System.out.println("or here!");
                     ^
3 errors

In Ruby, however, you can write Ruby in weird places:

puts("here?")
class Hello
  def self.main(argv)
    puts("world!")
  end
  puts("or here!")
end
Hello.main(ARGV)

Which runs like this instead

$ ruby hello.rb 
here?
or here!
world!

So? Big deal

Taking another step back, let's look at this Ruby class

class Hello
  def an_instance_method()
    puts("This is inside an_instance_method")
  end
  def self.a_class_method()
    puts("This is inside a_class_method")
  end
end

If you're a programmer you'd have ascertained def defines a method (or function). Now, the difference between def an_instance_method() and def self.a_class_method() is that a_class_method is a class method (or Java programmers like to say "static method") and is used like this

Hello.a_class_method()

which prints This is inside a_class_method whereas an_instance_method is an instance method that you can call on instances of the Hello class,

x = Hello.new()
x.an_instance_method()

So? Big deal

Say we define our Ruby class like this, with a puts statement at the bottom

class Hello
  def an_instance_method()
    puts("This is inside an_instance_method")
  end
  def self.a_class_method()
    puts("This is inside a_class_method")
  end
  puts(self)
end

Running it would produce

$ ruby hello.rb 
Hello

Notice puts(self) has printed the name of our class Hello. This means we are referring to the Class which we're still in process of defining! And since we can refer to it, we can also use it (as much of it as we've defined so far)

class Hello
  x = self.new()
  puts(x)

  def an_instance_method()
    puts("This is inside an_instance_method")
  end
  x.an_instance_method()

  def self.a_class_method()
    puts("This is inside a_class_method")
  end
  self.a_class_method()
end

Running it would produce

$ ruby hello.rb 
#<Hello:0x0000010084f778>
This is inside an_instance_method
This is inside a_class_method

Notice how instance x obtains an instance method after the fact! Let's clean up our class: rename it as User, and rename the class method to validates_uniqueness_of, and add some arguments to the class method…

class User
  def self.validates_uniqueness_of(what, options)
    puts("This is inside validates_uniqueness_of #{what} and #{options}")
  end
  self.validates_uniqueness_of('username', Hash['case_sensitive',false])
end

The #{blah} syntax is string interpolation, allowing Ruby code to run within a string, like "Five plus One is equal to #{5 + 1}". So, running this file would produce

$ ruby hello.rb
This is inside validates_uniqueness_of username and {"case_sensitive"=>false}

In Ruby, Hash objects (or associative arrays) can be defined literally as {'case_sensitive'=>false}; (brackets) and {curly braces} are largely optional; self is implied; You can also use :symbols to denote things you'd usually use enums or constants for

class User
  def self.validates_uniqueness_of(what, options)
    puts "This is inside validates_uniqueness_of #{what} and #{options}"
  end
  validates_uniqueness_of :username, :case_sensitive => false
end

We can use the < syntax to denote inheritance and define the class method elsewhere

class Base
  def self.validates_uniqueness_of(what, options)
    puts "This is inside validates_uniqueness_of #{what} and #{options}"
  end
end

class User < Base
  validates_uniqueness_of :username, :case_sensitive => false
end

We could stash more methods into our Base class

class Base
  def self.has_many(what)
    # some code
  end
  def self.validates_uniqueness_of(what, options)
    # some code
  end
end

Or we could use Mixins to organize them neatly into standalone modules and compose them together

module Relation
  def has_many(what)
    # some code
  end
end

module Validation
  def validates_uniqueness_of(what, options)
    # some code
  end
end

class Base
  extend Relation
  extend Validation
end

Either way, we can now have something that looks familiar

class User < Base
  has_many :comments
  validates_uniqueness_of :username, :case_sensitive => false
end

So you see, the toy looking code is not Rails-specific, nor is it some limited-capacity syntax for PPT & luring beginners.

Came for Rails? Stay for Ruby

And that's it. If this has piqued your interest, you might want to investigate how Ruby lets Rails get away with the syntax of config/routes.rb and how Ruby makes has_many and validates_uniqueness_of possible to implement.

Giving Feedback on a Design You Are Paying For

Disclaimer: I’m not knowledgeable in this area, but am interested to know what’s up. Please feel free to correct my misconceptions.

“Make this blue”, “Too big”, “Bigger”, “Darker”, “Too narrow”, “Put the logo here”

I find it hard to comprehend why anyone paying good money for design, would review in this manner. Over and over, round after round. Sounds more like a person trying to work Photoshop with voice control. Shouldn’t we let the skilled worry about their craft? If your designer doesn’t know design better than you, why there is a business relationship?

On the back of such encounters (as an onlooker), I had concluded [mistakenly] that having multiple rounds of design reviews was just masturbatory and that a customer should only focus to communicate the whys clearly and leave designers to do their job.

Yesterday, 37signals posted another “Behind the scenes” article on their blog. As I was reading their recap of multiple iterations and feedback, it occurred to me that my conclusion was misdirected. There’s nothing wrong with the fact that there were multiple rounds of review. My issue was with the nature of the critiques.

The feedback for each round were about story, intent, clarity. Not pixel pushing. Seems to me, that is how a money paying customer should be reviewing to get his money’s worth.

Loremipsumizer

I had the need to show some folks example screens of webapps I’m working on recently. Using those screenshots, the other party could have a better feel of things, we could have a clearer discussion. But the irritation [for me] is always the setup

  1. The app I’m working on is still in flux, i.e. design & data attributes will likely change, often
  2. The content I have is often imported from real data sources, and hence is somewhat private & sensitive
  3. I’m too lazy to think up fake names, fake scenarios, fake photos to fill my database, just so I could have a fragile, demo screenshot (I’d need to redo / update later)

What I’d really like is

  1. To be able to use my current webapp, as-is
  2. To be able to use my current data, as-is
  3. To protect private & sensitive data

Smells like a bookmarklet? So here it is Loremipsumizer.js. After installing it, I can anonymize any webpage instantly (then take a screenshot, annotate or print & discuss with somebody else, without worrying about the sensitivity of content)

Click here to try it on this webpage!

The Loremipsumizer will anonymize all text, scramble all numbers, replace images, flash embeds (& video tags?) with wireframe-ish cross-boxes (via data uri). Unfortunately I didn’t have an elegant solution to anonymize background images (css sprinting, image size, etc) so I’ll need suggestions there.

In any case, here are a few screenshots of webpages I’ve anonymized. No prizes for guessing which websites:

Note: Loremipsumizer does not require any JS library, and have not been tested on irritating browsers. Patches are welcome.

FOAF Rewards

The Joneses is an interesting idea: if you push product placements all the way to 11, you'd have it done in real life. But how do you attribute a [growth in] sale of product P, to the "Joneses" team member? Target market of product P + geography of the sale? And what if the network effects is far reaching and has no geographical boundary (i.e. internet)? So, no two "Joneses" teams should pimp the same product? No good.

What if we try something more pre-emptive, using something more direct - FOAF. So when customer Charlie buys Product P, your CRM picks up that amongst other customers who bought P, customer Betty is in Charlie's FOAF network (Facebook, Twitter, email, blog, flickr, etc).

With this knowledge, you could directly credit Betty a referral reward and hope to gain an army of MLM team. But this risks displacing Betty's original reason of buying your product with a weaker, extrinsic motivation.

Alternatively, you could credit Betty with a discount on her next purchase. This approach is good and already exist informally. But it is also unsurprisingly inefficient in its current state: the connection happens if you manage to make the sales assistant remember you and they bother to inquire about referrals when serving a new customer.

Wouldn't it be great if a hypothetical "iCashRegister (now with FOAF)" exist to make this more efficient?

To cap the potential hemorrhage of "discount credits" on heavily connected customers, if there are several customers connected to this new customer, they'd only each get a slice of the credits. Also, for some business, it might make sense to attribute a referral based on the transaction of the same product. For other businesses, it might make sense to attribute a referral based on purchase recency.

So now any customer connected to a subsequent customer gets discount credits. And all this can happen regardless of whether (you) the business owner is servicing the customer, or if it was just your part-time sales assistant in the shop.

To hell with wimpy loyalty cards. Why isn't your business using "iCashRegister (now with FOAF)"?

Update: Do check out Anafore if you're interested in this topic!

You're Doing It Wrong - ACM Queue

What good is an O(log2(n)) algorithm if those operations cause page faults and slow disk operations? For most relevant datasets an O(n) or even an O(n^2) algorithm, which avoids page faults, will run circles around it.
the results coming out of the CS department would be so much more interesting and useful if they applied to real computers and not just toys
- Web annotation on You’re Doing It Wrong - ACM Queue

Since @replies Can Come From Anybody

Someone, let's say Yahoo, could roll out their own twitter-like service (let's call it yatter). And all yahoo mail users "become" yatter users automatically, like how they became Openid accounts.

  1. when a yatter user "joe" yatts, "@twitter/charlie what are you doing?"
  2. yatter's twitter bot called "yatter" relays the tweet, "yatter/joe: @charlie what are you doing?"
  3. twitter user "charlie" sees the message in his @replies stream, and can respond, "@yatter/joe hitting my refresh button again and again"
  4. a yatter.com bot called "twitter" relays the message, "twitter/charlie: @joe hitting my refresh button again and again"
  5. yatter user "joe" sees that in his @replies stream in yatter.com.. (repeat from the top)

I'd guess it makes sense for yatter apis to be fully compatible with twitter.com, in the ma.gnolia.com vs del.icio.us kind of way. So twitter clients just need to add a new config, "hostname", and we're done.

I think yatter.com could technically allow @yatter/joe to follow @twitter/charlie. The question is, would twitter.com allow their @charlie user to follow @yatter/joe?

Yatter could use the age-old hotmail trick and append the latest status message of the mail sender to the email footer. That should pique interests of recipients. Besides, "a signature" is an existing, understood concept that users can easily see why they'd would want to update their "yatter status"..

An iPhone Optimized Web Page

[UPDATE: Proof of concept no more, RssPaper is now in the store!]

The defacto way of making a web page "optimized for iPhone" is to slap on iUI (or variants) to simulate the look & feel of a native app (i.e. the UITableView). You can click on an item in the list, and the page slides sideways to reveal another list, or more details… etc.

However, the starting point of trying to mimic meant we're aiming for the web site's experience is to be worse-or-almost-as-good compared to if it was a native app. e.g. m.cnn.com Can aim to be different instead?

In trying to mimic a native app, the iUI approach locks down the browser's width & scaling capability. I actually liked that part of browsing on the iPhone – its automatic zoom! To zoom-in, you simply double-tap on an area of the page. To zoom out, double-tap again. (There's pinching, but it is manual & I don't like tedious things)

Unfortunately, most layouts don't make it easy for iPhone to automatically zoom-in. The kicker is, a good & fluid CSS layout actually hinders! e.g. the text is still small after double-tapping on jnd.org

Turns out, the automatic zoom is controlled [only] by the width of the page segment.. meaning, the page's font size can be infinitesimally small – it doesn't matter. As long as the containing width is also small (e.g. contains 5 words across 1 row), the user can still comfortably zoom in and get big text with sharp font of 5 words across the entire screen width!

Taking this to an extreme, we could have all our site's content render in tiny little font inside narrow columns on 1 single page and the iPhone visitor can still effortlessly zoom in and read everything! No click, ajax, network lag, read content, back, click another, .. etc.. i.e. instead of content hierarchy behind deep navigation, we could have it based on font sizes.

Sounds like a newspaper huh?

To try this out, I'd hacked up this proof-of-concept a few days ago, and have been using it to read my RSS feeds on my bus rides the past few days. While the app itself is not there yet, the zoom interface experiment has really been working out very well!

screenshots

Have an iPhone/iPod touch? Try it and lemme know?

PS: A more extreme sell for a zoom-based UI is Microsoft's famous Seadragon demo.
PS: this whole experiment was sparked off when I tried to read the beautiful hacker-newspaper.gilesb.com on my iPhone.

9.99 Reasons to Love IE6

A friend showed me this website today: http://www.bringdownie6.com/ "Bring down!" Such angry words. There's so much negativity on the Internet regarding a browser.

Instead of 1) getting good folks to put feeble badges on websites, or 2) resigning to fate & cursing whenever you have to fire-up IE6 and check, or 3) getting bigger, better tools to do stupid things faster… Maybe we can be more constructive.

Here's an idea:

Dear Developers & Designers,

Save your sanity: At $0.00 cost to you, we make your website work in IE6!

Step 1. Register your website with us
Step 2. Just copy-paste this into your website's <head> section: <script src="http://weloveinternetexplorer.com/bff.js"></script>
Step 3. *chuckle* There's no Step 3!

How this'll work is that, all your IE6 site visitors will be gently redirected to our payment page, explaining nicely:

We're sorry but Website XYZ no longer works with your old, antique Internet Explorer browser. BUT for just US$9.99/month (1 movie ticket!) the hardworking engineers at weloveinternetexplorer.com will fixup the website for YOU, and make this problem go away for you! It'll just take 30 seconds! We accept all major credit cards & Paypal (maybe even 淘宝! Alipay (correction by @xtinegoh) )

But you choose not to :-( you may install any of these free, modern browsers and use Website XYZ through them: [firefox logo] [safari logo] [google chrome logo]


WeLoveInternetExplorer.com Team

If the IE6 compatibility work has not been complete yet, the above pay-wall will not be shown. Instead, we'd display a cool 1990s construction worker icon that these folks will be extremely familiar with!

Construct2_e0

All paid users can of course transparently continue to use the web site (and all other websites that uses this service).

PS: Designers & developers that would like to do Internet Explorer compatibility work (yes, all 3 of you out there, 尤其是中国的同胞朋友, Hội lập trình viên Việt Nam, and сотрудник российских программистов !!!!) Please contact me