Responsive web design: a response

Earlier today, Martin Beeby, a developer evangelist over at Microsoft, posted a blog about how responsive web design is the solution to developing rich web experiences across a multitude of platforms, and how designers are probably thinking about "just" desktop (browser) and mobile (cellphone), and need to think more in terms of other devices - iPads, interactive TVs, and so on.

He mentions three staples that Ethan Marcotte (the guy who coined the term "responsive design") wrote about in his book, coincidentally titled "Responsive Web Design" (ingenuitive, huh?). Of those three, one is media queries - the @media directive that's been around in CSS2, but has only now been started to touted as "CSS3" in recent years, with improved browser support for window size detection.

Now, I find @media queries useful and great when you're building CSS to target multiple devices - it allows you to set out base styles that enforce brand consistency across your design, and then simply adjust positioning for various devices - I get the concept, and I think it's a great idea. However, there's a big caveat about @media queries which gives me a particularly large cause for concern.

I run a business which deals with a lot of small customers - and having patched Umbraco to work in cheap hosting, I recognise the commercial aspects of people being on a very tight budget - I was there, after all, it's what prompted my patches.
However, throughout the design and build process of a website, there needs to be consideration for this very simple fact - bandwidth is fast becoming expensive and a limited resource.

I recently quit Vodafone because they removed my 5GB data bolt-on without telling me, and then all they offered as a replacement was a 2GB one (3GB if you have an iPad). Most domestic broadband providers cap usage, or have a "fair use" policy which constrains to an average of 40GB - when I Google'd, only four companies had truly "unlimited" packages (and some of these are also documented to use traffic filtering at peak periods - Virgin's XXL Package, for example). The average page size of Alexa's top 500, as of May '11, is fast approaching 700kb, and the one bit that people who tout @media as the answer to everything don't tell you is: your entire stylesheet, with resources, images, the works - for all viewports - is loaded, before the @media stuff is parsed by the browser.

Yes, you read correctly - everything gets loaded, regardless of the device you're looking at a page on, prior to @media being parsed by the browser. This means if you're on a mobile device which should be served up maybe 50kb of page and image, you'll get all 700kb of the desktop page too. Conversely, if you're on a desktop, you'll get 50kb of unnecessary mobile stuff downloaded for no good reason. Let's quickly work out how this breaks down:

  1. Mobile with 2GB data bolt-on - means you can browse approximately 2000 ~700kb pages before you cap out at your limit. That's less than ten a day for a month. Add in the fact that if you own a Smartphone, you can kiss goodbye to several MB a day if you have Twitter, Facebook, Foursquare, etc. all hooked up and running in the background.
  2. Home broadband package with 40GB allowance (which is the top end of most broadband companies, with exceptions already noted): you can browse ~60,000 pages a month, or ~200 a day. It is a drastic improvement by 20-fold, but homes now normally have more than one PC, and if your kids are Youtubing, or you're using something like BBC iPlayer/ITV Player/4OD, then you're going to cut into that limit pretty quickly.

These figures don't take into account caching, which the link above notes cuts back on average response sizes of the top 500 home pages from >500kb to <100kb - an 80+% saving. However, cellphone and portable devices, whilst improving, are notorious for having pretty crappy memory capabilities, and caching takes time to implement in a robust policy (since I build on Umbraco, I of course am biased to recommend using the included ClientDependency library, originally built by Aaron Powell at Redify and Shannon Deminick at Umbraco HQ, both formerly of TheFARM Digital in Oz).

The main issue here is that on your mobile, if you're browsing a site that uses responsive desgn to handle multiple devices, you're wasting in excess of 80%, maybe even 90% of your visitor's bandwidth just for them to view your site. For desktop viewers, it's more like 10% - but still nothing short of bad practice. Bandwidth is money - both for your customer, and for whoever's hosting the site.

