Two i's

I think it’s always good to be working on two things: The next most important thing, and the next most interesting thing.

Jason Fried

Things Get Fuzzy Fast: Examine Your Day So You Can Learn From It

Many of you will have seen Benjamin Franklin's daily schedule.

Benjamin Franklin's daily schedule

I love it, especially how it brackets the day with moments for reflection. He lives the examined life. He uses his morning to "contrive [the] day's business and take the resolution of the day." If Franklin were at a present-day web or design business, he'd be right in there at the daily stand-up, with all his plans lined up nicely.

But the most interesting part of Franklin's schedule is in the evening, in his "examination of the day." This is the moment that allows for learning and growth, for a conscious inspection of matters that gives you true agency over your work. Just in the way the web business runs a retrospective at the end of a project, you can achieve a much tighter cycle of personal evaluation, allowing your experience from one day to inform and improve the next. Without this, you can resign yourself to be little more than a sheet of paper – perhaps the one outlining your morning's good intentions – cast out to flutter in the wind, hostage to the whims of myriad external forces.

Taking back control takes a mere few minutes a day, and the results are worth it. In doing it myself, last week I learnt that I would start most days with a big goal in mind and a bunch of small chores alongside, but the chores would always end up taking longer than my drinking-my-first-coffee self predicts. I'd get to the end of each day with too little time for my most important work. Without any kind of examination, it's too easy to let a situation like this leave you feeling vaguely embattled and just press on without any change. This is not a recipe for improvement.

You might ask why a mornings-only cycle of evaluation wouldn't also work. At the end of the work day you just want to shut the computer and move onto something else, right? The trouble there is that you'd lose information. You best know how your day went when you've just finished living it. If you want to be active in adjusting your days so you can end them feeling accomplished, that's when you need to be recording things.

These daily reflections become even more powerful once you're part of a team. Write at the end of each day and this small investment in time can bring about a huge boost to everyone's general awareness of each other's work. If you're struggling with something, your teammates don't need to wait and see if you deem it important enough to bring up again the next morning. Instead, they can jump in and offer a hand as soon as they can see you could do with one. Then when things go well, there's no better motivation than seeing the continuing great work of your teammates, and you can boost the positive mood even further by joining in and celebrating their wins.

The way I see it is that, if I haven't shared it in writing with my teammates, then the work never happened. Prose is just as important as code.

Have you ever reached the end of a long stretch of work and thought, "Wow, didn't that time fly?" If you then thought more deeply, would you even be able to recall the particular ups and downs that defined the course of that work? What if you waited a couple of weeks and tried again? Things get fuzzy fast, and since the most instructive aspects of the work may not always be the most memorable, there's only a small window where you can learn from it. Become a diarist of your work, and you can keep this window open.

Being ignorant is not so much a shame, as being unwilling to learn.

Benjamin Franklin

Live an examined life, and you give yourself the best chance to improve it.

A Manageable Multi-Database Redis Development Setup

Redis has quickly become the companion to Postgres in most of our Rails apps. This creates a problem for development, since a Redis server only uses numbered databases. That's 1-16 by default. Hardly memorable, unless your app is called "5", in which case you're golden. On a single machine alone, it's easy enough to lose track of them once you have a few apps connecting to redis for both development and testing databases. Once you have multiple developers and designers working on an app, it's even worse. The solution I've found is to run a separate Redis server for each app, listening via a named socket.

This is easy to set up. First, take your standard Redis config file (mine is /usr/local/etc/redis.conf, thanks to Homebrew) and copy it to redis-common.conf. Edit this new file and change its port to port 0, ensuring it doesn't listen over TCP.

Then, create a separate config file for each app you want to use Redis. I call them /usr/local/etc/redis-server-<app_name>.conf. These files are nice and short:

include /usr/local/etc/redis-common.conf
pidfile /usr/local/var/run/redis-app_name.pid
unixsocket /tmp/redis-app_name.sock
dbfilename dump-app_name.rdb
vm-swap-file /tmp/redis-app_name.swap

These per-app config files are enough to run an entire Redis instance: they load the common config, followed by the app-specific paths that allow the server to run in isolation from other apps.

You can then start the Redis server like this:

redis-server /usr/local/etc/redis-server-app_name.conf

Currently, I have 5 different app-specific configs like this. This makes bringing Redis up and down a bit of a chore. I simplified the process with a couple of shell functions:

function redstart {
  redstop
  for file in `ls /usr/local/etc/redis-server-*.conf`; do
    redis-server $file
  done
}

function redstop {
  for file in `ls /usr/local/etc/redis-server-*.conf`; do
    pidfile=`grep pidfile $file | awk '{print $2}'`
    if [ -f $pidfile ]; then
      kill `cat $pidfile`
    fi
  done
}

