I am dain

and these are my thoughts mostly on technology

Build your Minimum Viable Product

I gave a talk about building and iterating an MVP at the brilliant Workplace Hackshop organised by HackHumanity.

It’s a short presentation so take a look, but these are the just the main points for the busiest executives:

  • Form key hypotheses – optimise for learning, not functionality
  • Express your main value proposition
  • Get it out – if you’re not ashamed of it you wasted time
  • Measure every user interaction
  • Know where your audience hangs out
  • Look for customers ready to pay
  • Fake it, kludge it, hack it together

Comments

An introduction to jQuery Deferred / Promise and the design pattern in general

I gave an introductory talk a while back at the London Ajax User Group about jQuery Promises after which there was a lively debate, so I thought it would be great to post the content of the slides with some notes as a sort of tutorial.

Update (2012/09/01): As it turns out there was a nice video recorded of the talk, if you have 10 minutes free give it a watch!

The original presentation is on Github (made with Keydown as presentation engine which doesn’t seem to handle resizing well enough to be embeddable): daaain.github.com/jquery-deferred-intro/jquery-deferred-intro/slides.html

A simple CORS AJAX example

As a simple scenario to optimise I set up a not very useful example of loading 2 articles from HTML5Rocks and showing the first sections of each.

So in which cases are Promises useful?

AJAX request handler spaghetti

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$.ajax({
  type: 'GET',
  url: 'http://www.html5rocks.com/en/tutorials/file/xhr2/',
  success: function(response) {
    var insertDiv1 = $('<div></div>');
    insertDiv1.html($(response).find('section').html());
    $.ajax({
      type: 'GET',
      url: 'http://www.html5rocks.com/en/tutorials/audio/scheduling/',
      success: function(response) {
        var insertDiv2 = $('<div></div>');
        insertDiv2.html($(response).find('section').html());
        $('body').append(insertDiv1, '<hr/>', insertDiv2);
              }
    });
  }
});

Timing issues (DOM ready, animations, etc)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$(document).ready(function () {
  $.ajax({
    type: 'GET',
    url: 'http://www.html5rocks.com/en/tutorials/file/xhr2/',
    success: function(response) {
      var insertDiv1 = $('<div></div>');
      insertDiv1.html($(response).find('section').html());
      $.ajax({
        type: 'GET',
        url: 'http://www.html5rocks.com/en/tutorials/audio/scheduling/',
        success: function(response) {
          var insertDiv2 = $('<div></div>');
          insertDiv2.html($(response).find('section').html());
          $('body').append(insertDiv1, '<hr/>', insertDiv2);
        }
      });
    }
  });
});

But what are these Deferreds and Promises really?

Deferred

  • A proxy for an asynchronous, future event
  • Has an interface for getting resolve()d or reject()ed
  • Starts in pending state, can only be finished once
  • Calls listeners immediately (but always async) once resolved

Promise

  • Allows listening and state inspection (using state()), but completely immutable so no interface for resolution
  • Basic (jQuery specific) listeners are done() and fail()
  • Can be chained with then() (used to be pipe())
  • Can be grouped and processed using $.when()

How do they work?

A canonical Deferred example

Setting up a listener and triggering it with resolve:

1
2
3
4
5
6
7
var deferred = $.Deferred();

deferred.done(function(value) {
   alert(value);
});

deferred.resolve("hello world");

This also works as it doesn’t matter if a Deferred is already resolved it will still trigger the callback we attach to it:

1
2
3
4
5
6
7
var deferred = $.Deferred();

deferred.resolve("hello world");

deferred.done(function(value) {
   alert(value);
});

A canonical Promise + When example

Return a Promise from a method and attach a listener to it (can have more than one):

1
2
3
4
5
6
7
8
9
10
11
12
13
function getPromise() {
  var deferred = $.Deferred();

  setTimeout(function(){
    deferred.resolve("hurray");
  }, 1000);

  return deferred.promise();
}

$.when( getPromise() ).done(function(value) {
   alert(value);
});

So let’s untangle our example

