Flaky Goodness

Don't Give Up

June 5, 2017

It's my birthday today. I'm getting older and so are my friends and family. You are too, probably. It's getting harder to eat well, exercise and stay in shape.

Why is it getting harder? Everyone has their own reasons and they're good ones. The reasons become more convincing as we get older and busier. That's not what I want to talk about right now. I've started to notice something with people I care about that deeply concerns me.

When we were young we took staying in shape mostly for granted. We ate and drank what we wanted and let metabolism, good luck, and naturally active lifestyles handle it for us. As we got a little older we found we had to put some effort into staying healthy. For some of us that effort become an ingrained set of habits and values. For others it didn't.

Now, as we're continuing to age, my friends are noticing that their weight is out of control. They drink too much, by anyone's definition of "moderate." They are being diagnosed with lifestyle-related diseases. They're on medication to manage chronic illnesses. And one daily medication is becoming two is becoming three.

Maybe you're in the same boat, or maybe you will be someday. Will you shrug your shoulders and accept the inevitable decline of your health with age? Will you give up?

Here's something else I've noticed. Our bodies, and overall health, is incredibly adaptable. If you can walk 100m today and walk every day you will soon be walking 1000m. And not long after that 10 km1.

One-way, unfortunately

And then you'll start running. And maybe you'll only run 1 km the first time and take breaks, but if you run every day soon you'll be running 5 km without breaks. And then 10 km.

You'll find that you've started losing weight, and that you're sleeping better and have more energy. And that will motivate you to start eating a little better. Maybe cut down a bit on the drinks. And you'll get healther. Eventually. Because the human body will adapt, if you work at it every day and give it time.

As long as you don't give up.

About three years ago I was inspired by The Healthy Programmer to start walking, then running, then swimming. A couple of weeks ago I (slowly) finished an indoor 1/2 triathlon. Later this year I'm hoping to complete a full triathlon indoors. I never thought that I'd be able to complete a triathlon, but now it is the next step in a progression of goals set and achieved.

Not breaking any records, but hey.

The body is like that. You can set goals and make daily progress towards them. Sometimes you will hit plateaus and sometimes you will regress, but over the long term you will get healthier. Everybody starts from a different place, but you can always make progress. No matter where you are right now there is a next step, and a step after that.

Just don't give up.

--

1 328 feet, 0.6 miles, and 6.4 miles respectively.

Hey Siri on the Apple Watch

May 30, 2017

People seem to have trouble with this so here is the trick to using Hey Siri on the Apple Watch.

  1. Flip your wrist up so that your watch face appears before saying Hey Siri. Starting from a blank watch face doesn't seem to work very well (or at all).

  2. As soon as the Siri waveform UI appears, continue with your request. Do not wait for Siri's audio or haptic feedback. When you see the waveform, continue speaking.

Continue speaking now

The combination of these two steps makes Siri on the Apple Watch much more reliable for me.

Networking at WWDC

March 31, 2017

Congratulations to everyone who won the chance to attend this year's Apple World Wide Developer Conference in San Jose. My first (and so far, only) trip to WWDC was in 2016 and it was an amazing experience.

A good friend going for the first time this year asked me what I thought about WWDC as a place for business networking. He is a freelance iOS developer and is always on the lookout for new opportunities to work on interesting projects. My advice, based on my experience last year, boils down to this:

  1. I didn't meet many people who were actively looking for contractors to help with their iOS project. I don't really remember meeting anyone who was looking for technical co-founders or partners either. I'm sure these opportunities are there, but I wouldn't say they are common at WWDC.

  2. There are many other contractors at the conference. Chatting with them is fascinating (some of the stories are pretty good) and could potentially lead to sharing of opportunities in the future. I met at least a few people to whom I've passed on contracting leads I've come across since.

  3. The social aspect of WWDC I enjoyed the most was getting to meet in person all the people with whom I've had some interaction in the Mac and iOS developer community. People with whom I've argued on Twitter, whose podcasts I enjoyed, whose libraries I've used, and some who currently do, once did, or would soon begin, working for Apple itself.

This third type of interaction will probably not lead to a direct business opportunity. But membership in the Apple community is the greatest reward for choosing to develop for the platform. There are real people behind all the work you see and use, and once a year you can shake their hand, buy them a beer, and talk shop for a bit.

So if I was going this year, I think I would seek out the third, be open to the second, and not worry about the first type of networking in my list.

Making Xcode more like Emacs

October 13, 2016

You might already know that macOS has great system-wide support for Emacs text editing shortcuts. And you might also know that you can customize that support to add your own custom shortcuts. In fact, there is a nice pre-built file of additional Emacs bindings compiled by Jacob Rus that I recommend.

Xcode ignores these customizations.

Luckily you can add your own similar customizations if you're willing to dig into the Xcode application bundle. Here's the file to edit:

/Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Resources/IDETextKeyBindingSet.plist

It gets replaced when you swap out your Xcode binary so be prepared to copy your modified version back in from time to time. Here's a snippet from mine, appearing directly under the </dict> closing the <key>Writing Direction</key> section.

<key>Custom</key> <dict> <key>Move to non-whitespace beginning of line</key> <string>moveToBeginningOfLine:, moveSubWordForward:, moveSubWordBackward:</string> <key>Delete current line in one hit</key> <string>moveToEndOfLine:, deleteToBeginningOfLine:, deleteToEndOfParagraph:</string> <key>Insert line above</key> <string>moveToBeginningOfLine:, insertNewline:, moveUp:</string> <key>Insert line after end of current line</key> <string>moveToEndOfLine:, insertNewline:</string> </dict>

When you restart Xcode you will find your custom commands available in Xcode > Preferences > Key Bindings > All. You can bind keyboard shortcuts here.

Bind keyboard shortcuts

Happily the keyboard bindings seem to persist through Xcode updates, so just copy your IDETextKeyBindingSet.plist file back in after updates and you should be good to go.

Limitations

It seems that the methods available to us for the definition of custom text editing shortcuts (like deleteToBeginningOfLine:) are all instance methods on NSResponder. So many of the more useful Emacs features (like Moving by Defuns) might be impossible to implement. If you can think of a way to do this, I'd appreciate hearing from you.

Three Products I Hope Apple Makes but They Probably Won't

February 10, 2016

Apple's hardware releases last year have felt like shots across my credit card's bow: things I almost like but not enough to buy for myself. Here are three dream products I would buy in an instant, if only Apple made them.

A round Apple Watch

I am so sad that Apple has committed to a rectangular watch face. I've never seen a rectangular watch I liked. I understand the difficulties in making a good circular UI, but if anyone could crack it Apple could. The next Apple Watch will probably be faster and thinner and may have better battery life. But a round face would seal the deal for me.

An 11" Retina MacBook Air

My 2013 11" MBA is probably my favorite Apple computer of all time1. Literally the only thing I'm missing is the gorgeous retina display on the new 12" MacBook. A Skylake CPU update for slightly longer battery life would just be icing on the cake: everything else on the 12" MacBook feels like a downgrade. But with the 12" MacBook and rumors that the next 13" Pro will be thin and light enough to supplant the 13" Air, it looks like there might not be enough room in the lineup for an upgraded baby Air. I hope I'm wrong on this.

An iPad mini with Apple Pencil support

I love the iPad mini's 7.9" form factor for inside-pocket portability, but without native stylus support I've switched to a Samsung Galaxy Note 8 for stylus notetaking and sketching on the go2. The Samsung S Pen technology is exceptional, and inking on my 2013 Android tablet feels similar to using Intuos tablets and the Microsoft Surface pen3.

The Apple Pencil is at least as good if not better, but is currently only available on the ginormous iPad Pro, in which I have no interest. There are rumblings that the Pencil will make its way down to the 9.7" iPad Air but I hope Apple takes it all the way down through the iPad line. I'd love to come back to iOS for my portable tablet needs.

Notetaking on a Samsung Galaxy Note 8

Notetaking on a Samsung Galaxy Note 8

They Probably Won't

I'm not holding my breath on any of these. In each case it feels as though Apple has made a deliberate decision to move in a different direction. Hope springs eternal though, and you can never put it past Apple to surprise us with something we hadn't even imagined.

--