Easy. Redis up and Redis down in one hit.

There's another benefit to running Redis like this: loading production data onto your development machine. Most cloud-hosted Redis providers give you backups in Redis' .rdb format, which is the data file for the whole server. You can't load this for a single numbered database. Splitting your local Redis servers by app means you can just replace the file specified in dbfilename with this backup file and now your app has the latest production data without interfering with any other app's Redis data.

Bonus: Redis config management functions

Want an easier way to build and manage those per-app config files? Here you go:

function redls {
  ls /usr/local/etc/redis-server-*.conf
}

function redgen {
  if [ -z "$1" ]; then
    echo "You need to specify an app name, eg. redgen decafsucks"
    return 1
  fi

  app=$1
  config="/usr/local/etc/redis-server-${app}.conf"

  redstop

  echo "include /usr/local/etc/redis-common.conf"     > $config
  echo "pidfile /usr/local/var/run/redis-${app}.pid"  >> $config
  echo "unixsocket /tmp/redis-${app}.sock"            >> $config
  echo "dbfilename dump-${app}.rdb"                   >> $config
  echo "vm-swap-file /tmp/redis-${app}.swap"          >> $config

  redstart
}

function redrm {
  if [ -z "$1" ]; then
    echo "You need to specify an app name, eg. redrm decafsucks"
    return 1
  fi

  redstop
  rm -f "/usr/local/etc/redis-server-${app}.conf"
  redstart
}

Bonus: Rails redis initializer

Here is the do-it-all Redis initializer I use in my Rails apps:

require "redis"

if (redis_url = ENV["REDIS_URL"] || ENV["REDISTOGO_URL"]).present?
  uri = URI.parse(redis_url)
  REDIS = Redis.new(
    host: uri.host,
    port: uri.port,
    password: uri.password)
else
  redis_socket = "/tmp/redis-myappname.sock"
  if File.exist?(redis_socket)
    REDIS = Redis.new(
      path: redis_socket,
      db: !Rails.env.test? ? 0 : 1)
  else
    REDIS = Redis.new(
      host: "localhost",
      port: 6379,
      db: !Rails.env.test? ? 0 : 1)
  end
end

This looks for Redis URL ENV vars first, which are used on Heroku to specify the Redis location. If they're not found, we must be in development, so it looks for the named Redis socket for the app (change redis_socket to make it your own). If that's there, it uses database 0 for Rails development and production modes, and database 1 for test. Finally, we don't want to fail completely if someone hasn't yet starting using the named redis sockets, so we fall back to the standard Redis TCP port.

There is No Lab

Much has been said about remote work lately. Yahoo! brought it to the fore when CEO Marissa Mayer completely cancelled their remote work policy a few weeks ago. It made mainstream press and quickly raised the ire of David Heinemeier Hansson, whose beliefs about remote work have shaped his life: half of his 37signals co-workers are remote and he too spends half his year working abroad.

At Icelab we don't have so much a formal policy about remote work (or about anything, really), but instead some simple guiding principles: work with good people to make good things, and as long as we can keep the business running, do whatever we can to help those people lead the lives they want.

I try to embody these principles: I spent the bulk of last year working from the Philippines and Hong Kong — and just this afternoon, I’ll fly off to Tokyo, the first leg in a trip that will see me working from five countries across three continents over the course of this year. It's allowing me to see the world in a way never before possible. Hugh's done some of this too, also checking in from Tokyo for a month at the start of last year. And in a couple of weeks, David's heading to Europe for a holiday and can extend it a little while by doing some work over there too.

Having people work from overseas has been no problem at all. In fact, 2012 was our biggest, most productive year yet.

Remote work isn't all about extending a holiday or seeing the world. It can also be about finding the right space for productivity in everyday life. Even Yahoo! recognised that you can't be chained to the office, that "occasionally [you] have to stay home for the cable guy," but this is more a sign of their failure to recognise the intrinsic value in a change of environment. As The Economist argued:

Plenty of evidence suggests that letting employees work from home is good for productivity. It allows them to use their time more efficiently and to spend more time with their families and less fuming in traffic jams or squashed on trains… You can shackle a Yahoo to his desk, but you can't make him feel the buzz.

We make our offices as comfortable and conducive to productivity as possible, but good work doesn't always happen from the same place. Good people, on the other hand, are good people everyday, regardless of their location.

Click to Edit with AngularJS

Every time I use AngularJS I love it a little more. One of my favourite things about it is how greatly it reduces ceremony and separation. When I'm writing front-end interactions, the last thing I want to be doing is jumping between files and maintaining state in two different places, especially for simple things like "click to edit" behaviour. That's what I'll show you now, done powerfully and directly in Angular:

<div ng-app>
  <div ng-controller="ClickToEditCtrl">
    <div ng-hide="editorEnabled">
      {{title}}
      <a href="#" ng-click="editorEnabled=!editorEnabled">Edit title</a>
    </div>
    <div ng-show="editorEnabled">
      <input ng-model="title">
      <a href="#" ng-click="editorEnabled=!editorEnabled">Done editing?</a>
    </div>
  </div>
</div>

Try this jsfiddle to see it in action. What we're doing is showing some text (an article's title in this example) and then revealing a field to edit it upon clicking an "Edit" link.

To achieve this, we use an Angular editorEnabled model (really just a flag here) that we check with ng-show and ng-hide directives to hide and show the various parts of the interface. We change this value using an ng-click directive on the hide and show links. Angular's data binding keeps everything in sync. As soon as editorEnabled flips between true and false, the interface reacts accordingly. And the best thing? Everything you need can be written directly in the markup.

The only bit of JavaScript is just the most basic setup for the Angular controller, providing an initial value for the title:

function ClickToEditCtrl($scope) {
  $scope.title = "Welcome to this demo!";
}

For some more sophisticated behaviour, you can put some more code in the controller. Let's change the interface to show "save" and "cancel" links when editing the title, and only update the title if the "save" link is pressed:

<div ng-app>
  <div ng-controller="ClickToEditCtrl">
    <div ng-hide="editorEnabled">
      {{title}}
      <a href="#" ng-click="enableEditor()">Edit title</a>
    </div>
    <div ng-show="editorEnabled">
      <input ng-model="editableTitle" ng-show="editorEnabled">
      <a href="#" ng-click="save()">Save</a>
      or
      <a href="#" ng-click="disableEditor()">cancel</a>.
    </div>
  </div>
</div>

See it in this jsfiddle.

The code in the corresponding controller doesn't need to worry about the interface at all, it just operates on the scope, and the interface updates itself accordingly.

function ClickToEditCtrl($scope) {
  $scope.title = "Welcome to this demo!";
  $scope.editorEnabled = false;

  $scope.enableEditor = function() {
    $scope.editorEnabled = true;
    $scope.editableTitle = $scope.title;
  };

  $scope.disableEditor = function() {
    $scope.editorEnabled = false;
  };

  $scope.save = function() {
    $scope.title = $scope.editableTitle;
    $scope.disableEditor();
  };
}

If you wanted to extend this even further and make it a reusable component for different parts of your interface, you would make it a custom directive.

One of the other great things about AngularJS is that you can use it as much or as little as you like. We've used it for the entirety of The Thousands' admin interface, so adding bits of behaviour like this is no problem. But even if you're not already using it, you can just as easily attach an ng-app to any one of your HTML elements and get started.

Announcing Decaf Sucks 1.1

It's been a while since we've talked about Decaf Sucks on the iPhone. Our first release has run smoothly for a year and a half, helping many thousands of iPhone owners find better coffee. Thanks to our well caffeinated contributors, nearly half of our reviews are now submitted from the app.

On this note, we're very excited to announce the release of Decaf Sucks version 1.1 in the App Store. This release makes it even easier to contribute reviews with the addition of Facebook login support (now available wherever Decaf Sucks exists).

We've also added support for the iOS 6 and the larger iPhone 5 display, as well as giving the app some extra polish all around. In particular, our overseas friends can rest easy, because the distance to your favourite cafes is now reported in miles or kilometres based on the device's region format setting.

Decaf Sucks 1.1 is still free and waiting for you in the App Store. Get it now and find some great coffee near you!

Read on for a full list of all the things we've changed.

New features:

  • Login with Facebook to write reviews
  • Support for the larger iPhone 5 display
  • Distance units are localised into miles or kilometres based on the device's settings
  • iOS 6 compatibility updates

Other improvements:

  • When setting a cafe's location, show a callout above the map pin to make it clear that it can be dragged around.
  • When setting a cafe's location, ensure that the pin is actually draggable on the first tap.
  • When setting a cafe's location, always show a proper full address after dragging the pin around.
  • Show a proper non-retina image for the back button's pressed state.
  • Fix a bug that sometimes caused the map view to start very zoomed out.
  • When a review is completely empty, make sure the "Post" button stays disabled.
  • Ensure the map for a single cafe encompasses the current location, if it is nearby.
  • Fix a bug that led to some reviews being set to Hyderabad, India. Yes, this was really weird.

Decaf Sucks 1.1 is available in the App Store now.