Create a Promise for DOM ready and the two AJAX requests and wait for all of them to be fulfilled:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function getReady() {
  var deferredReady = $.Deferred();
  $(document).ready(function() {
    deferredReady.resolve();
  });
  return deferredReady.promise();
}

var firstRequest = $.ajax({ url: 'http://www.html5rocks.com/en/tutorials/file/xhr2/' }),
    secondRequest = $.ajax({ url: 'http://www.html5rocks.com/en/tutorials/audio/scheduling/' });

$.when( getReady(), firstRequest, secondRequest
).done( function( readyResponse, firstResponse, secondResponse ) {
  var insertDiv1 = $('<div></div>');
  insertDiv1.html($(firstResponse[0]).find('section').html());
  var insertDiv2 = $('<div></div>');
  insertDiv2.html($(secondResponse[0]).find('section').html());
  $('body').append(insertDiv1, '<hr/>', insertDiv2);
});

Another solution

The AJAX request can be already fired off while we wait for the DOM (also showing how can we chain listeners with then()):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function getReady() {
  var deferredReady = $.Deferred();
  $(document).ready(function() {
    deferredReady.resolve();
  });
  return deferredReady.promise();
}

var firstRequest = $.ajax({ url: 'http://www.html5rocks.com/en/tutorials/file/xhr2/' }),
    secondRequest = $.ajax({ url: 'http://www.html5rocks.com/en/tutorials/audio/scheduling/' }),
    firstDiv,
    secondDiv;

$.when( firstRequest, secondRequest
).then( function( firstResponse, secondResponse ) {
  firstDiv = $('<div></div>').html($(firstResponse[0]).find('section').html());
  secondDiv = $('<div></div>').html($(secondResponse[0]).find('section').html());
  return getReady();
}).done( function( readyResponse, firstResponse, secondResponse ) {
  $('body').append(firstDiv, '<hr/>', secondDiv);
});

Dealing with rejection

When a Promise gets reject()ed it will immediately cascade down the then() chain so you only need to handle it at the end (with jQuery it’s only since 1.8+ though).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
getTweetsFor("domenic") // promise-returning function
  .then(function (tweets) {
    var shortUrls = parseTweetsForUrls(tweets);
    var mostRecentShortUrl = shortUrls[0];
    return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning function
  })
  .then(httpGet) // promise-returning function
  .then(
    function (responseBody) {
      console.log("Most recent link text:", responseBody);
    },
    function (error) {
      console.error("Error with the twitterverse:", error);
    }
  );

I’ve taken this example from Domenic Denicola’s blog post “You’re Missing the Point of Promises” which is a great next step on the path of understanding Promises and asynchronous control flows. Go and read it now!

A few more pointers

  • In case there’s a long request you can send updates to a progress() listener using notify()
  • You can insert transformations into the then() chain
1
2
3
$.when( { testing: 123 } ).done(
  function(x) { alert(x.testing); } /* alerts "123" */
);
  • And finally it must be said that jQuery Deferred is by far not the only one, see Promises/A spec and the clarified Promises/A+ spec. If you’re not already using jQuery then Q, rsvp.js or when might be better alternatives with seamless interoperability due to stricter adherence to the CommonJS specs.

Loading Javascript / CSS files from Jammit’s assets.yml with Jasmine Gem to avoid duplication

Got a really handy bit of script working today, but it took me some time to figure out so thought I should post it.

Using the latest Jasmine Gem (only on Github master as of 2013/01/29) you just need to create spec/javascripts/support/jasmine_helper.rb and drop this in there (note that jasmine_helper.rb takes the responsibility of custom configs over from jasmine_config.rb from now on!):

1
2
3
4
5
6
7
require 'yaml'
require 'erb'

Jasmine.configure do |config|
  jammitYaml = YAML.load(ERB.new(File.read('config/assets.yml')).result)
  config.src_files = lambda { Jasmine::PathExpander.expand(config.src_dir, jammitYaml['javascripts']['workspace']) }
end

