Software As She’s Developed

Mahemoff’s Podcast/Blog – Web, Programming, Usability from the Author of ‘Ajax Design Patterns’ (AjaxPatterns.org)

Software As She’s Developed header image 1

Letters from a Gaming Newbie

July 26th, 2010 · SoftwareDev

I was pleased to attend Casual Connect this week and talked about how HTML5 is becoming viable for games development, alongside my colleague Mark, who covered the Chrome Web Store in general. I was definitively there in a purely web geek capacity, as gaming is not an industry I’m very familiar with. So here are a few things I learned:

  • Casual gaming is quite distinct from “hardcore” gaming. (as @Eastmad reminded me on Twitter.)
  • Casual gaming is heavily intertwined with “social” gaming these days – games on Facebook et al.
  • The social network is just “the graph”. At least for some games, they’re architected to separate “the graph” from the core game logic, so you can swap in and out different social networks. The graph is of course essential for gameplay with social games as well as viral adoption.
  • The industry is mature – there is a clear ecosystem of companies with different roles. Studios make games, publishers distribute them, portals aggregate them, social networks provide the graph. And then there are ad networks, analytics, hosts/caches, development tools, virtual currency providers, consultants. (Very cool seeing how any vertical quickly evolves into a distinct industry structure. Adam Smith approves.)
  • The industry is sophisticated. There is a big aspect of number-crunching, analytics-driven, thinking, e.g. pinning down the cost of customer acquisition. There’s a feeling that monetization is the best growth opportunity right now, more so than increasing the number of players. 1-2% of people spend, whereas with Massive Multiplayer Online games and in Asian markets, 5-10% is more common.
  • Trends to watch: Streaming games (Gaikai, Onlive) – It’s amazing it actually works, but these are technologies that treat the user’s computer/browser as a dumb terminal and stream the game’s video down to them; location based games, merging real and virtual worlds; embedding games into the fabric of the web (e.g. through widgets etc), so they’re not just isolated in social network sites and dedicated game portals; combining genres, so that hardcore gamers can interact with their casual gamer friends; using multiple channels in clever ways, rather than just porting the same game to ten different platforms.

→ No CommentsTags: ···

Thinking in Web Apps

July 24th, 2010 · SoftwareDev

Thinking In Web Apps is a short list of design principles for Chrome Web apps, published a couple of weeks ago by several of us in Chrome Developer Relations.

Many people think Developer Relations means blogging and speaking. That’s part of it, but it’s also important to be spending time with developers and understanding the challenges they face, as well as supporting them. In the case of Chrome Web Store, I’ve been working with several partners who are building apps in time for the store’s launch. Explaining how certain technologies work and taking questions back to the core Chrome development team. One of the things I’ve discovered in Developer Relations is the way patterns/principles emerge:

  • A new capability is announced, e.g. a new programming language, an upgrade to a hosting service, a new API. In this case, it’s the Chrome Web Store and the concept of installable web apps.
  • We make some guesses about how to use it and share them with developers. You have to see it as educated guesses; it’s the law of unanticipated consequences that says you can never be sure how people will use a capability, even if you’re the one who designed it.
  • Developers start to build use the new capability.
  • By aggregating across all of the pioneering developers, and talking to other developer relations people working with other pioneering developers, we gain a new appreciation of what works and what doesn’t.
  • We have more general info to share with partners. Wash, rinse, repeat.

The important thing is to be documenting what we’re learning as we go along, hence you can expect to see more articles like Thinking in Web Apps. Whether you want to call them patterns, principles, or whatever.

See also Task-Artifact Cycle.

→ No CommentsTags: ·

Video Sync with WebSocket and Node

June 18th, 2010 · SoftwareDev

Wanting to explore WebSocket, I made a demo that syncs videos for all users looking at the page (See the Code). Any user can "take control", so that the other videos will follow the controller's video. Writing it was a cinch with the Javascript WebSocket API in the client, and the very straightforward Node WebSocket Server powering the server.

Note it's just a simple demo - there's no security model here and there's a very simple sync mechanism: When a "slave" client receives the latest duration, it adds a second to account for lag, and moves the video iff there's a 5-second discrepancy.

How does a WebSocket client look? Well, it looks a lot simpler than a traditional Comet client. Initiate the connection with "new WebSocket":