I personally built the new Kingsmill Bread website before Christmas for CMW London, with two sites - one for full desktop and iPads, and one specifically for cellphones (if you're on a cellphone, tough luck, we do user-agent checking to redirect you to the mobile one automatically. Sorry!). If they want to expand that out in future to support TVs, tablets and netbooks specifically, great - we know that the site is fully performance-optimised for each platform already to save them and their visitors money on bandwidth.

Responsive design has a place, but it's by no means a one-size-fits-all solution. Remember that in an ever-increasingly-connected world, bytes are money, and it's your responsibility to save them to deliver value-for-money in your solutions.

Multi-discipline

I've been having some great conversations with a few developer friends lately, as we all hate having to "re-pave" our machines every time we upgrade hardware, or our laptop dies and we have to sort out a replacement so we can continue to work.

People think that becoming a developer is all about code, and in some cases, that's true. I think, though, that being a developer means solving the problem at hand - whatever the technology, language, or platform. A lot of us are purely focused on our specialism - be that .NET, webforms/MVC, front-end HTML5/CSS3/jQuery, etc. What about the metal behind it? All that code that makes what you write, possible - the operating system, web server, network protocols, and stuff that just makes your brain crackel with excitement? OK, maybe that's just me...

Anyway. Developers hate repaving machines. Some of you probably have IT departments for doing that kind of stuff, but for the lone freelancer, one dead hard-disk (as happened to mine earlier this week) means re-installing everything afresh on a new disk. And there are ways of making this stuff quicker, if it happens to you regularly (disclaimer: I'm on laptop number 7 since March 2008, but six of those have been in the last 2 years...).

Planning for failure is something every developer should do, and that includes your hardware failing too. Here's a quick step-by-step plan on how to make sure you can minimize that downtime.

  1. Source control. If you don't know what it is, find a shotgun and a mirror... wait, I'm kidding.

    Seriously though, if you're writing code without source control, it's like sleeping with your girlfriend, without contraception, a week before her period, drunk and blindfolded. One slip, and something goes wrong, and you don't remember how the hell it happened, or how you can fix it. And man, your head hurts.

    Get source control. Anything except Visual SourceSafe will do, as long as you can commit changes to a remote server via HTTP/S. I personally use Subversion, but I'm starting to lean towards using Git, as my hosted project provider has support for both. This way, anything goes wrong, not a big deal, you have the entire history of everything you changed and you can re-download it on demand. Assembla (my old provider) offers free private spaces up to 1GB in size. If you're doing it professionally, pay for pro tools - I use CodeSpaces' $29.99/mo plan, for up to 10 users & unlimited projects, and I pay for it every 6 months in bulk. I get project, task, user, time and code management - it's the best hosted provider I've used by far (with the exception of their API, but that's for another post).
  2. Get an external hard disk, and back up to it weekly.
  3. Image your hard disk with all your apps pre-installed. This is a tricky one, and the main meat of this blog post. I'm also using Windows 7, so YMMV with different operating systems.

Here's a really sweet video walkthrough on how to generalise, and then capture, a full system image, including installed applications (basically, go nuts with installing your copies of Visual Studio, SQL Server, Office, etc. etc.), and store this in a .WIM file, which can then be used to either re-deploy to other systems (IT admins, this one's for every time you hire a new dev team member), or used to re-image your own system (i.e. your hard disk just died, like mine did last week).

If you just arrived here because your hard disk frazzled at 2am last night, then my next post is a step-by-step walkthrough on how to restore the image that (hopefully) you created from watching the above video.

Watch this space!

Windows 8 previewed at BUILD Conference, Anaheim, California

So Microsoft's BUILD conference kicked off today with the keynote presented by Steven Sinofsky, VP of Windows and Windows Live.

BUILD logo

As a developer by trade, I was excited as heck by the keynote, and I'm frustrated as anything that I can't be there in person, to get my hands on the Windows 8 tablets they're (allegedly) handing out to attendees.
However, compared to keynotes by Google, Apple and all the other giant multi-billion tech conglomerates, I was disappointed by the lack of consumer focus. Microsoft wants people to upgrade to Windows 8, they still have to sell to consumers. I appreciate their value and their money is in pitching to developers who can add value to the platform, but Apple comes out with devices "that just work". I want to see more of that "it just works" stuff - I want to see someone doing music playback, watching movies, writing school essays, business reports, connecting to Wifi - all the stuff a normal domestic user does.

Now that my big gripe is out of the way - WOWZERS. Windows 8 strikes me as a developer's dream. Here's a small selection of the (pretty awesome) feature list from the first hour of the keynote:

  • Everything from Windows 7, runs on Windows 8;
  • Visual Studio 11 for writing Windows 8 apps, can handle both native HTML5/JS apps, Silverlight, and Winforms/WPF - and pass code back and forth between it and Expression Blend for making your apps both beautiful and functional;
  • 30% lower memory footprint than Windows 7 out-of-the-box (404MB compared to 280~ish MB in the demo);
  • Windows APIs now support pushing services from apps back into the native APIs for consuming from other apps;
  • Support for 256TB hard disks... (that's about a quarter of Google's index size);
  • A new Windows 8 App Store, which is optional for developers to use - no more Apple- or Google-style monopolistic control of the marketplace;
  • 3 lines of code to hook up to device-centric sensors (accelerometers, webcams, and so on).

 

So what does this actually mean for developers?