1 I was lucky enough to have both an Apple ][+ and an original Macintosh 128k as a kid and they were awesome but I wouldn't trade my Air for them now.

2 I use Microsoft OneNote, which is free, supports mixing inking/sketching with typing, and syncs beautifully across iOS, OS X, and Android. And presumably Windows too.

3 I believe the Samsung Galaxy Note devices and the Microsoft Surface both use the same or very similar WACOM digitizer technology as that found in Intuos tablets. All attempts to make a good capacitive stylus (passive or Bluetooth) for modern devices pale in comparison: they all provide a completely different and wholly inferior experience.

14-day Week View in Calendar

February 7, 2016

Calendar (formerly iCal) has become increasingly stubborn about the number of days shown in the Week view. In OS X 10.7 and earlier it was possible to expose a Develop menu to bump the week view to my preferred 14-day range, but that went away in 10.8. You could still defaults write your change, but sometime between 10.8 and 10.11 that stopped working too.

14-day Week View

With a little spelunking in ~/Library/Preferences/com.apple.iCal.plist, I found the appropriate setting. Close Calendar, and type into Terminal:

defaults write com.apple.iCal "n days of week" 14

Reopen Calendar in Week view and you should see a 2-week window. To restore the original behaviour you can simply close calendar and type:

defaults delete com.apple.iCal "n days of week"

Aah. That's better.

Pile of Poo

February 3, 2015

Here's a little toy I put up on GitHub that will make a young person in your life smile. It's a secret code generator in Ruby. Run the script with the plaintext and you get back an HTML puzzle page "encoded" using a substitution cypher made up of a randomized subset of the emoji character set.

Sample output

Open the HTML in an emoji-friendly browser (like Safari) and print it out. Good times, and completely immune to the POODLE vulnerability.

My Priorities

January 21, 2015

Once in a while I am able to pull my head above water level and reflect on my work priorities. When I start making the list it is always longer than I thought it would be. My reach exceeds my grasp, sometimes in a healthy, optimistic way and sometimes less so. It's a useful exercise: what are my real project priorities, and what does that even mean?

This is the working definition I've come up with:

Your priority projects are the ones you touch every day. Everything else is a hobby.

There is nothing wrong with having lots of hobbies. Still, this is a bitter pill for me to swallow because I am involved in so many different things that I (supposedly) care about. There are only a few things that I work on, even just a little bit, every day. If I am honest with myself, those are my priorities.

My Problem with Objective-C Dot Syntax

March 3, 2014

Say you have a class Employee with the property CGFloat salary. Here are two choices to set this property from inside an instance of the class.

_salary = 35000.00;

or

[self setSalary:35000.00];

These do very different things. In the first case you directly set the instance variable (ivar) and do not trigger any observers or other hooks that may be watching salary for changes.

The second is actually calling the method setSalary, whether defined explicitly in your code or generated for you by the compiler. It is also triggering anything in the framework that may be set up to detect changes to the property.

In general, you would always want to use the second form rather than the first. Something out there might be expecting to be notified when salary changes, and if you set it directly you are doing an end-run around one of the things that makes programming in Objective-C so nice. Sometimes though, you actually do want to use direct ivar assignment.

Now, consider a third way of setting the salary.

self.salary = 35000.00;

Is this like the first form (direct ivar assignment) or like the second (property assignment)?

Integrating terminal Vim with Finder [UPDATED 2015-02-10]

February 24, 2014

MacVim is a great choice for Vim on the Mac. It is a pre-built GUI wrapper with a lot of nice extras that smooth the infamous Vim learning curve. But the Vim experience is better in its native habitat1, the terminal, and like others, I grew to prefer text-mode Vim.

I hate losing Finder integration though. I want to be able to double-click on a text file and have it open in my editor, preferably reusing an existing Vim session if available. This is non-trivial to set up with terminal Vim. The approach I'll describe here is fiddly, hacky and a work in progress. But it does work.

XQuartz

Might as well get the hard part over with first. Check to see if you have Vim compiled with the necessary options:

vim --version

Do you see +clientserver, +X11, and +xterm_clipboard? I'm guessing you do not.

Here's the thing. If you want this procedure to work you're going to need to install and run XQuartz in the background, all the time. I have mine set to run at startup and I leave it running while I use my machine. I'd prefer not to need this because I don't use X11 for anything else, but it is fundamental to this configuration so I've learned to live with it.

Go ahead and install XQuartz now, because you'll need it on your system before re-compiling Vim.

UPDATE 2015-02-10: OS X 10.10 Yosemite

You'll need to link the X11 include and library directories to where the vim configure script can find them:

sudo ln -s /opt/X11/include /usr/include/X11 sudo ln -s /opt/X11/lib /usr/lib/X11

Compile Vim from source

You can't call yourself a programmer until you've compiled your own editor from source, right? Well, here we go.

Download the Vim source and configure. Here are the options I use:

make distclean
./configure --with-features=huge \
                --enable-rubyinterp \
                --enable-pythoninterp \
                --enable-luainterp \
                --enable-cscope \
                --enable-gui=gtk2 \
                --disable-darwin

You're disabling the available OS X integration (--disable-darwin) in favour of XTerm integration (--enable-gui=gtk2). That flag will be ignored by the configure script if you haven't installed XQuartz, so scroll through the configure output and confirm that your --enable-gui=gtk2 wasn't discarded.

Now:

make
sudo make install

And check that everything worked with:

vim --version

You should now see +clientserver, +X11 and +xterm_clipboard.

tmux

If you're this far down the text-mode rabbit hole you have probably already installed tmux. But if you haven't, download and install it from source.

iTerm2

Here's one you don't have to recompile. A long time ago I thought that the built in terminal on OS X was fine and that I didn't need a souped-up terminal, but I was wrong. Get iTerm2.

Now you want to set up an iTerm2 profile specifically for creating/connecting to a tmux session and a Vim server. Here's a screenshot of what I've done:

iTerm2 profile

iTerm2 profile for launching tmux and Vim

That full command-line is:

/bin/zsh -c "tmux attach -t TMUX || tmux new -s TMUX '/usr/local/bin/vim --servername VIM'" 

Substitute your shell of choice if you haven't got religion on oh-my-zsh yet.

We are not even close to finished yet.

AppleScript

Now you want a script to actually tell iTerm2 to start a new terminal session using this profile, or just activate an existing one if available. Open up AppleScript Editor and type the following.

tell application "iTerm"
    activate
    repeat with theTerminal in terminals
        repeat with theSession in sessions of theTerminal
            if (name of theSession contains "tmux") or (name of theSession contains "vim") then
                set current terminal to theTerminal
                select theSession
                return
            end if
        end repeat
    end repeat

    -- No tmux or vim session yet. Start one.

    set theTerminal to (make new terminal)
    tell theTerminal
        launch session "VimServer"
    end tell
end tell

I've saved mine into ~/bin/open-tmux-or-vim.scpt.

This script is actually pretty handy, and I've bound it to Ctrl-Option-Cmd-V (using a Quicksilver trigger, but you can use whatever you want).

Automator workflow

Now we're going to make an application (actually just an Automator workflow) that will accept the files we've selected or double-clicked in the Finder and hand them off to the running Vim server we started (or will start). Fire up Automator and create an application as follows:

Automator workflow

Automator workflow for opening from Finder

I know what you're thinking. Sleep 0.5? Really? This is number one on the To Do list for future improvement. But for now, I've hardcoded a delay so that Vim has a chance to set up a listening server to accept the --remote-tab-silent we're issuing. Without the delay the Vim server won't have launched yet.

I've saved mine into ~/bin/OpenWithVim.app.

Associate file extensions

Right-click on a .txt file in the finder and choose Open With... > Other.... Enable All Applications and navigate to where you saved OpenWithVim.app. Click Add..., now click Change All... and Continue.

Try double-clicking on this file, or any other .txt file. It should open in terminal Vim within a tmux session.

Bonus points

If you want to associate lots of extensions and (like me) want to do this on several Macs, the Open With... dance is too cumbersome. Duti is a great solution to this, and I've mapped a Vim command to edit and trigger my .duti.conf file so adding new associations is a breeze. The bundle ID for the automator action you just created, by the way, is com.apple.automator.OpenWithVim.

Conclusion

If you've read this far and come to the conclusion that you should probably just use MacVim, I don't blame you. But I'm loving this set up right now and expect it will only get better.


1. There are good reasons for this, and they won't sway you until you've experienced it yourself. Building your own Vim is convenient because you can enable all the features you want and you can stay up to date. But mostly, there is a gestalt that occurs when you're working with solely pure-keyboard, pure-text tools. The allure is so strong that I'm considering switching to text-mode, tmux-friendly mail, Twitter, and messaging clients.

My RSS Setup

June 30, 2013

Barring any last minute stay of execution, Google Reader will stop working tomorrow (Monday July 1) so this would be a great time to pull your feed list off the service if you haven't already.

As predicted, the last few months have seen a whirlwind of RSS development and announcements as the Mac and iOS community have scrambled to fill the impending void. There are a number of great options now and they've been detailed at length in other articles. Here is what I decided to go with.

On the server-side I am self-hosting the single-user Fever aggregator. Fever is innovative in its presentation and ranking of articles, and this was its initial differentiator when it entered a market that still housed the 800-pound gorilla. I don't really care about that though.

For me, the low, one time cost and compatibility with Reeder makes it a great choice. As a bonus I can finally (finally) subscribe to feeds from my client application, which I had to sign into Google Reader's web app to do before.

On my iPhone I'm sticking with Reeder. Its gorgeous UI and reading experience hasn't changed much in the last couple of years, and the fact that it hasn't needed to is a testament to the strength of its design.

I wish I could use Reeder on my iPad but it has been lagging the iPhone version and doesn't yet offer Fever support. This is expected to come soon, and the renewed interest in non-Google RSS solutions is hopefully a motivating factor for the developer. I have a sinking feeling that nobody's getting rich off RSS, even with Google gone, so it's probably still a matter of the developer's internal motivation whether any particular product or service is improved. In a nutshell: Go Silvio Go!

For now, I am using Sunstroke, an excellent Fever-specific universal client and honestly perfectly suitable to the task.

Sunstroke for iPhone and iPad Sunstroke for iPhone and iPad. Source: goneeast.com/sunstroke/

I don't read feeds on my Mac so the web/desktop reading experience is a non-factor for me.

There is concern in blogging circles that Google Reader's hasty retirement is going to dramatically reduce RSS readership. Readers might not bother to find a replacement solution, especially with how fragmented the market has suddenly become and the complexity of choosing both a server-side and possibly multiple client-side tools. People might just gravitate to other sources of news instead.

I hope that this worry is unfounded: reading RSS feeds is still my favorite way to keep up with my (unevenly curated slice of the) world.

New Feed URL

May 1, 2013

As of today, Flaky Goodness can be found at http://goykhman.ca/gene/blog. Please update your bookmarks and subscriptions accordingly.

The Creamiest TextView in the App Store

April 14, 2013

I'm very pleased to announce the launch of my "weekend project" about a year in-the-making. Indigo In is now available on both the App Store and Mac App Store for all of your Macs and other Apple devices, and it's free. Enjoy.

Indigo In on iPhone

Indigo In on iPhone

There is no shortage of simple notetaking apps for either Mac or iOS, so I think it's worth mentioning what makes Indigo In a little different.

First, there is exactly one note. When you launch In you are editing that note. You never have to exit a note, create a new note, delete old notes, organize or tag your notes, etc. This makes for a really nice ubiquitous capture experience.

Launch In, start typing1. If you haven't yet gotten religion on ubiquitous capture, it's like the move from Windows to Mac: few who make the switch look back.

Second, the sync. This is why a weekend prototype took a year to hit the App Store. My original vision was simple: one page of notes constantly in sync between my Mac, iPhone and iPad. To make that happen took more than I expected. I might go into the technical details in the future, but for now I will say that I'm pleased with the result. Tap ideas into Indigo In on any of your devices and they will appear on all your other devices within a few seconds.

There are other nice things about Indigo In. The sharing feature (a $1 in-app purchase available only on the iPhone/iPad version of In) is handy for whipping through what you've captured and actually doing something with it. If you have a favorite app you'd like as a Share destination please suggest it on Twitter @indigoinapp.

Also, there is no sign-up or sign-in: everything is synced through iCloud, to which your device is probably already connected. That invisible login experience was the reason I stuck with iCloud despite its challenges.

Indigo In is a classic scratch-my-own-itch project and I'm really happy to see it spread its wings. It's in each of my docks and I use it constantly. I hope you find it useful too.


1. Try voice-dication with In. This feels especially Star Trek.

Using Panic's Status Board to monitor TimeTiger data

April 11, 2013

Yesterday renowned Mac and iOS developer Panic launched their beautiful new Status Board app for iPad. It lets you display real-time metrics from various public and personal sources in sizable, re-arrangable widgets on the iPad screen and optionally mirror that display to an HDTV or monitor hanging in your office. This is not a new idea, but is implemented elegantly and in an extremely user-friendly way. You can read iMore's full review.

Panic cleverly incorporated some simple interfaces for providing custom data sources to show in Status Board. This kind of thing is pure catnip for developers, so I took a few hours1 yesterday to put together a simple tool to publish TimeTiger time data in a Status Board-friendly way.

Sample TimeTiger Metrics

I've posted the tool on GitHub. It is a .NET 2.0 application written in VB.NET (Visual Studio 2005 and up) and uses the public TimeTiger SDK. It doesn't include any scheduling capabilities yet and provides only six simple reports, but serves as a great starting point for rolling your own real-time TimeTiger time and project Status Board layout.

TimeTiger Status Board tool

Sound interesting? We can help you get started using the TimeTiger SDK or adapting this specific tool to your needs.


1. According to TimeTiger, 3.4 hours from initially purchasing Status Board to committing working code and the screenshots you see here.

The Softphone that Gene Built

April 7, 2013

This is the IAX softphone that Gene built, so that he could make low-latency1, almost free phone calls from his computer anywhere in the world.

BlueVoice (original UI)

BlueVoice (original UI)

This is the wireless headset that Gene uses along with the IAX softphone that Gene built.

Plantronics CS-50 USB Headset

Plantronics CS-50 USB Headset

This is the wireless headset that Gene bought to replace the first one because a Mac OS X update broke the USB compatibility on which the headset's wake-from-sleep depended.

Plantronics Savi W440 Headset

Plantronics Savi W440 Headset

These are the open-source audio processing libraries on which Gene's softphone depends, that haven't been updated since 2008, and that Gene now has to port to 64-bit Mountain Lion.

IAXClient library on SourceForge

IAXClient library on SourceForge

So that Gene can actually build his softphone again.

To make low-latency, almost free phone calls from his computer anywhere in the world.


1. I've never been happy with the latency that seems to be endemic to SIP softphones. Building my own softphone based on the Asterisk IAX protocol allows me to leverage the native transfer capability of Asterisk, providing extremely low-latency point-to-point phone call connections that I wasn't able to achieve with anything off-the-shelf.

For the Most Part

March 29, 2013

iCloud has been getting piled on recently by the Mac and iOS developer community and that's too bad, because I think that for the most part1 it delivers on the promise of effortless, ubiquitous multi-device synchronization. There are bugs and edge cases to be sure, but it has been getting better2 and I believe that there is light at the end of the tunnel3. I may be naive, but I believe that most of iCloud4 either does or will soon "Just Work."

iCloud incorporates multiple sync technologies of which Core Data sync is just one. The promise of Core Data sync specifically is too great to ignore and it has lured many developers, including myself, into implementing solutions that depend on it. At some point or another, before, during, or (oh god the humanity) after release, iCloud Core Data sync falls out from under you and you must consider abandoning your project or using an alternative synchronization approach or even platform.

After my app was rejected for using (the dead simple and highly reliable) iCloud key-value store, I did in fact re-implement using Core Data sync. And I got it working, mostly. Then I hit one of those "falls out from under you" scenarios.

It has been suggested that iCloud Core Data is not appropriate for complex database schema with dependent relationships, integrity constraints, and so forth, but is quite useful for simple models. Based on my experience and the trivial example I put together to demonstrate my problem, I do not believe that to be the case.

But I could be wrong.

I've posted a 3-minute video that demonstrates the problem. It's possible that the bug is mine and mine alone, so here is the GitHub project if you'd like to take a look yourself. I would appreciate a pull request that actually resolves the errant behaviour rather than just works around it with a clever hack.

If this is a bonafide iCloud bug though, it's pretty bad. Given how trivially simple the use case is it's hard to imagine using iCloud Core Data sync in any shipping app5 until it improves. Here's the bug report, submitted to Apple as rdar://13192714.

As for my project, I've re-implemented (for the third time) using plain old text files in the plain old iCloud ubiquity store and have submitted it for review. It's working great: just as well as the original key-value store implementation. More on that soon.


1. Except for Core Data sync.

2. Core Data sync has not been getting better.

3. There is no light where there is Core Data sync.

4. Not the part with Core Data sync.

5. I know of some shipping iCloud Core Data apps, at least one of which is quite popular. I assume that their use cases manage to walk a very fine line between the issues others have and are continuing to report. There is no way to know whether any particular use case, no matter how simple, will be so blessed.

Be Careful What You Start

January 27, 2013

In April 2012, coming off another technically interesting but commercially flopped side-project, I was in the process of convincing myself that I should really be sticking to my knitting when I came up with a cool idea for, yes, another side-project.

Some People Just Don't Learn

The concept was simple and resonated with my own needs, and I figured I could whip up a prototype fairly quickly to see whether it would be useful to myself and others.

It was.

So, with a working prototype in hand I (once again) imposed upon the awesome talents of Colleen Nicholson to come up with an app icon, and set about bringing this thing to market.

I'll do it over the weekend.

— Bill Gates

How long would it take? A couple of weeks to Beta, maybe a couple of weeks of that, and then submission to the Mac and iOS app stores. Launch in June, margaritas on the beach by Canada Day1.

The core UI was dead-simple. The magic was in the iCloud-based synchronization on which the whole thing hung. A little research and a little testing and I decided on the iCloud Key-Value Store API. Although primarily intended for storing user preferences and configuration settings, the API was sufficient for my needs and it was2 the simplest and most reliable iCloud sync option.

I needed to build a fair bit of intelligence on top of that layer. The original schedule was washed away by reality but as the weeks and months rolled past I eventually got the sync behaviour I wanted. This was no fault of iCloud: the Key-Value Store API was rock-solid and acceptably performant for me throughout my testing, but I had a lot of kinks to work out in my own code. It was November before I finally submitted the iOS and Mac apps for review.

Prior to the completion of the review process, a Beta tester discovered a show-stopper and, after messing around with the code for a bit, I decided to pull the binaries until I could get it right. Sync is hard, and if you screw it up people are going to lose data.

I spent the next few weeks hacking away on an experimental branch of my sync code, digging deeper and deeper until I could no longer see daylight. Throwing my hands up just before the Christmas holidays, I decided to shelve it until 2013.

Refreshed and re-energized in the new year, I took a step back and started writing lots of automated tests against my sync logic. One of my frustrations had been my inability to quickly identify regressions and test edge-case conditions quickly enough. So, as you do, I implemented a detailed simulation of the actual iCloud Key-Value Store against which I could test my sync logic.

And Then it Worked

Like a shaft of light from the heavens cutting through the gray skies, in early January everything came together in a smooth, reliable, fast, and tight little bundle. I released another Beta and almost immediately submitted the app for review.

Rejected

Rejected

The iOS app was approved in about a week or so, but a few days after that the Mac app was rejected. I was using the iCloud Key-Value Store to save actual user-generated content, and that's not really what it's meant for.

I'm not going to whine about the relative merits of this argument or the fairness of this rejection. The fact is that yes, I was using the KVS to store user data and that no, that's not what it's meant for. So now I'm back to the drawing board on (by far) the most challenging element of this app.

What Now?

After 3 (or was it 4?) complete re-writes of the synchronization engine, the last including a fairly high-fidelity simulation of a chunk of iCloud, I think it's fair to say that my little weekend project has become a scope-creep cautionary tale. Part of me thinks it's time to shelve it for good. Especially since one of the most viable options now is converting the code to use iCloud Core-Data Sync (aka the Painmaker).

But I'm not very good at letting go of something once I've got it clenched in my jaws. So don't be surprised if a post not too long from now announces the release of this little project, a year or so after that first weekend prototype.


1. July 1st.

2. And still is, from what I hear.

User Intention

January 20, 2013

My father is vexingly difficult to shop for. I think that every brilliant gift idea I've had over my adult life has either been immediately returned or is still sitting on a shelf somewhere. I remember asking him once what type of camera he wanted, and his response was essentially this: small enough to fit in his pocket, and with a single button. But that one button has to take the perfect picture, with the perfect composition, exposure and color balance, every time.

This serves as a pretty good description of the ideal user interface: one button that does exactly what you intend. As software designers we can't ever quite get there, but we have ways of getting closer.

Limiting scope

The less a product does the simpler the interface can be. The stock Camera app on the iPhone has far fewer controls than my Nikon D7000, simply because it does less.

Making decisions instead of providing options

There will always be those of us who want to shoot in Manual or Aperture Priority to express our artistic vision and eke out the best result in any circumstance. But most of the world would rather shoot in Auto. A well designed Auto mode, one that minimizes the downside of giving up all that control, is a design win.

More controls than my car

More controls than my car

Asking the right questions at the right time

If full-Auto gets you 80% of the way there, it might be possible to get to 90% by exposing just a tiny bit of UI-complexity when absolutely necessary. A subtly blinking flash icon when the ambient light is too low, for example, or a similar HDR button when the sensor detects a very high dynamic range in the scene. It might be overkill to have these controls visible all the time, but they might make a big difference if presented conditionally.

Abandoning UI abstractions

As developers we refuse to accept that most of our userbase will never fully embrace the conceptual abstractions that we take for granted and depend on every day.

Modes. Hierarchy. Aliases. Virtual or "smart" collections.

We fool ourselves into thinking that because some of our users are able to use some of these things some of the time, they must understand them and like them. But really, the lion's share of our poor userbase has often just learned the steps or actions to accomplish their tasks without ever understanding what's happening under the hood. And at the first sign of trouble, they'll get lost, confused, and possibly angry.

Doing these things is hard, especially when you're building a product that was originally designed to scratch your own itch. And for every example of a design that takes this advice to heart, there are critics, detractors and disillusioned former fans who jump ship for a more advanced and customizable approach. But this tension between simplicity and power is where software design lives.

Unstuck

January 13, 2013

I get stuck a lot.

Bouncing between half a dozen active development projects as well as the other stuff I do at work, not to mention at home, creates a kind of multi-tasking hell. The constant context switches during an already interruption-filled day makes it challenging to eke out even a little forward motion. Projects are routinely left ignored for days or weeks.

Restarting these fallow projects becomes progressively more difficult the longer they are left untouched. In software development we have an expression for this: bit rot. As code is left untouched while its surrounding environment changes, and as the original developers leave the organization or move on to other things, the code becomes increasingly difficult to pick up again and improve or even fix.

That happens to my projects. The longer I haven't touched something the tougher it is to pick up again and move forward. I may have forgotten some important detail, forgotten what the next step was, forgotten what got me so excited about it in the first place. It takes a surprising amount of effort to page in the requisite mental state to make forward progress.

Just the thought of coming back to a large, ambiguous, difficult project becomes a barrier. Looking back on my notes and seeing the next step is no help: the next step is often big, hairy and loosely defined1.

So I have adopted a mental trick. When I consider coming back to a project that has been sitting for a while I force myself to only tackle a tiny, trivial, embarassingly easy element of that project. I might fix a typo or an itty bitty visual glitch, delete some previously commented out code, rename a poorly named method or two, whatever. Really, really low hanging fruit.

What is the smallest, easiest, fastest, least risky thing you could do to move this thing forward? Even just a fraction?

And 5 minutes later I am back into the project. The mindset I had when I was last working on it has seeped back into my subconscious and I can start planning my next move.

Until the next interruption.


1. Jeffrey Windsor and Ernest Hemingway both wrote about how they dealt with this in their work. Merlin Mann published a nice summary on his old productivity blog.

Archiving a TV News Segment

January 6, 2013

A few weeks ago during the peak of the holiday season our 3 1/2 year-old was interviewed for the evening news. It was a cute segment about the weather and his thoughts on Santa. He did great.

We wanted to save a permanent copy of the segment when it aired, but we don't use a PVR or any other TV recording device. Even if we did have a TiVo or cable-company provided PVR it is unclear whether a recording made with one of these things would serve as a good archive, given the proprietary formats and ubiquitous DRM.

What to do?

Most news networks now make their segments available for free viewing online. But have you ever tried to save one locally? It is enough of a challenge that I think most people would give up and just keep a link to the online version hosted by the news station. But again, this is not suitable for permanent archiving: links change, media companies and TV stations get bought and sold, and so on.

Here is the step-by-step process I used to download and store a permanent, high-definition version of the news segment on which my son was interviewed. I should probably point out that the legalities of following this procedure may depend on your geographic location and whether you have a reasonable fair-use claim on the content. In this case, as my son was the interview subject I think it's probably ok.

I should also point out that this procedure is highly dependent on the TV station website itself, and different websites might use different approaches, content delivery networks and so on. After reading through this procedure if you can't make heads or tails of what is going on you may want to delegate this process to a tech-savvy friend or relative. I would rate this at a difficulty level of 8/101.

  1. Identify the URL of the specific page on the TV network website where the video is available to view.
  2. Fire up Firefox with the Download Helper extension and navigate to the page.
  3. Start playing the video.
  4. If Download Helper picks up an .mp4 version of the video that is playing (not just Flash), you're done. Grab the .mp4, preferably in 720p or 1080p if available, and thank the lucky stars you don't have to go through the rest of this process.2
  5. Brace yourself. This would be a good time to make a coffee or something stronger. Clear your schedule, hug your family.
  6. Uninstall Flash from your computer. You want the TV website to think that you are incapable of viewing Flash. ClickToFlash and other Flash blockers are probably insufficient, although if you can find a way to selectively (but completely) remove Flash support from one of your browsers (preferably Safari), go ahead and try that instead.
  7. Set your browser user agent to the one used by Safari 5.1 on the iPad. I used the Safari Develop menu to do this3. The purpose here is to make the TV website believe you are on an iOS device, and are capable of viewing high-definition H.264 video. This is our preferred video archival format.
  8. Clear all your browser cookies and history. You want the site to forget that you ever visited with a Flash-capable browser.
  9. Navigate to the page where the video is shown. Play the video and wait until the pre-roll ads are done and the video is actually playing. Right-click on the playing video and Inspect Element (in Safari).
  10. See if you can identify something that looks like the video source URL, which (in my case) was a file called master.m3u8.
  11. This is a UTF-8 playlist file, and we need to download it to take a look. Download the .m3u8 playlist file (use wget or curl if you'd like), and open it in a text editor.
  12. We're getting warmer. This master playlist file references a number of stream playlists, each at a specific bandwidth level. Since we want an archive in the best possible quality, identify the line corresponding to the highest bandwidth rating. Note that this might not be the bottom-most line in the file. Download this stream playlist URL using wget or curl and open it in a text editor.
  13. Here we go. We're now looking at a sequential list of video files, probably with the .ts extension, that together make up the segment we want to download. Use wget or curl to download each one of these ts files locally, making sure to keep the sequence number in the filename.
  14. Recombine these .ts files (losslessly of course) into a single .ts file. I used tsMuxeR for this.
  15. You now have a single .ts file that contains your video segment. If you'd prefer the video in an mkv container (which might be easier for your playback environment), you can use tsMuxeR to demux the combined ts file into separate video and audio streams, and then use mkvmerge to re-package the streams into an mkv file.

Voila. A perfect archival copy of your news segment in 15 easy steps!


1. Relative to what, you might ask. As a rough guide, consider difficulty 1 to be playing the video from the TV website, and difficulty 10 to be replacing the video on the site with Never Gonna Give You Up. RickRolling the nation is 10 for difficulty and 10 for style.

2. Steps 1-4 are usually sufficient for almost all other difficult-to-grab video on the web. TV and news sites in particular seem to make things difficult.

3. You should be able to use the User Agent Switcher to get the same effect in Firefox, but for whatever reason I couldn't get it to work right with the segment I was trying to download. Safari worked a treat though, and its Inspect Element feature comes in handy for later steps.

Pizza Segmentation

December 30, 2012

Have you noticed that pizza seems to be getting a lot more expensive?

I started ordering a large 4-topping pizza online from our neighborhood Pizza Nova the other day and the total was going to be somewhere around $37 after tax. Before delivery fee and tip. That's a lot to pay for a pizza: well north of the local shawarma place and pushing into sushi territory. What's up with that?

Thinking about it a little, the answer is clear. Everybody eats pizza. From the elementary school kids scarfing down a slice and Coke for lunch to the commercial real-estate broker who doesn't have time for a restaurant meal to families like ours. Pizza, at least in our culture, is a universal food.

But not everybody pays the same price for their pizza. In fact, if I was running a pizza conglomerate I would be thinking long and hard about how to charge each of my widely varying customers the maximum amount they're willing to bear to address their pizza needs. Tough to do when the pricing is publicly posted above the counter and on every second flyer in my mailbox, but evidently not impossible.

Source: pizzanova.ca

Source: pizzanova.ca

A pepperoni slice and Coke is $3 at lunchtime. That takes care of the elementary school kids. A large pepperoni (pickup-only) is $10, but only if you dig up the special offer on the web site. That one is for the super-value conscious. And for me, $40 for a large 4-topping pizza. Because the actuarial masterminds at Pizza Nova have sorted me into a bucket for people that have a specific pizza vision and are either insensitive to the cost of actualizing that vision or too impatient to hunt down a better deal.

They're not wrong: I've been paying that much for pizza for years. But as of now, the $10 pepperoni is starting to look much more appetizing.

Spinning in Circles

December 23, 2012

Declarative programming, at least in the form I described last week and the week before, is by its very nature ambiguous. A computer can't really know for sure what I mean when I say "make this circle occupy 25% of the screen" because I haven't said anything about which 25% or what happens when I rotate the display or what if I have two screens or no screens?

Resolving these inherent ambiguities falls on the original assumptions made by the designer of the declarative framework. And declarative frameworks are made up of imperative code1, so that's what ultimately tells the computer how to draw my circle.

Take a look at my imaginary CSS example from last week. It might seem pretty definitive at first, but it leans on several implicit assumptions I made. You might share these assumptions, but the computer has some options for rendering the page2. For example, I neglected to specify that the left and right columns must be exactly the same width.

Let's say that I meant for the outer columns to have the same width, but my rendering framework renders the left column using only as much width as the contents require, and the right column using all the remaining width on the page. What now? How do I tweak my declaration to act in the way I actually want rather than the way the computer assumes I want? How do I tell CSS, even my awesome imaginary CSS, that the remaining width of the page should be split evenly between two separate columns?

I've seen a lot of ugly hacks in my day, but I think the ugliest hacks of all are the ones that try to coax non-default behaviour out of a declarative framework. This is the realm of negative margins in CSS, comically convoluted XAML control template specifications, key path sequences in Cocoa key-value coding, hand-optimized SQL querying in Rails, and so on.

Trying to make a declarative framework do what you want rather than what it expects is one of the most painful things I've ever experienced while sitting in front of a keyboard. And you can't just override the default behaviour unless the original framework designer gave you a specific mechanism to do just that.

So, do we just eschew declarative programming entirely and stick to layering progressively more abstract layers of imperative code on top of each other?

Maybe for now.

But declarative programming speaks to a bigger vision: an unrealized dream of what programming could be someday. Programming where we just sketch out a rough outline and let the machine fill in the details. Programming at a level of intentions and desired outcomes rather than menial shifting and sifting of data structures and algorithms.

10 MAKE THE WORLD EXACTLY HOW I ENVISION IT OUGHT TO BE
20 GOTO 10

Imperative control loop for a really great declarative program

In a way, declarative programming shares a lot with that other unrealized dream, artificial intelligence. Maybe they're actually two aspects of the same thing. And as with artificial intelligence, just because we're not there yet doesn't mean we should stop trying.


1. At the lowest level, all code executed by a computer is imperative. Everything eventually gets compiled to very specific, well-defined instructions along the lines of "move this bit of memory here" and "add 1 to the value in that bit of memory over there."

2. There are more ambiguities than this. I didn't explitly state that the columns should appear beside each other, either, so the computer could legitimately stack the divs vertically without violating my constraints.

Circling the Declarative Drain

December 16, 2012

Last week I sketched out the rough difference between imperative and declarative approaches to programming, and admitted that I cut my teeth on the former. I alluded to the deep-seated fear and distrust I harbor of declarative approaches, although I didn't actually write that. So here I am writing that.

Let's look at a (sort of) modern example: using DIV tags and CSS to lay out a web page. This is a mostly declarative technique in that you don't tell the browser exactly where to put each element and how big it should be. Instead, you set out some constraints for the elements and let the browser work out the rest. In theory, with sufficient constraints, you should get precisely the behaviour you want by expending a tiny fraction of the coding effort that would be required if you approached this imperatively.

Let's pretend for a moment that we lived in a world where this was actually the case. What would such magical markup look like? What is declarative at its best?

I present to you the classic1 fluid-fixed-fluid 3-column layout. Your web page is divided into three vertical columns. The middle column is fixed to a width of exactly 300 pixels. The left and right columns grow and shrink evenly to fill up the remainder of the available browser width2.

Thar she blows

Thar she blows

What if we had an elegant, semantic and precise markup and styling language to define this behaviour in code?

<head>
    <style>
        body { width: 100% }
        div { height: 100% }
        .fixed { width: 300px }
        .fluid { /* I don't even need to put anything here because it would be redundant */ }
    </style>
</head>
<body>
    <div class=fluid>This is the left column</div>
    <div class=fixed>This is the center column</div>
    <div class=fluid>This is the right column</div>
</body>

You may quibble with my making it look like modern-day HTML and CSS, but you'll agree that this is fairly concise and semantic: it doesn't take long to read, and it's pretty clear what I'm trying to accomplish. The key is in the <style> tag near the top: see how little CSS it takes to make things work in my imagination?

There are a couple of ways to make this happen in actual HTML and CSS, and they're all horrific. Take a look at this representative example, which I tried to use a couple of weeks ago. Much as I wrote in 2008, I ran screaming back to tables around the time I started trying to get more than 2 browsers to work at the same time.

But even if this solution did work on lots of browsers (it doesn't), and even if it didn't suffer from a handful of other annoyances (it does), just take a look at the markup required. I SAID LOOK AT IT. And weep as I do.

Next week, if I've recovered my composure, I'll use this one example to make a broader hypothethis about why this happened, and continues to happen, with declarative approaches to programming problems.


1. Classic only to me, in the sense that I bang my head against it every few years so it feels like an old, familiar, foe.

2. See what I just did there? I declared an (almost) complete specification for the behaviour of our page. That's how we'll be doing this 50 years from today, or today, if we can just delegate this whole mess to the intern.

How to Draw a Circle

December 9, 2012

In Grade 4 I really started getting into the programming groove. The high-res graphics capabilities1 of the Apple II Plus begged for tools that took advantage of them. One my first serious2 programming projects was a bitmapped image editor I named SuperDraw. Lovingly handcrafted in Applesoft Basic, it was my crowning achievement at the time. But it couldn't draw circles.

If you think I could just call Ellipse(0,0,50,50), I'll remind you that fancy graphics libraries that abstracted away shape primitives didn't come until years later. If I wanted a circle I would have to figure out where to put each individual pixel. I consulted a family friend who happened to be a math tutor. He started by showing me the equation for a circle:

How to draw a circle

x2 + y2 = r2

The square of the x-coordinate plus the square of the y-coordinate is equal to the square of the radius for any point on the circle. Simple, right?

You might imagine a 9-year old Gene puzzling over how to turn this mathematical identity into a recipe for iterating over the x and y-coordinates of a circle of radius r in order to light them up on the monitor. This is actually non-trivial, and if you have some spare time I recommend this excercise as a good way to review your trigonometry.

What I'm getting at though is that a description of a circle, even if it's perfectly accurate and complete, doesn't tell you very much about how to draw one. This is the difference between declarative programming and imperative programming.

The programming with which I grew up was pretty much purely imperative. You gave the computer instructions and it followed them. These instructions might have been in a procedural language (like Applesoft Basic or C), an object-oriented language (like Java or C++) or even a functional language (like Lisp). It all boils down to the same thing: a predictable flow of control through a set of instructions that eventually leads to the desired outcome, or if not, can be traced through step-by-step to isolate the problems.

As the complexity of your problem grows, purely imperative programming can become a bit of a drag. Its effectiveness is based on your ability to abstract away that complexity in layer on top of layer of logic. Near the bottom layer you have methods that calculate the pixels in a circle, somewhere in the middle you have methods that draw complete circles and squares, and near the top you have methods that, for example, draw an organizational chart of your company given a database of the employees and their job titles.

For decent-sized programs that can be a lot of layers and a lot of code to manage. All this complexity: isn't that what computers are good at? Can't we just tell the computer what we'd like achieved and have it figure out how to get there?

Declarative programming is just that. "I'd like to live in a world where there was a circle at (0,0) with radius 25" is the declarative equivalent of "please draw a circle at (0,0) with radius 25." But declarative scales better. You could declare a complete screen layout, with associated constrants ("this circle should always occupy 25% of the window width") and trust the computer to resize the circle as the window is resized. The imperative approach, on the other hand, would require an event handler to catch a resize when it occurred, get a handle to the circle, recalculate the new size, and so on.

At their best, declarative frameworks and approaches can dramatically simplify the specification of complex systems and interactions. And next week I'll illustrate why things don't really work out that way.


1. 280x160, 6 colors, 4 lines of text at the bottom of the screen. Sweeet.

2. I was an immature hack up until then, but Grade 4 was really the turning point.

Just Give Up Now

December 2, 2012

That thing you've been thinking about doing? That great idea of yours? Maybe you've already started on it? Don't bother. Here are just a few of the reasons it's not going to work.

  1. It has already been done. Fire off a couple Google searches and I'll bet you'll find at least one or two nearly identical approaches.
  2. There's a better way to do it. You might believe your approach is solid, but have you really thought through all the angles? Are you a domain expert in this field? The likelihood you've come up with the best approach is miniscule.
  3. There are people working on it right now who are smarter than you, better funded than you, and have way better taste. They are going to launch imminently, maybe even in the next couple of weeks. Are you ready to go up against them?
  4. It has already been tried, unsuccessfully. During the dot com boom there were probably three different venture-funded startups that went down in flames trying the very thing you're considering.
  5. It isn't aligned with your long term goals. How does this idea even fit in with your family plans? Your career plans? Your life plans?
  6. It's low priority. You have way more important things to be worried about right now.
  7. You don't have the budget to do this well. Even if you could hack together a duct-tape prototype of this thing, it would take an engineering team 6 months and a truckload of money to build something worth bringing to market.

And so on. It's easy to crush an idea.

Look, the truth is that taking the leap of faith required to make ideas happen requires not looking down. If we all understood the risks of what we were attempting and had an objective assessment of our odds, nothing new would ever get built.

Everything I've said so far is probably true about your ideas and about mine. Forget it. As Dr. Seuss wrote so poignantly in The Lorax, "Unless someone like you cares a whole awful lot, nothing is going to get better. It's not."

And if you think that any or all of the arguments above are a legitimate reason to abandon your idea, buy me a beer and I'll explain why you've got nothing to worry about.

Native Mobile or HTML5

November 25, 2012

You're building a new web-based application or service and you want to offer a mobile solution to your users. Do you build a native app or tailor your website to mobile clients using responsive HTML5 and JavaScript?

It's tricky.

If you agree that native apps will offer the better user experience (and I believe that, with practically zero exceptions, they will), the gut instinct is to build out native apps for your chosen mobile platforms. But which platforms? Well, you need an iPhone and iPad app, and you need to support both the retina and non-retina versions of each, and yeah, Android support is pretty important these days, and maybe a lot of your target uses Windows on the desktop so you want to cover your bases with a Windows RT client.

Ruh Roh.

You've just signed up for about 10 developer-years of extremely expensive effort. If your business is still in the "if we build it they will come" stage, this is probably ill-advised.

The TimeTiger web client running in mobile Safari

The TimeTiger web client running in mobile Safari

So maybe for now, you can put optimal user experience on the back-burner and develop a nice mobile-friendly responsive web site. This comforting idea is a dangerous illusion, as:

  1. Cross-platform responsive web development is incredibly difficult and fiddly, and can actually take longer than native app design using decent tools.
  2. Even when you get it right, the average user's mobile web experience will be significantly worse than an equivalent native experience.
  3. Once your business is off the ground, you will eventually want to make native clients anyway, so much of this effort will be wasted.

Your choices boil down to diving into the bottomless pit of native mobile development or sacrificing your app at the altar of crappy user experience. Not ideal.

The only way forward is to consider, deeply, your users. What are they using now, what are their expectations and what are they willing to accept in order to gain the functionalty you're offering?

"What you tolerate defines your community." - Heather Champ at Web Directions South 2012

If you are developing an app targeted at a design-conscious, consumer audience whose attention you need to grab and hold, it is absolutely essential that you provide a magical and delightful experience. Don't trick yourself into believing that HTML5 is enough: learn from Facebook's mistake.

On the other hand, if you're providing a hard-core business tool where the appeal is in the actual functionality or data you're offering, you can probably get by with a responsive web solution for now. If your users are thankful just to be able to get what you've offering on their device, no matter the form, you're good. If your users are typically not very design conscious, in that they don't care whether you have nice smooth transitions between pages and maybe can't even tell whether they're looking at a retina device or not, you're good.

Good for now because everybody likes to use great software, even when they aren't consciously aware of what makes the software great in the first place. All things being equal, a competitor will eventually develop a native experience that, even if it provides less functionality, will still start pulling users away from you. Unless and until browser technology improves and converges, providing your mobile experience in the form of responsive HTML5 is a shunt: good enough for now, but that's it.

A Consumption Device

November 18, 2012

For as long as the iPad has existed it has faced criticism about what it could and could not be used for. Legions of bloggers tripped over themselves labelling it "a consumption device," while an equally vocal contingent relentlessly pointed out examples of the iPad being used in well known and respected art and literature, music production, construction, medicine, and so on.

The myth of the iPad as a consumption-only device was thoroughly debunked, at least in the eyes of many Apple enthusiasts. It might or might not replace your MacBook, but you could certainly use it for more than watching movies and reading iBooks.

This was an exciting time, the birth of the "Post-PC" era, and I, like many others, wanted to experience the wonder. I was inspired by articles by Mark O'Connor, who talks about ditching his MacBook in favour of an iPad to do bonafide software development on a 200,000 processor system. I dreamed of a world where I could do most, if not all, of my work on an Internet-connected iPad.

My day-to-day work responsibilities are a grab bag of operations, support, sales, customer service, and development, so I had no illusions about being able to dump my 15" MacBook Pro on Day 1. But gradually, I started pushing more and more of the systems and processes I used into the cloud. My vision was to be able to do everything except actual software development using an iPad, and from anywhere in the world.

Source: Mark O'Connor, Yield Thought blog Source: Mark O'Connor, Yield Thought blog

You don't need to hold the iPad mini for long to realize that it is something special. In fact, some Apple writers are proclaiming that it is what the iPad should always have been. Careful not to take anything away from its big brother, they are choosing the mini for themselves in favour of the larger option.

But for what use?

From what I can tell, to consume rather than produce. MacBook Airs or Pros are for doing work, and the blissfully light, thin, and compact iPad mini is for e-mail, Twitter, reading and surfing. Choosing the mini as your iPad seems to be an admission, perhaps more of a realization, that if you're working, you'd rather be doing it on a MacBook.

My fear is that treating the iPad as a primary production device is going out of favour. That there is a growing belief that although it is possible, it is rarely optimal, and almost never preferable to using a MacBook for the same job.

There will always be exceptions of course. Some applications are so amazingly well suited to a tablet form factor that you'd never want to be using them on a laptop if you could avoid it. But something as simple as web-based surfing and research feels like swimming upstream when you factor in the need to jump to 1Password, excerpt and annotate the research material, clip and edit images, create the occasional PDF etc. Weak interapp sharing mechanisms, the prohibition of system-wide 3rd party productivity utilities, no split-screen capability, and no centralized file store all conspire to make the experience clunky and unpleasant.

Surprisingly, it is Microsoft that seems to be holding up the banner of tablet productivity highest. The Surface is a flawed product, with a half-baked OS, and a weakening team behind it, but Microsoft, bless them, is trying so hard to make Surface your primary work device. It's a shame they've got so far to go.

Best Enough

November 11, 2012

Dustin Curtis just published an interesting post about the payoff you get from finding and choosing the very best of whatever you own and use. He argues that it is better to have a few very nice things that work just the way you want and that you can blindly trust than it is to have many things that aren't quite right.

I like this idea, and over the past few years I have tried to incorporate a "less stuff, but better stuff" approach to my life. In some things I have been successful, and in some things I have failed. Now I'm convinced that it would be madness to try to apply this approach to everything, or even to most things.

Finding "The Best" is expensive

Financially to be sure, but more importantly, the research, selection, evaluation, acquisition, maintenance and divestiture of "The Best" is significant. Dustin talks about the 20 different sets of flatware he bought and tried before settling on "The Best." With no derision intended, there are only a few things on which I can afford to lavish such passion. A very few things.

Living up to "The Best" is all-consuming

I spent the better part of 2012 fiddling with Vim to try to make it "The Best" editor for me. Hours and hours of (admittedly enjoyable) learning and tweaking and asking and banging my head against a desk. I could never quite get it to where I needed it to be, and I'm using something else now. I don't regret the time I spent, but make no mistake, that was a lot of time.

When you commit to using "The Best" IDE, or driving "The Best" car, or using "The Best" kitchen utensils, you are commiting to constant learning, honing, tweaking, maintaining and upgrading. These are fantastic things to do for a few things in your life. A very few things.

"The Best" does not actually exist

There is a well-known sales tenet having to do with consumer education. The more educated a potential customer becomes about the product area, the more likely they are to up-sell themselves to a "better" solution.

For most of my life I had no interest in coffee, but over the past few years I have "educated" myself up from pre-ground department store beans and a French press all the way to locally roasted artisan beans and a Rancilio espresso machine with a hacked-on PID controller that keeps the boiler temperature within a 0.2 degree range. The tamper I use has a lightly rippled base to prevent channeling.

Reg Barber Ripple Tamper Base

And guess what? I could be doing much better, but I have decided to stop here for now.

Once you start down the path to "The Best," there is no end. Ask a photographer what "The Best" camera body is. Or a designer about "The Best" layout software. You see, "The Best" is not a product or solution at all. It is a journey towards perfection. A challenging, fascinating, often frustrating journey that you should only be on if you care an awful lot about the destination.

And how many of these journeys do you want to be on right now? How many can you afford to be on?

For almost everything in our lives, there is a "good enough," and stopping there is the right move. Sufficiency does not preclude excellence, but it's a great way to stay out of the rabbit-hole of perfection. Err, I mean, "The Best."

The Lifification of Games

November 4, 2012

I grew up playing fantasy role-playing games on my computer. I don't recall whether my Vic-20 ever had anything in that genre, but I fondly remember long hours spent in front of my Apple II playing Ultima II, III and IV. Ever since then I've always had one or three of these on the go.

Back then I wasn't trying to play through these games. I don't think I even realized that the Ultima games had a end-goal. To me, they were worlds explore and master. Immersive fantasy environments that I could live in, for a few hours each day. Finishing the games was something I did, or didn't do, once I got bored of playing them.

These days I have been playing Skyrim, World of Warcraft, and EVE Online. All fantastic games and truly immersive sandbox environments. WoW and EVE especially, as MMOs with epic scope and vibrant communities, fulfill my every wish of having an alternate world in which to kick back and relax after a tough day in the real one. Or so it would seem.

Dusk over Windshear Crag

You see, I spend most of my work days happily sitting in front of a computer and a keyboard, sometimes talking into a headset, working towards individual or team goals that I have set for myself or others have assigned to me. When I complete those goals I am rewarded in larger or smaller ways, and I advance in my longer-term objectives and plans.

My job is an MMO.

And the games I play are looking more and more like a job. My quest list in WoW looks a lot like my task list at work. They both involve typing some things on my keyboard, responding to things happening on my screen, maybe solving a puzzle or problem, occassionally speaking with people on my headset. I enjoy doing both, but they both kind of feel the same.

The games I play now can't be called simple any more, or even relaxing. The mechanics, plotlines, strategies, and gear has become so expansive that they are their own field of study. One printed strategy guide for the latest WoW expansion, Mists of Pandaria, clocks in at 456 pages. And because WoW is a social game, you are expected to know what you are doing when playing with others. In fact, at the higher levels of the game, you are expected to practice.

So I consciously opt-out of these Alpha-groups and concentrate on having fun. Playing at my own pace. Enjoying the environment and the world, like in the old days. But I can't help feeling that I might as well be spending more time becoming a superstar in the real-world rather than a scrub in the virtual one.

Report the Bug

October 28, 2012

Has this happened recently to you or someone you love?

"I was using this software/web service today and all of a sudden it crashed/reset/did something unexpected. I had to re-type everything, and I didn't even have it written down or printed out. Man I hate company. They should really get their act together."

Here's the thing. We, as software developers, try hard to make our software as bug-free as we possibly can. It doesn't matter: a few of the suckers will always make their way into production code. Even if it were possible to test every single line of code in a non-trivial system against every possible input (it isn't), heterogeneous operating environments, shifting technology stacks, integration with external systems and components, network latency, and random acts of configuration madness™ will always conspire against perfection.

In other words, every piece of software you are using right now is buggy.

A lot of people understand that; they've accepted it. They have become passive victims to our industry's inability to achieve perfection.

They do not submit bug reports.

I have witnessed the most heinous acts of software cruelty perpetrated against nice, normal people just like you and me who have walked away shaking their heads and just feeling frustrated and sad. If there was one message I could send to all of these victims it would be this:

"If the software does something you do not agree with, report the bug."

It often doesn't occur to people to do this. They think the developer doesn't care about their problem. Worse, sometimes they think they themselves are at fault! As software developers we use the bug designation "by design." In other words, the software is working as we expect it to, but for whatever reason that didn't work out for the user. Well, guess what? Sometimes, there is a bug in the design. So:

"If the software does something you do not agree with, report the bug."

Apple has an ancient bug tracking system colloquially called Radar, actually named Apple Bug Reporter. A bug I submitted in June against Apple Mail has an ID of almost 12 million, and the reported bugs are numbered consecutively, allegedly starting at ID 1 from sometime in the late Jurrasic, probably. This bug, and every other bug I've ever submitted to Apple, have been marked as duplicates. Apple has so many detailed bug reports in its database that it is almost impossible to stumble over something new and novel and this is great. Apple is aware of and able to prioritize almost every conceivable defect or perceived defect in their software. The culture in the Apple developer community is that you're not entitled to complain about a bug in one of Apple's products unless you've already filed a Radar, duplicate or not.

Radar or GTFO

Photo of Michael Jurewitz, former Apple Developer Tools Evangelist, taken by George Dick. "Radar or GTFO" addition by Steve Streza. Image taken from a Black Pixel blog entry by Daniel Pasco. These guys know a thing or two about fixing bugs.

It is telling that so many of these issues are still unresolved. Again, with any non-trivial system, fixing every single reported issue isn't possible because some solutions would cause other problems, or would require fundamental design changes that would negatively impact the product as a whole. Or would take the product in a direction other than the one the developer envisions. Or will soon be obviated by a planned update to the system that replaces or upgrades that part of the functionality. But just hearing what customers find flawed with the system is invaluable.

"If the software does something you do not agree with, report the bug."

Do you have a bug to report in TimeTiger? Do you have a feature suggestion or just feel that something could work smoother, faster, prettier? We might not fix it right away, but I guarantee that we appreciate your input.

"If the software does something you do not agree with, report the bug."

A User by Any Other Name

October 21, 2012

When we were starting Indigo in 1997 I sought $100K of angel financing from an old friend and mentor. Michael Schweitzer, who passed away in 2003, had taken me under his wing at the age of 15 and we remained close throughout my university career. I am still in awe at the learning and opportunities which I owe to this friendship, and I will always be grateful. Michael and his company became one of Indigo's earliest clients, so his participation, both financial and advisory, seemed like a perfect fit.

As we proceeded through the informal negotiations Michael met my co-founders and started to learn more about our collective goals and beliefs. At the last minute, just before there was an actual contract to sign, Michael pulled out of the deal.

Feeling crestfallen and a little betrayed, I wanted to know why.

"Gene," he said, "in every conversation I've had with your group, all I've heard about was your new approach. How special this thing you were trying to build was going to be. How your team was so great. I didn't hear anything at all about us. About the customers, and our needs."

One Perspective

He continued. "I don't doubt your team's ability. You've put together a strong group. But I just don't think you care enough about us. I hope you guys do great, but until I see that you've become more focused on your customers, I won't invest."

Predictably, I dismissed his opinion out of hand. And of course, he was absolutely right. Over the years I have started to learn to project our focus externally, rather than internally to our organization. And I chuckle a little bit when I have conversations with people, and startups, that haven't quite gotten there yet.

Jack Dorsey of Square and Twitter posted a nice piece on not wanting to attach the labels "customer" and "user" when more specific labels, like "buyer" and "seller" are available. A number of prominent bloggers responded to this labelling issue, including Marco Arment who posted an interesting take on the relationship between the label and the business model that drove it. Jessie Char jokingly goes further, and is (not really) trying to eliminate the term "client" entirely from her organization's vocabulary, preferring "friend with benefits."

It makes me wonder what organizations like Facebook call us behind our backs (my guess: "meeple").

But for me, Jack's second point resonated more strongly. "... all of our work is in service of our customers. Period." I think Michael would have felt that way too.

Update: Jessie was kidding. Duh.

Getting Rid of Stuff

October 14, 2012

The toughest part of my hardware upgrades is getting rid of the old stuff. Most of the time it still works perfectly, and even if it didn't I wouldn't want it in landfill. So I've been mastering the art of efficiently divesting myself of old "stuff."

Here's my current checklist, roughly in order of preference. If you're already on top of this and are about to skip this post, I urge you to at least read the section about Freecycle if you're not already familiar with it.

Photo: Michelle Arsenault, licensed under Creative Commons Attribution-ShareAlike 3.0

Landfill, by Michelle Arsenault, August 2008

Can I hand it off to friends or family?

Typically I will only do this for stuff that is in great working condition and is being replaced for reasons other than obsolescence. I was recently able to hand off a really nice flatbed scanner that I hadn't used in over a year to my brother. I had to pony up $40 for a replacement powerbrick to make this happen, but I still feel better now that it has a good home.

Can I sell it to a company that buys this stuff?

For some stuff there is a trade-in or cash-back option provided by a reputable retail or mail-order company. For example, in the U.S. Gazelle is apparently very convenient for trading in Apple stuff. Here in Toronto, when I upgrade my Mac stuff I trade it in at Carbon Computing. Carbon is very low-hassle and they'll cut you a cheque after they inspect and test your equipment. Along the same lines, big camera shops like Henry's will take used camera gear for trade-in.

You won't get as much as you would like by going this route, but it's highly time-efficient and requires very little work on your part. Plus it gets the stuff out of your hands fast.

Can I sell it online?

Your success with this will vary, as will your level of comfort. I've sold 3 or 4 used iPhones on eBay over the years, and I've made more than enough on each one to fully pay for a new (subsidized) iPhone. Except for the one time I shipped to Malaysia without tracking information, and surprise surprise, the iPhone "never arrived." It was my own mistake for not charging enough for shipping to pay for a waybill-tracked delivery method, but still, an expensive annoyance.

A couple of my friends are master Craigslisters. I've only had one Craigslist experience and it was negative (a no-show on a Sunday night in a Costco parking lot: very shady), and that has put me off. But they tend to deal in high-end furniture and home fixtures, so that scene is probably different than the one for the Xbox I was going for. Anyway, each time they move (and they move a lot), they are able to unload all their old stuff for at least as much as they paid for it, and then refurnish for less than that. I think they might actually be cash-positive on their moves (or at least cash-neutral). They should probably be the ones writing this post.

Can I donate it?

There are probably non-profits in your area that want your working computer gear. I have donated equipment to specific organizations where friends have worked, and it's a nice feeling to know your stuff will be used for a good cause. It can sometimes take a little work to identify appropriate organizations in your area and arrange for pickups and deliveries, but it's great when it happens.

Can I Freecycle it?

How can everyone not know about this? Freecycle is magic. It is the fastest, simplest, most responsible, most rewarding and lowest hassle way of getting rid of just about anything, including but certainly not limited to electronics, as long as you're willing to give it up for free.

Once you've joined the Freecycle group in your area, simply post a brief note about what you're offering (for free) and your major intersection. Once a moderator has approved your post (often the same day), you will start getting e-mails (sometimes a flood of them) from people who are willing to come to your home (or a place of your choosing) to pick up the item.

You can choose the best recipient. Most of the time I will pick the first respondent, but occassionally one e-mail will stand out as representing a particularly good fit for the item I'm donating. You can then arrange a time for the pickup and you're done. Post another note saying the item has been claimed to stem the assault on your inbox.

I've Freecycled dozens of items, including everything from fully functioning rack-mounted servers to "box of random cables, most functional," and there has never been a no-show or any other hassle. So simple. So awesome.

Can I recycle it?

When all else fails, big box chains like Best Buy are now recycling electronics gear. Apple recycles old Apple stuff, although you can almost always sell functioning Apple stuff. Even your municipality might be aggressively recycling old electronics. Your gear should never have to end up in landfill.

Start by Being Terrible

October 7, 2012

Are you a good driver?

I don't mean professional-grade, just better than most of the jerks you're constantly dealing with on the road. You're an above average driver, aren't you?

Despite what we would like to believe, not all of us are above average. In fact, there is probably little correlation between someone's perceived skill behind the wheel and their actual skill. By definition, we cannot be objective about our abilities in any particular field, whether we are complete newbies or seasoned veterans. Not all "veterans" are good. Without some external expression of our work, for others and even ourselves to point to and compare to our original vision, we have no sense of how good we actually are.

This can be useful. If we fully appreciated how terrible we were at something new, we might never stick with it long enough to become better. Imagine taking a dancing class where you were always keenly aware of how ridiculous you looked. It would be hard to concentrate, and impossible to enjoy the experience. It is only by putting aside our internal self-assessment that we can push past terribleness.

Iteration

What do you think about this post so far? Do you think you could express this idea more efficiently, or with a little more flair?

I have been reading blog posts on the Internet for far longer than I have been writing them. It is only when I actually started writing that I felt the full weight of my ineptitude. I love good writing, online and off, and I presumptuously considered my own skills on par with what I was reading. I often felt that I could have written that same post, maybe even a little bit better.

But just trying to express my ideas in writing has shown me how much I have to learn. Now that I've started, and now that I see just how bad I am, maybe I can begin to improve.

You might think I am being too hard on myself, and you might have heard other writers express a similar sentiment. Know that the reason a writer (and perhaps any type of artist) is their own harshest critic is because he is sensitive to just how inefficiently, self-indulgently, pompously, inconsiderately, condescendingly, and ignorantly he has sprayed what started out as a pretty good idea onto the page.

Even if you happen to be enjoying this post, I guarantee it is a poor shadow of the idea in my head. And that's what I'm trying to get at: our ideas are good, but we are arrogant to think that we can express them with perfect fidelity. That all of their strength and virtue will land on the page, or in the presentation, or the source-code.

That can happen, but only once you have started becoming less terrible.

Taking Advantage of the Sum of Errors

September 30, 2012

Estimating project schedules is hard. It is especially difficult for larger projects, and it is not uncommon for projects in my industry, software development, to be underestimated by several multiples. Sometimes, an order of magnitude and up.

I am not going into why that might be the case: it has been widely discussed and may the subject of a future post, but suffice to say, it happens all the time, and even to experienced project managers. Here is one way to look at project estimating that helps me keep things mostly reasonable, most of the time.

Consider an interesting little script that you think might take 10 hours to write. For the purpose of this example, let's say that our estimates are always 50% off, in one direction or the other. This might seem egregious to you, but in the software industry only being 50% off is practically omniscience.

So, we have made a 10 hour estimate with an expected error of 50%. The script will actually take either 5 hours or 15 hours to actually finish. How can we improve on this?

What if we break down the work of doing the script into 10 smaller pieces and estimate each of these individually? Even a small script will require a documentation/usage page, command-line option parsing, some sort of input processing, maybe an algorithm or two, some output, some error-checking, perhaps a non-trivial edge case it might need to handle. Don't forget the effort of creating a Github gist for this, or creating a remote source-code repo to which you can push your hard work.

Now we have 10 items, and we try really hard to accurately estimate each one individually. By sheer coincidence, our best estimate for each of these 10 items is 1.0 hours, providing a total estimate of 10 hours for the script. And our estimation error is still exactly 50%, so each item in our estimate will actually take either 0.5 or 1.5 hours to complete. Assuming we err on either side equally, here is the estimated vs. actual for this project.

Sum of Errors

The individual estimation errors for each task have effectively cancelled each other out, giving us an extremely accurate overall estimate.

Sure, these numbers are contrived for the purpose of this example, but the punchline is still useful: the more chunks into which you decompose your project, the more accurate your estimate will tend to be. The sum of errors will approach 0 as the number of estimates increases, assuming a normal error distribution.

An unfortunate consequence of more accurate estimates tends to be larger estimates. But that's a subject for another day.

An Alternative to QuickBooks

September 23, 2012

I've been keeping an eye out for an alternative to QuickBooks to handle small-business accounting. Sure, QuickBooks is big and comprehensive, but I only use 5% of it, and frankly I'd rather do that 5% much differently.

Now this is how you do accounting

The recent craze of plain-text writing and blogging workflows has brought me back to a project that I've been circling around for several years. You may not know this, but there is a plain-text accounting system. It's called Ledger and it's amazing.

The idea behind John Wiegley's Ledger is that you type your transactions into a great big text file. You then run the super-fast Ledger command-line processor, and specify what sort of output you'd like to see, such as a list of account balances or a detailed register for a particular account.

Think about that for a second. Every single one of your transactions is crunched when you're simply curious about how much is left in your chequing account. Sound crazy? Not really, because Ledger is so screamingly fast (and, being devoid of UI, so efficient at processing large batches of transactions), that in the time it would take you to submit a single transaction in QuickBooks, Ledger can process them all.

Once you bend your mind around this unusual process, you start to see the possibilities. TextExpander snippets for common transactions. Scheduled jobs for generating and e-mailing key reports. A bare-bones web UI for report generation, perhaps that your accountant can access. Simple integration with your website or other systems. There are a lot of interesting things you can do when freed from the constraints of UI-laden accounting software.

So, how to start? I made a Ruby script that converts your entire QuickBooks transaction history into something that is immediately usable in Ledger. So usable, in fact, that your Ledger trial balance should match your QuickBooks trial balance.

Here's how to use it:

  1. In QuickBooks, generate a Journal report for the date range All. In my version of QuickBooks, this is in Reports > Accountant & Taxes > Journal.

  2. Export to a comma separated values (.csv) file, say journal.csv.

  3. Run the script as follows:

    qb2ledger journal.csv > ledger.dat

  4. Now you can run Ledger directly against this data file. So, for a list of account balances, you could run:

    ledger -f ledger.dat bal

So far I have found one annoyance: older versions of QuickBooks don't escape double quotes when exporting the CSV file. That means you'll have to go through and escape them yourself if you happen to have a few double-quotes scattered around your transaction memo fields. I had a number of things like Samsung 15" monitor, for example. To help with this, you can use this regexp to search for double-quotes that don't belong:

\"[^,]*\"[^,]*\"

Once you find them, you can simply preface them with a backslash to allow qb2ledger to parse them properly, or do what I did and get rid of them in the original QuickBooks transactions before doing the export.

Now, rather than moving all of your historical transactions over to Ledger, you may just want to close off that set of books and start a new one. In fact, I might go this route myself, but this script is still useful for getting a handle on how Ledger could work for you. And that's important, because Ledger isn't for everyone. If you know your way around double-entry accounting, though, and want a fast, powerful, extremely flexible sledgehammer of a solution, you should take a look.

Have more questions about Ledger? Take a look at the Ledger site or read through the full documentation. There is an IRC channel as well, #ledger on freenode. Have questions about my qb2ledger script? Ask me on Twitter.

There and Back Again

September 16, 2012

The first new car I ever bought was my beloved 2001 Honda Prelude. I obsessed over every detail of that car, spending hours in the crappy Flash-based Honda online configuration tool before ever setting foot in the dealership. I babied the Prelude for every one of the 10 years that I owned it, and when I finally sold it it still looked like it was fresh off the showroom floor.

But times change, and a new baby and the need for more carrying capacity eventually made it necessary to move to a more practical vehicle. So when I picked up Forza 4 for the Xbox, one of the first things I did was check whether my old car was represented in the huge catalog of available in-game vehicles.

It sure was, and I scooped it up for 6,000 CR (which seems disrespectfully low, regardless of what a CR is "worth").

The in-game Prelude was only available in a few colours, and not in the Electron Blue Pearl of the earstwhile object of my obsession. Forza allows you to re-paint your car in any color you want though (for free!) and in moments I was looking at an amazing likeness of my old car. I shook off the very mixed feelings and jumped into the driver's seat to start a race.

Lo and behold, the dashboard was lovingly reproduced. I was floored.

I don't own this car any more And this one isn't even real

And then I heard the engine roar. The Forza team actually went and matched the engine sound of the 2001 Honda Prelude. I was nauseaus.

And sad. Because I went from owning my dream car to only being able to drive it in a computer game.

Still won the race, though.

Leader of the Pack

September 9, 2012

Recently I spent a moment watching a thin, scraggly looking guy walking a group of 6. Large. Dogs. Every once in a while, one of the dogs would try to pull in one direction or another, but, with a little bobbing and weaving the guy was able to unsteadily navigate in one general direction.

Were the dogs to all pull in the opposite direction this poor guy would instantly become cargo. He'd have no chance. And the dogs each demonstrated, from time to time, an individual desire to go in a direction other than the one imposed upon them. But their lack of coordinated action, in fact their lack of awareness that coordinated action was even possible, kept this little guy in charge.

Force equivalence

Putting aside for a moment that these dogs were evidently loyal, well trained animals that were not imminently going feral, it is interesting to look at it from the other side:

The thing that allowed this one small guy to take the 6. Large. Dogs for a walk was that he had a destination, and they, as a group, did not.

3-day

September 2, 2012

A few years after graduating from University I noticed that I wasn't very happy. By all accounts I had no reason to feel this way: a decent career, great friends, a healthy family, nothing to complain about. And yet I couldn't shake the feeling that some days I didn't want to get out of bed.

Probably Not the Answer

I had (and still have) friends who suffer from various forms and intensities of depression1. I did not realize at the time just how prevalent mental illness was, but I still knew that I didn't want any part of it. I was genuinely worried that I might be suffering from more than just the blues.

I wasn't sure, so I decided to implement what at the time seemed like a pretty clever lifehack. Every morning I would log, on a scale of 1-10, how happy and energized I felt. Just one number. And then based on what I wrote, I would choose my activities accordingly.

If the number was high, say 7 or above, I would go try to be all that I could be. If the number was 3 or lower, I would indulge myself in low-effort tasks and usually just spend the day watching movies and playing video games. I was working from home and mostly independently at the time so I didn't have to deal with going into the office every day. That was a big help in pulling this off.

I had some simple rules during these low-energy days (that I later dubbed "3-days"). No command decisions, no new projects, and no difficult work. Any time I found myself doubting the direction my life was taking, questioning my important relationships, or impatiently re-thinking a major work initiative I would remind myself that it was a 3-day, and I didn't make these kinds of moves on a 3-day.

This was a big relief. It was an instant excuse to short-circuit the downward spiral of doubt, fear, anxiety and guilt that I remember feeling during those days. And I got a lot of gaming in too.

I started to find that 3-days were often followed immediately by 5- or 6- days, which were then often followed by 7-, 8- or 9- days. It was rare that I had two 3-days in a row and I don't think I ever had three in a row.

As soon as I realized this my 3-days became even less stressful2. I became confident that the way I felt right now wouldn't last long. If I just concentrated on taking care of myself today and not doing too much damage I would be better equipped to face the world the next day. Or the day after. After a few months I didn't need the log any more.

I still have 3-days. I think everyone does. But recognizing them, and acting accordingly, have worked for me so far.


1. By describing my own experiences I do not mean to trivialize the painful and substantially more complicated forms of mental illness suffered by so many of us. This summer the Center for Addiction and Mental Health (CAMH) ran a public awareness campaign in Toronto to address just how uninformed, dismissive, and hurtful we can be when faced with a friend or relative suffering from this kind of condition. Even though I consider myself not completely ignorant on the subject, some of the billboards, like the one I linked above, gave me pause, because I think I might have actually said these things to friends. If you think you might need help, please talk to a pro.

2. Another example of why I think tracking can be such a powerful tool.

Is Git useful at the beginning of a project?

August 27, 2012

Oooh! Reader mail!

"Upcoming Entrepreneur" writes asking whether Git is relevant for an unreleased, one-man development project.

From my standpoint, once you've got a 1.0 release of your software product, Git makes perfect sense to help you better control hot fixes, feature branches, and major version releases. ... Am I crazy to think that I shouldn't bother with Git until I release a 1.0?

So, just how much value does version control, and especially industrial-strength version control like Git, add to something that you're working on alone and hasn't even hit production yet?

Here's what a distributed version control (DVCS) system, like Git or Mercurial, is good for at this stage of a project:

  1. Letting you back out of a poor design choice. Truthfully, I've only taken advantage of this when I had the foresight to branch before heading off in my ill-fated coding direction.

  2. Helping you learn and practice DVCS before you're in production. Make no mistake, once your project grows to multiple people or gets actual clients, you will need Git or Mercurial or something similar. Learn now while mistakes are cheap to fix. As you've discovered, there is a learning curve, and there is a difference between using your DVCS like a butter-knife and actually wielding it like a double-bladed axe of coding justice.

  3. Integration into your automated testing and deployment infrastructure. I use Git repositories to manage the deployment process of several projects and it's a nice way to do that. There are alternatives of course, but if if you've got the axe already...

Modern editors and IDEs sometimes give you simplified alternatives to DVCS. Xcode has snapshots, AppCode has Local History, and so on. Frankly, I was never interested in these because they're really just safety nets for use when you don't commit often enough. You won't need them once you are using your DVCS well (committing often, branching and merging or abandoning fearlessly, etc.). And like I said, you will need Git or something like it eventually.

If you really hate the Git command-line, by the way, there are alternatives. Mercurial is well regarded and has been called a somewhat saner approach to the whole thing. There are also nice graphical clients (I use SourceTree) but try to force yourself to stay on the command-line for as long as you can... you will learn faster.

Thanks for writing in "Upcoming Entrepreneur" and kicking my butt back into blogging. I took this as an excuse to scratch an itch and put together a simple static blogging engine based on Dropbox ... because it's all the rage.

More questions? You can always reach me on Twitter @genegoykhman.

Tables Anonymous

May 13, 2008

Hi, my name is Gene and I use table layouts. I really want to use CSS for positional layout, I really really do. And every few years I look at the various sites I manage and think to myself, Gene, today is the day you replace all this hacky table garbage with nice, clean, browser-independent CSS.

So I scrap the tables and it feels good, like getting rid of accumulated crud always feels. And I start styling. Now, I am by no means a CSS expert and I look up a lot of stuff online and in books, but I now know enough to get around basic grid-like layouts and have figured out the positional properties more or less. And I'm not really doing anything fancy. So, initial progress tends to be quick and in an hour or two I have a pretty sharp, pure-CSS layout working in my test browser (currently Safari).

Encouraged and emboldened I start testing a couple of other browsers that I'd like to support, like IE6 and 7 and Firefox. I notice a few display discrepancies and here is the TSN turning point. This is the exact point at which my CSS journey becomes a death-spiral into whack-a-mole layout hell. I spend 3, 4, 5 hours madly swapping between test browsers trying to figure out why fixing one breaks another ad infinitum.

First I get creative, trying various tricks of cascading styles and divs so that every browser gets fed the kibble they like best. At this point I'm still clinging to the hope that I don't have to use any browser detection nonsense. And for a while it looks like I'm making progress. But inevitably, every single time, one browser will have an unexplained white space between elements that are supposed to be flush or something will wrap where it's obviously not supposed to wrap. After creativity comes desperation and I start madly trolling the Internet for all kinds of crazy (I'll say it again: crazy) hacks that people use to work around the various browser idiosyncrasies. JavaScript expression syntax, even (OMG I can't believe this exists) conditional JavaScript compilation, and by this point it's about 3:00 AM and I start to ask myself the following question:

How is this horrid, ugly, hack of a CSS layout any more elegant than my original table layout?

Obviously is isn't, so I roll back all my changes and call it a night. Maybe next year things will be different. Maybe by then Microsoft, Apple and the Mozilla foundation will all get together over beers and settle this crap once and for all. And maybe, just maybe, CSS will become as reliable and consistently rendered as my 5+ year old table layout has been. Maybe I'll learn the magic secret of browser-independent CSS and will laugh at the problems I'm facing now. But I doubt it. Say what you will about CSS vs. tables. At least tables work.