What it does is to load assets.yml, parse the YAML array javascripts: workspace:, uses Jasmine’s PathExpander.expand method to actually glob the files from the paths listed there and finally wraps the whole thing into a lambda so that it acts as a method.

Comments

Getting Cross-origin resource sharing with complex jQuery AJAX requests

I’m working on an HTML5 desktop application which needs to load some HTML text from a server, but not through an existing API. So I had to find a solution which can be set up without too much backend work and make it possible for non-technical people to easily update the content. I’m assuming that the easiest setup will be using an existing CMS system with a few custom server settings to enable cross-domain communication. It’s also a security sensitive application, so the content will need to be protected with basic authorisation at least.

Well, let me get things straight: CORS which is more than the simplest GET request is not easy!

While trying to set up and end to end proof of concept to make sure this will work and to be able to advise with setup I ran into several blockers, so I’m going to go through them step by step.

Setting up the jQuery AJAX request

For simple use cases all you need to do to is fire off a simple GET request:

1
2
3
4
5
6
7
8
$.ajax({
  type: 'GET',
  url: 'http://www.html5rocks.com/en/tutorials/file/xhr2/',
  success: function(response) {
      var article = $(response).find('article').html();
      $('body').html(article);
  }
});

If the server you’re hitting is sending back the header Access-Control-Allow-Origin with the value * you’re all set:

JS Bin

However what I ended up with is far more complicated, as doing anything with custom headers (which included authorisation) you have to first make a so called preflight request. This is an OPTIONS request which only asks the server if it supports all the headers needed for the ‘real’ request which follows.

So let’s first see the full AJAX request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$.ajax({
  type: 'GET',
  url: 'http://www.mydomain.com/myFancyContent.php',
  headers: {
      'MyCustomHeader': 'important information'
  },
  xhrFields: {
      withCredentials: true
  },
  username: 'myuser',
  password: 'mypassword',
  success: function() {
      console.log('success');
  },
  error: function() {
      console.log('failure');
  }
});

JQuery has some helpers for authorisation, so the easiest way to get it working is setting xhrFields.withCredentials to true and passing username and password as separate parameters, this way we don’t have to worry about the intricacies of creating the auth hash ourselves.

Another convenience property is headers which you can use to inject any custom headers you might need, without having to manually do it with beforeSend.

Apache config

Another big stumbling block for me was to get the settings for Apache right.

The very first thing you need to do is making sure mod_headers is enabled, which can be as simple as:

1
2
$ sudo a2enmod headers
$ sudo /etc/init.d/apache2 force-reload

Once that’s done, you can either edit your main httpd.conf or apache.conf files, or just create an .htaccess file in the folder you want to enable CORS in.

These are the settings I ended up with after a lot of experimentation:

1
2
3
4
5
6
7
SetEnvIf Origin ^(.*)$ ORIGIN_DOMAIN=$0
<Files "*">
  Header add Access-Control-Allow-Origin %{ORIGIN_DOMAIN}e
  Header add Access-Control-Allow-Methods "GET, OPTIONS"
  Header add Access-Control-Allow-Headers "Authorization, X-Requested-With, Content-Type, Origin, Accept"
  Header add Access-Control-Allow-Credentials "true"
</Files>

The first line makes sure that Origin is echoed back, because as it turns out once you have some custom headers a simple * in Access-Control-Allow-Origin won’t do any more. You can do some URL filtering here if you want, but this setup makes sure that even file:/// works which is great for development.

In Access-Control-Allow-Methods we make sure that OPTIONS will work, and with Access-Control-Allow-Headers and Access-Control-Allow-Credentials we set everything up for a basic authorisation handshake.

Annoyingly none of these worked on the simple HTML file I uploaded, until as a desperate idea after a few hours of futile attempts I tried renaming it to PHP extension which made Apache suddenly apply all of them.

If that wasn’t enough, the unregistered development HTTPS security certificate also blocked my attempts to get things working. If you open any URL on the server you’re using and accept the certificate this problem will go away, otherwise the options are to install / import the certificate on a system level or to start the browser with some flags like --allow-running-insecure-content for Chrome.