JAVASCRIPT:
  1. var conn;
  2.   $_("#join").onclick = function() {
  3.     conn = new WebSocket("ws://localhost:8000/test");


Upload a message to the server with send():

JAVASCRIPT:
  1. video.addEventListener("timeupdate", function() {
  2.       if (iAmControlling()) conn.send(video.currentTime);
  3.     }, true);


Receive a message from the server with conn.onmessage():

JAVASCRIPT:
  1. conn.onmessage = function (ev) {
  2.     if (matches = ev.data.match(/^pause (.+)$/)) {
  3.       video.pause();
  4.       video.currentTime = matches[1];
  5.     }
  6.     ...
  7.   }


And when it's time to draw the curtains, close the connection with another one-liner:

JAVASCRIPT:
  1. $_("#leave").onclick = function() {
  2.       conn.close();
  3.       ...
  4.     };


The server is also rather tiny. It mostly just broadcasts (sends to all clients) any incoming message and it's up to the clients to deal with it. Which is why I say there's no real security model here.

As you can see in the above snippets, "video" plays an excellent cameo role here, with its equally simple API. One downside, which others have mentioned too, is the lack of styling in the default video controls. It's great the API supports automatic controls, but it's unfortunate there's no CSS manipulation. In this case, the "slave" browsers should be able to see the time, but not have the ability to change the progress. I hope this changes in the future, because the API is otherwise very powerful without compromising simplicity. Until then, libraries will arise to fill the gap.

The demo works in both Chrome and Safari (and they play nice simultaneously).

→ 3 CommentsTags: ···

Using BrowserScope to Detect Geolocation Support

May 27th, 2010 · SoftwareDev

About Browserscope

Browserscope is a very cool tool coming out of Steve Souders' performance efforts and being developed by Steve along with Lindsey Simon. It's part of a trend towards crowdsourcing browser info, in similar vein to TestSwarm, for testing specific code, and along the lines of what I did with WebWait, which is to support multiple people benchmarking a website at once. (Though I've not set up reporting on it - one day...)

So anyway, Browserscope began life as a way to benchmark just performance, but is now a general-purpose tool for crowdsourcing tests about anything browsers do, e.g. checking for security vulnerabilities is one vital application. HTML5 does not miss out - HTML5Test.com has been ported over too - see beta.html5test.com.

Geolocation Test

I decided to make my own test recently, to see what extent Geolocation is being supported by the browsers. Run the test against your browser here (it will upload only information about whether geo is supported, not your actual geolocation data):

http://test.mahemoff.com/geo.html

The results so far indicate browsers either don't support it, or support accuracy+lat+lon. I was hoping to see at least direction, and would <3 to see altitude! But it will have to wait.

How to Make your Own Browserscope Test

If you ever wanted to know how every browser under the sun handles a particular something, Browserscope is your new hotness. It makes it trivial. Register with Browserscope to get the boilerplate code. Then you just write an app that does the exercises and builds up a hashmap of the info you want to collect, and BAM, submit it. The hashmap should have values between 1 and 1000. Do that, and you'll end up with a nice summary page showing your test results aggregated across all browsers that ran them.

The submission is taken care of by some boilerplate code - it uses on-demand Javascript to pass the data back to the third-party BrowserScope domain (you host the test yourself). Aside from writing the actual test and promoting its location, the only thing you have to do is make a nice UI to show the users what you just did, and perhaps get their consent before uploading. I think those are actually two things Browserscope could automate too, at least providing a nice default UI which test creators can customise.

→ 1 CommentTags: ·····

Another HTML5 Tidbit: Web SQL Database

May 27th, 2010 · SoftwareDev

I coded up a small demo of Web SQL Database. As the demo points out, notice you can hit reload and the data remains, being that it's one of the several techniques for offline storage.

There's not much to say about Web SQL - you either know SQL already, in which case it's fairly straightforward and just a matter of squeezing your SQL calls into the conventions of the API, like any other SQL framework as, lamentably, there's never been any kind of standardisation on the wrappers that go around SQL - or you don't know SQL, in which case there's your bottleneck child if you intend to use Web SQL Database for offline storage.

Web SQL Database lies at the other end of the complexity spectrum from Web Storage (aka localStorage and sessionStorage), which is simply a big ol' hashmap for your domain. The complexity is fairly manageable, though, as there's literally a generation of SQL know-how out there, and hopefully ActiveRecord-like libraries on their way.

IndexedDB promises to offer a third way - more like the hashmap approach, but with some of the indexing-based performance gains SQL has to offer. No browsers have implemented it yet, though you can build an experimental windows version using a third-party Firebreath implementation.

→ No CommentsTags: ····

Upcoming: UXCampEurope and SWDC

May 22nd, 2010 · SoftwareDev

Google I/O is over and I'll post a bit about the HTML5 hack session I ran later, but here I want to highlight a couple of upcoming sessions in Europe:

UXCampEurope. If this is anything like the Bay Area and London UX camps I've been fortunate to attend, it will be huge, and being Europe-wide and in Berlin, this expectation might just be met. I was sitting on the browser along with @mattlucht hitting refresh 10 times a second when the tickets were released at the start of the year! I'll set up a slot called "What did HTML5 ever do for users, anyway?". I'm planning to overview some of the features of HTML5 and its evolution from Ajax, and ask how it might be used to improve UX. It's a camp, so I'll also be hoping to collect contributions and writing them up somewhere.

SWDC. The first Scandinavian Web Developer Conference and Peter Svensson is organising, so I know it will be an awesome event, and the sessions speak for themselves. I've bumped into the guy twice in the past month - he travelled from Stockholm to DC for JSConf, and again to SF for I/O. My session is on the mobile day, called "HTML5 Gives You Wings", focusing on HTML5 techniques for performance and app-like behaviour. Here's the summary:

Welcome to the dynamic world of mobile development, where new browsers stay close to the edge and HTML5 is already a reality. Despite the impressive advances, many mobile apps are still bottlenecked by the network and compact processors continue to lag behind their desktop counterparts. So how can HTML5 help? This talk will focus on those features of HTML5 that are interesting for performance optimisation and the techniques for emulating native apps, such as offline data storage.

→ No CommentsTags: ········

Offline Apps with Application Cache: Quickstart, Tips, and Deep Dive

May 19th, 2010 · SoftwareDev

I've been mucking with AppCache, aka ApplicationCache. It's the secret sauce that lets you build offline apps, which is great for performance and fabulous for pretending to be an iPhone app when you're not.

Quickstart an Offline App

As with most HTML5 technologies, the basic usage is quite simple:

  1. Create a trivial trio of HTML, CSS, and JS files, maybe with an image or two. (Or reuse an existing toy app.)
  2. Link to a "cache manifest" file from your HTML file's html tag like so:
    HTML:
    1. <html manifest="clock.manifest">

  3. Make the manifest file. It's just the literal phrase "CACHE MANIFEST" on the top line (I know, bit random), followed by the list of files in your app:
    CACHE MANIFEST
    clock.html
    clock.css
    clock.js
    clock.png
    
  4. Mark it as MIME type text/cache-manifest. If you're SSHing to a virtual host (like I did with Dreamhost), all you need here is a one-line .htaccess file:
    AddType text/cache-manifest manifest
    

That's it. Now those files above will be cached locally and won't need to be downloaded again next time. To test it, load the site, shut down your net connection, and reload. It's still there innit.

It works the same on your app-phone - on iPhone or Android (or others maybe), load the site, switch to airport mode, go back to the browser and reload ... the site's still there. Where it gets really fun is making it into a regular app:

  • On iPhone, bookmark the site with the Safari "+" button, choose "Add to Home Screen", and the app will be sitting alongside all your other apps on the home screen.
  • On Android, bookmark the app in the browser. Hold your finger down somewhere empty on the home screen, choose add "Shortcuts" | "Bookmark", and choose the bookmark you've made.

You could do the same with any website of course, but it's particularly cool when the website is an offline one...it works just like a regular app!

Practical Tips and Troubleshooting

Purging the Cache

In practical terms, you are quickly going to come up the no. 1 problem of developing against a cache. How do you purge it whenever you update your code?

Simple. You only need to make an arbitrary change to the cache manifest file, so just include a version number in the comment:

CACHE MANIFEST
# v1
clock.html
clock.css
clock.js
clock.png

Keep revving it up every time you change any file, because changing those files alone won't have any effect. And if it's getting serious, you'll want to practice the principles of DRY and continuous integration by automating this process.

Ridding yourself of Errors

An unfortunate thing happens when there's a downloading error: The whole thing silently fails. Until debugging tools get better, if you find your app's not updating, you ought to check each of the resources specified in the manifest really, really, carefully.

Cached Resources

Cache manifests are not exempt from standard caching rules, so the manifest itself, as well as other files might be cached. Pain. A good solution is to use the following Apache directives to .htaccess:

ExpiresActive On
ExpiresDefault

That MIME Type

Things might fail if the Cache Manifest MIME type is wrong, so use your browser's debugging tools or a service like Web Sniffer to check it (thanks CSS Ninja).

The Wording

The wording can also trip you up. Be really sure it's exactly "CACHE MANIFEST" at the start of the file. Again, better debugging tools in the future will help here.

The Fancy Stuff

All of the above is enough to get up and running with an offline app, and maintaining it too. But wait, there's complexity too!

Fine Control Over What Gets Cached

The cache manifest file actually allows three kinds of resources:

  • Online resources that can be cached (CACHED). As shown in the example above, it's the stuff that's available for caching.
  • "Fallback" resources in case a file isn't cached (FALLBACK). These are like catch-all email addresses; any resource that's not cached, is a candidate for a fallback. There's a pattern-matching algorithm to map resources (which mightn't have been cached) to other resources (which hopefully have been cached). For example, you probably wouldn't cache every wikipedia article, so the fallback section would ensure a special "offline.html" page is shown for those missing articles.
  • Online-only resources (NETWORK) Resources which should never be cached, e.g. it would be a good idea not to cache stock prices if people were making million-dollar decisions on the back of what they see on your possibly-cached web application.

The syntax (adapted from the WHATWG example):

CACHE MANIFEST
# a comment
# v37
# (version number unnecessary
# but recommended for cache purposes)

# the following "CACHE:" is optional; # a special case because top of file # is cache by default # CACHE: images/sound-icon.png images/background.png # note that each file has to be put on its own line

FALLBACK: / /sorry-i-am-offline.html

NETWORK: /stocks/*

Checking if We're Online

window.navigator.onLine ... try it now in your console (and try it again with your connection off).

Monitoring State and State Changes

What do you notice about all the app cache stuff above? It's all declarative, no Javascript. But you can go on to do extra stuff with Javascript too, via the Application Cache API. (I am somewhat skeptical about the applications for this API, since simple and declarative is the way to go for something as potentially hairy as offline...but that's for another rant.)

The window is effective tied one-to-one to the cache object, so you can just access the cache with window.applicationCache. For example, you can get cache state with window.applicationCache.status, try it now in your console. It will probably be zero...the possible values range from 0 to 5, representing: UNCACHED, IDLE CHECKING, DOWNLOADING, UPDATEREADY, OBSOLETE. (These constants are also available on the cache object, i.e. window.applicationCache.UNCACHED is 0.)

There are also event handlers to monitor event state: onchecking, onerror, onnoupdate, ondownloading, onprogress, onupdateready, oncached, onobsolete.

Forcing Updates

applicationCache.update() will force an update, i.e. start downloading the application again if the manifest has changed. However, it won't suddenly switch over after downloading. To do so would be to pull the rug from under your live, running, application. It will be there next time. But if you do want it right away, use applicationCache.swapCache().

Offline Mobile Apps: It's More than Application Cache

Application cache certainly is a critical feature of mobile apps; it's a basic user expectation that a mobile app starts right away, unlike a complex web app which must be downloaded. However, there are other things too. For example, offline storage. That's another feature of HTML5, comes in many incaranations, and something for another day. The other really big deal is the UI. Of course, you need to simulate certain UI features of the native apps if you want your web app to go native. Hence, libraries like IUI, jQTouch, and Apple's secret PastryKit. On the input side, your UI must also handle touch events, something some of the aformentioned brand of libraries will support. Finally, there will be specific features of the platform that can help; for example, setting the home screen icon and going full-screen so the browser chrome doesn't show up.

→ 5 CommentsTags: ··

Cached Positions in the Geolocation API

May 4th, 2010 · SoftwareDev

The Geolocation API is surprisingly short and simple. A simple lookup is a doddle:

JAVASCRIPT:
  1. navigator.geolocation.getCurrentPosition(function(position) {
  2.   alert("You're at " + position.coords.latitude + ","
  3.           + position.coords.longitude);
  4. });


About the most complicated thing is "cached positions", and even those are quite straightforward. So what's that all about?

A cached position is what the API returns when you don't need a live, "this is where the user is right now", position. Geo-lookups can be time-consuming, so sometimes you might opt for a slightly stale location instead of making the user wait for a lookup. You might also be helping the user to reduce battery life or bandwidth consumption.

In the simplest usage, a real lookup will always occur:

JAVASCRIPT:
  1. navigator.geolocation.getCurrentPosition(showMap); // no options? no cache for you.


However, you can also say "I'll happily accept a location from the past minute (60,000 ms) if you know it"

JAVASCRIPT:
  1. navigator.geolocation.getCurrentPosition
  2.   (showMap, handleError, {maximumAge:60000});


Set maximumAge as Infinity (a valid Javascript literal) to say "just give me a cached value you cached any time, I don't care how far back".

Using a second timeout parameter, you can force the position to be cached, i.e. prevent a lookup altogether, even if there's no cached value, in which case you get an error.

JAVASCRIPT:
  1. navigator.geolocation.getCurrentPosition
  2.   (showMap, handleError, {maximumAge:60000, timeout:0});


(The spec uses "position" and "location" interchangeably; ideally a spec like this would use a single term, but at least in this case they do mean almost the same thing.)

→ No CommentsTags: ·

HTML5 is a Brand

May 3rd, 2010 · SoftwareDev

HTML5 has conflicting definitions.

If you go by the official WHAT-WG spec, HTML5 is a list of specific features, including Canvas, Video, Audio, the new form controls, the new semantic markups, and microdata.

If you go by the media and Steve Jobs, HTML5 is simply a new platform that lets us do rich, interactive, applications without the need for the desktop, or browser plugins. This definition implies a superset of the WHAT-WG HTML5 features. As the HTML5 spec notes, the following are frequently confused as being part of HTML5:

  • Web Workers
  • Web Storage
  • WebSocket API
  • WebSocket protocol
  • Server-sent Events
  • Web SQL Database
  • Geolocation API
  • SVG
  • MathML
  • XMLHttpRequest

The spec says it's the media who confuse those items; I'd say it's just about everyone who doesn't read Last Week In HTML5 (NSFW) religiously, i.e. most people. Furthermore, I would add the following delicious ingredients to the HTML5 mix:

  • CSS 3
  • ECMAScript 5

And now that we're getting real, as far as most people are concerned, HTML5 is about what the technologies do for end-users. So I'll add the following, which all have an impact on programmer productivity and hence indirectly improve the user experience by making development more agile and effective:

  • Javascript libraries and frameworks
  • Web Development Tooling
  • Web Development Theory (guidelines, principles, hacks, "browser physics", patterns)

And I'll also add the containers in which web apps run, where features such as add-ons and improved security are also making things more splendid for users:

  • Browsers
  • App wrappers (PhoneGap, Titanium, Air)
  • Operating Systems (WebOS, ChromeOS, Yahoo! TV widgets, Web Widgets

And in addition, there are the anticipated features, which the HTML5 spec says will come with a later version, but are still considered by many to be the promise of HTML5:

  • Device APIs (microphone, webcams - these can't come sooner!)
  • Ping attribute

If you want, you can stick your head in the sand and declare "HTML5 is the limited subset of technologies addressed in the WHAT-WG specification". However, the ship has already set sail and thanks to the ongoing Apple vs Adobe saga, HTML5 has been deeply etched into the fabric of the industry as "the technology that makes rich web applications". HTML5 is now a brand referring to all of the things mentioned above. Better get used to it.

→ 5 CommentsTags: ··

Audio/Video Tag: Don’t Forget to load() before you play()

April 30th, 2010 · SoftwareDev

This is a gotcha that will catch a lot of people out because it goes against the expectation that you just change an image's appearance by setting its "src", done. And also, it's a deviation from the more general convention that you change DOM properties declaratively to make stuff happen. Probably for good reason, given the temporal nature of audio and video playback, but just beware it's a different model.

Bottom line is - load() between changing src and play()ing:

JAVASCRIPT:
  1. function play(url) {
  2.   var audio = document.querySelector("audio");
  3.   audio.src = url;
  4.   audio.load(); // !HUL|_O! PAY ATTENTI0N!
  5.   audio.play();
  6. }


A lot of online sources talk about play() and omit to mention this vital fact, because they're only play()ing a single track...and the first track works fine. This is an oddity - you can just call play() the first time and it will automatically load. This happens whether you set "src" in the initial HTML's "audio" tag or whether you set it programatically. I did some fiddling and it looks like the behaviour is the same in Chrome and Firefox. It's like the track is auto-load()ed the first time you set its source. (And note that Firefox doesn't auto-buffer so that's nothing to do with it.)

devx has you covered on this topic, and points out the subtle issues which you would need to look at for a quality production:

However, media by its very nature is a time-spanning process. You're working with both the need to load and cache audio and video files and the network connection, which itself can prove to be a challenge that's usually not a factor for most non-temporal resources. For these reasons, when dealing with video and audio on the web, if you want to take control of the process in any way, you have to work asynchronously, tying into the various events that are passed back to the client from the media-serving website. Table 4 (taken directly from the HTML 5 documentation) provides a full listing of the various events and when they are dispatched. ... Of all the events in Table 4, perhaps the most useful are the canplay and canplaythrough events. The first, canplay, will fire when enough data has been loaded for the video player to start actually rendering content constructively, even if not all of the data has been loaded. The canplaythrough event, on the other hand, will fire when the data has essentially completely loaded into the browser's buffer, making it possible to play the video all the way through without the need to pause and retrieve more content.

→ 2 CommentsTags: ···