Well... I can write an HTML5/JS app, and it'll run natively on the desktop, be consumed by the desktop's other apps, but can also run standalone on my mobile phone, my tablet, my Linux PC, my Mac PC (if you're so inclined... boo hiss). I can write a Silverlight app and take full advantage of XNA on the desktop, XBox and Windows Phone.

Windows has finally recognised that interoperability between hardware platforms and applications is a must to stay ahead. This is the most cohesive effort I've seen from them, Apple or Google to unify the entire platform offering, giving developers (and their employers) maximum freedom to experiment, innovate, and inspire.

The Windows 8 developer preview will be available at 8pm PST. I'm tempted to go to bed early and get up at 4am local time just to download it.

The keynote's still going on at the time of posting, so I might be back to update it with more cool stuff later as it's announced.

Benjamin

The <xsl:key /> element (and why it rocks)

XSLT is fantastic for simple data structure queries - like WHERE and ORDER BY clauses. But what about the XSLT equivalent of DISTINCT?

Fortunately, there's a great answer to that - <xsl:key />.

Why would you want to use it? Well, I've been working on Blog4Umbraco a lot lately, and I've implemented custom datefoldering strategies. Now, that's great for flexibility on SEO and human-readable URLs, but if I don't have date folders set up, then the Blog Archive and Full Archive macros break, cause they rely on the unique nature of datefoldering to work - by iterating over the year folder in yyyy format, then month in mm format, then date in dd format, then the posts themselves - four levels of nested for-each's.
I would be using the Exslt.ExsltSets:distinct function to retrieve all postDate values of all grandchildren, were it not broken with a nice YSOD stacktrace in Umbraco 4.5.2.

So the question is: how do we retrieve every post, and then tell XSLT only to iterate over the *unique* values, without resorting to .NET? Answer: <xsl:key />.

The <xsl:key /> element is designed to generate unique IDs in-memory for matching nodes based on their properties.
In this instance I used:

XML, using GeSHi 1.0.8.8
<xsl:key name="ym"
match="*[(@isDoc or name()='node') and BlogLibrary:IsType('BlogPost', @id)]"
use="umbraco.library:FormatDateTime(./postDate, 'MMMM yyyy')" />
Parsed in 0.001 seconds at 219.43 KB/s

(P.S. main reason for using (@isDoc or name()='node') is compatibility between Umbraco < 4.0 and 4.5+ schemas - it'll work with both!)

So now I have a key called "ym", which will be created for every Umbraco content node, where the key's value for that node will be calculated from the use attribute.

This now means that I can do:

XML, using GeSHi 1.0.8.8
<xsl:if test="generate-id()=generate-id(key('ym',umbraco.library:FormatDateTime(./postDate, 'MMMM yyyy')))">
...
</xsl:if>
Parsed in 0.001 seconds at 145.70 KB/s

This does a few things:

  1. Calls generate-id() for the given node, which creates an ID;
  2. Calls generate-id() for any node where the "ym" key matches the given expression - in this case, passing in the current node's postDate for evaluation;
  3. Returns true if the two IDs match.

If it matches, great, we render results.

Hope this is useful!

Happy birthday to me... bye-bye spam

As a lot of you know, I've been busy refactoring Blog4Umbraco over the last few weeks and months, trying to drastically improve it's fortunes to support lots of new features.

One of the things that has bugged me is that Akismet, the included comment spam protection service, is only licensed for non-commercial usage, and if you want to run a "commercial" blog (however you want to define that), then you have to pay them some money. Now, that's all well and good, but as a true Socialist (I vote Lib Dem, for anyone who wants to know) I believe that certain basics in life should either be free or be at substantially reduced cost - healthcare, education, anti-virus software, operating systems, CMS software... OK mostly software. I think spam-fighting kit, with 87% of the Internet's traffic being made up of spam in one form or another, is now a basic essential, and the right of every good Internet citizen to possess at the very least basic security to guard against it.
Anyway, I've found Akismet's "commercial" clause a little wooly in the past, as a site that isn't e-commerce, nor has adverts, may still be run by a company (hey, we're putting a blog on the new Code Gecko site), and therefore is techncially "commercial" in nature. Where does one draw the line? Answer: by making it free - as in both free speech and free beer.

So on this note, I decided to hunt out some free blog comment spam systems that would gladly allow commercial use, and found two of particular note:

  • BlogSpam.net - a nice open-source option, with a hosted service for those who don't want to run their own service, written by Steve Kemp. I reckon this'd be ideal for high-traffic sites, cause it gives you the option of running your own, which you can then performance-tweak as and when you want.
    • Pros - no API keys;
    • Cons - few .NET wrappers (see below).
  • TypePad AntiSpam by the guys from Six Apart. These are the same guys that introduced the concept of TrackBacks, letting bloggers "ping" each other instead of just pinging blog aggregate services - an implementation of this is coming in Blog4Umbraco v3. Their implementation is great cause it's the identical API to Akismet, but with the "commercial use allowed" clause - great.
    • Pros - Can use Joel.Net's Akismet API library with a simple modification;
    • Cons - said library requires recompilation, it's a hosted service, and requires API keys.

Now, both of these are lovely, but there's no .NET wrappers for either of them. And as Scott Hanselman and Linus Torvalds say, "talk is cheap, show me the code".

BlogSpam.net API wrapper

Joel.Net's Akismet wrapper for TypePad AntiSpam

The BlogSpam.net API wrapper is MIT-licensed, as is pretty much all my open-source stuff.
Joel.Net's Akismet wrapper is 3-clause-BSD-licensed, so I can't take credit for anything except one line of code which changes the API URL from api.akismet.com to api.antispam.typepad.com - look Ma, no hands.

I gladly released this on March 14th - aka International Pi Day (3/14... *groan*), and the birthday of Albert Einstein (14/3/1879, 132nd anniversary), Quincy Jones Jr. and Sir Michael Caine (both 14/3/1933, aged 78), Jerry Greenfield of Ben & Jerry's (14/3/1951, aged 60), and yours truly (14/3/1987, aged 24).

Happy birthday to me, and enjoy!