Hope this will help someone else facing the same problems!

Some thoughts on the fragile relationship between nature conservation and economic growth

Update: I started a small blog / public notebook of all things sustainable / resilient at transientresilient.tumblr.com

As part of the Sustainability course on Coursera I’m currently taking, I had to write a forum post around population growth. It was inspired by an article about the dwindling richness of sound recordings in nature and tried to articulate some thoughts around incorporating nature conservation into the economy.

While human population might be internally sustainable, what about our lasting impact on nature?

Just read an article about Bernie Krause experiencing the shocking loss of biodiversity around the World through audio recordings of wildlife taken a few years apart at the same spots: http://www.guardian.co.uk/environment/2012/sep/03/bernie-krause-natural-world-recordings

It’s crazy how little respect humanity as a whole has towards untouched nature… Maybe it’s time for it to be calculated as part of GDP so that land left alone to nature would contribute to this “sacred index” which seems to be the only thing which matters in the industrialised world? I wonder what could rein in our relentless colonisation of Earth with our population still set to rise at least for the next few decades.

Unfortunately the UN can’t force any country to do things differently than its often short-sighted politicians decide under the intoxicating lure of lobby money, maybe the best hope for a source of change could be regional supranational entities like the EU? The pollution / renewable energy generation targets mandated on the EU level are the only thing which I can see that is shaking the political elite into the barest minimum of action here in the UK. While the wealth generated here in London is just staggering, the city fails to meet basic air quality standards already pushed back from a few years ago after repeatedly failing to meet them.

I’m from Hungary in Eastern Europe originally, and having moved to the UK I’m really sad to see as I travel in the countryside here that the industrial revolution left precious little wild nature on this island. Maybe it’s actually a boon that Eastern Europe wasn’t caught up in such a crazy rate of “development” that the really important things are ignored and sacrificed on the altar of “progress”. Maybe it’s because of the agrarian heritage which inevitably comes with a level of respect towards nature?

In the end I guess my main question is: how could it be possible to include nature as part of the wealth of a nation so that capitalism takes notice?

It also made me want to grab my sound recorder and go out to capture sounds of nature, maybe even juxtaposed with recordings from the city.


Edit: Oh, just after writing this post I found an article which is just about how to value nature as wealth: http://www.guardian.co.uk/environment/2012/sep/03/ecuador-yasuni-conservation

While it starts off really promising…

Just as the species must innovate to survive, Yasuni has inspired the planet’s most creative and ambitious approach to biodiversity conservation, social development and climate change. Ecuador – which is also home to the Galapagos Islands – is the only country in the world to have recognised the rights of nature in its constitution. After the discovery of a $7.2bn oil reserve inside a pristine corner of the Yasuni national park, the government has proposed leaving the fossil fuel in the ground if the international community will give them half that amount.

…and mentions some interesting numbers and findings…

The UNEP estimates that 40% of the global economy is based on biological products and processes. Biodiversity loss, it says, is becoming a greater concern for businesses than international terrorism.

…apparently the biggest culprits don’t really care anyway:

But what has happened since has been the opposite: because the US, UK and others can consume the assets generated by the amazon jungle for free, they have committed absolutely nothing. The Yasuni ITT initiative has raised a lot less than expected.

The sliver of hope though is that while governments don’t care, people do:

The ITT initiative, which covers the Ishpingo, Tambococha and Tiputini oil fields in Yasuni that make up an area of less than one-fifth of Yasuni’s national park, aims to address this in a core area for protection. Last year, it reached its target of raising $100m thanks to some creative accounting and generous public support (the UK was top for individual donations after featuring in the Guardian), and contributions from Bo Derek, Leonardo DiCaprio, Edward Norton and Al Gore.

Ivonne Baki, who is spearheading the fundraising effort, says the project has now raised $200m, but more is needed. “The cost of not doing something now will be far higher than the economic crisis. If we are serious about reducing emissions of CO2 and doing something – which is all they talk about at international meetings – then this is the place giving oxygen to the world.”

Setting up rmate with Sublime Text for remote file editing over SSH

If you want to be able to edit files using your local Sublime Text 2 app over SSH, you can use rmate which is a small remote connection script developed originally for TextMate.

This is how it goes:

  • Install the rsub plugin for ST2, which is available through Package Control too.
  • Add a remote forwarding line under the right host in your ~/.ssh/config file to enable connection:
1
2
3
Host myfancyvps
  Hostname 123.45.67.89
  RemoteForward 52698 127.0.0.1:52698
  • SSH in to your remote: ssh myfancyvps
  • Download rmate: curl https://raw.githubusercontent.com/aurora/rmate/master/rmate > rmate
  • Move it in place: sudo mv rmate /usr/local/bin – you can put in ~/bin too if you only want to set it up for yourself, but sharing is caring :)
  • Make it executable: sudo chmod +x /usr/local/bin/rmate
  • Profit: rmate .profile – make sure you have an open ST2 window to enable listening!

The main reason why I really like this is because you can also sudo rmate with system config files and be able to actually save them back, as opposed to editing via an SFTP client where you need to log in with root to be able to do this.

Also, don’t forget to open the port in your iptables if you have a restrictive / whitelist firewall policy: -A INPUT -p tcp --dport 52698 -j ACCEPT. Also you have to do iptables-save and iptables-restore to make these settings persistent after reboot.

A slightly annoying caveat is that a port can’t be shared with other people if you happen to be logged in at the same time, so you might have to set up separate ports in iptables with the first port number in the RemoteForward setting matching it (the local port should remain the same). In this case you have to specify the port number in each call though: rmate -p 52699. So probably the best is to create an alias in your .profile: alias rsub='rmate -p 52699', but in this case you also need to add: alias sudo='sudo '. By adding that trailing space you make sure that the sudo‘d command is also checked for alias substitution, so doing sudo rsub my_system_config_file will still work.

Setting up Octopress

Steps I’ve taken

Note: ‘username’ is your Github username and ‘myblog’ is the name of your blog / site which you’ll have to replace in the instructions. Don’t sweat too much about the latter, it’s just a project name you won’t necessary have to use on your site.

Set up Github repository for hosting

Go to: https://github.com/new

Fill in form and create repo called “username.github.com”

Set up Octopress

If you don’t have it yet, install rbenv and ruby-build (to handle Ruby runtimes and build gems). If you’re on Windows this is going to be a bit more complicated, but setting up RubyInstaller and Ruby Development Kit is not that bad.

1
2
3
4
5
6
7
$ rbenv install 1.9.2-p290
$ git clone git://github.com/imathis/octopress.git myblog
$ cd myblog
$ gem install bundler
$ rbenv rehash
$ bundle install
$ rbenv rehash

Get a nice theme

1
2
$ git clone git://github.com/tommy351/Octopress-Theme-Slash.git .themes/slash
$ rake install['slash']

Configure Octopress

Edit at least “Main Configs” in _config.yml. You can come back later to fill in the rest.

Set site up for Github Pages

1
$ rake setup_github_pages

Paste your Github repo URL: git@github.com:username/username.github.com.git when prompted.

This will set up some folders and the structure of the Git repos. Master branch will track the actual generated website (the contents of _deploy folder) and source will be the sources you are going to edit.

Create your first post

1
$ rake new_post["Hello World!"]

Edit contents of myblog/source/_posts/yyyy-mm-dd-hello-world.markdown

Generate page and see it in your browser

1
2
3
$ rake generate
$ powify create myblog
$ powify browse myblog

See if it’s all good locally

1
$ rake deploy

Check the real thing: http://username.github.com

puts ‘Hello world’

A brave new blog, this time powered by the impressive dream team of Ruby, Compass, Jekyll, Octopress and Github.

No database to worry about, back up and restore. Everything is in a Git repository, kindly hosted and served up to the world by Github.

All content is created in Markdown, hand typed in Mou.app.