Effectif DevelopmentNestatag:effectif.com,2009:/(agile web development and consultancy)2015-09-04T00:00:00+00:00Graham Ashtonhttps://effectif.comgraham@effectif.comMicroconf Europe 2015 – thoughts and takeawaystag:effectif.com,2015-09-04:/microconf/europe-2015<p>I've just arrived home from MicroConf Europe, which was the best
conference I've ever been to.</p>
<p>The things I learned and ideas I had will definitely have an impact on
my working life, as will the new relationships forged with the people I
met.</p>
<p>At the start of the start of the first day Rob Walling challenged us all
to come up with 3 takeaways that would have an impact our businesses.</p>
<p>These are mine.</p>
<h2>Takeaway 1: Join a mastermind group</h2>
<p>A mastermind group involves 3 or 4 small business owners meeting
regularly to discuss each other's businesses. Over time you get to know
each other's products well, and can offer each other objective advice.</p>
<p>I've experienced how difficult it can be to think clearly about my own
strategy. I've also surprised myself by giving some startlingly good
advice to some friends, so I can really see the value in this.</p>
<p>I've joined a group with somebody I met at Microconf, and have signed up
to mastermindjam.com (a matching service for micropreneurs).</p>
<h2>Takeaway 2: Setup a productised service</h2>
<p>I've been building <a href="https://www.agileplannerapp.com">Agile Planner</a> (my
project management app for iterative software teams) for over three
years now. It doesn't pay the rent yet (I'm working on it), so I’ve been
taking a couple of freelance jobs every year.</p>
<p>This obviously takes time away from working on Planner, especially as
freelancing requires complete focus on a client project.</p>
<p>Productised consulting would enable me to provide lots value to multiple
clients, on a recurring basis, without forcing me to stop working on
Planner.</p>
<p>I became interested in trying it back in 2014, and even had a product in
mind. I’d previously decided to focus all my efforts on Planner, but I
think it's time to give it a try.</p>
<h2>Takeaway 3: Relentless execution</h2>
<p>At the end of his talk, Rob Walling dropped in the catchphrase
"relentless execution".</p>
<p>Rob's comment reminded me of a time when I was no stranger to the joys
of shipping feature after feature, in a sustainable manner. It's how I
feel when I'm freelancing, or working for somebody else.</p>
<p>When working on my own business I usually spend a while thinking hard
about what to do, then spend a few days or a week executing the plan.</p>
<p>Doubts about the strategy can easily creep in during the execution
phase, but it’s rarely productive. It’s better to complete the work
quickly, then take stock and assess progress and strategy afterwards.</p>
<p>Saying “relentless execution” ought to keep me on track. It’s working
great so far…</p>
<h2>More on Microconf...</h2>
<p>To read more about the conference, including other people's blog posts
and some notes from the talks, see Christoph Engelhardt's <a href="http://www.it-engelhardt.de/microconf-europe-2015-notes-and-noteworthy/">recap
page</a>.</p>
2015-09-04T00:00:00+00:002015-09-04T00:00:00+00:00Installing a specific version of a homebrew packagetag:effectif.com,2014-08-26:/mac-os-x/installing-specific-version-of-homebrew-formula<p>When developing for the web, I like to make sure that the software I'm using in development is a close match for the code that I'm running on my live servers.</p>
<p>My preferred approach is to develop my code in a virtual machine containing the same operating system and software as my production server environment, but sometimes we don't have much control over the code we run on the server. This is often the case when hosting apps on a PaaS (Platform as a Service) provider such as Heroku.</p>
<p>I develop Agile Planner on a Mac, and install software required by my app (such as PostgreSQL, memcached and Elasticsearch) using the <a href="https://github.com/Homebrew/homebrew">homebrew</a> package manager.</p>
<p>Packages in homebrew are typically updated to provide the latest version of an app, which means that you can find yourself running more recent versions of your software in development, than in production.</p>
<p>It's useful to be able to install a specific version.</p>
<p>It's easy to do with homebrew.</p>
<h2>Installing from a tap</h2>
<p>If a lot of people might need to use an old version of a package (or "formula", in homebrew's terminology), it might have been made available as a tap. Old versions are maintained in the <a href="https://github.com/Homebrew/homebrew-versions">homebrew-versions repository</a>, and show up in the output of <code>homebrew search</code>:</p>
<pre><code>$ brew search elasticsearch
elasticsearch
homebrew/versions/elasticsearch-0.20 homebrew/versions/elasticsearch090 homebrew/versions/elasticsearch11
</code></pre>
<p>The first line of output refers to the default package, while the following line refers to the "tapped" versions that are also available. You can install one of them like this:</p>
<pre><code>$ brew install homebrew/versions/elasticsearch11
</code></pre>
<p>In my case, the version I'm looking for (version 1.2.1) isn't available as a tap, so I need an alternative approach.</p>
<h2>Installing from a specific commit</h2>
<p>The homebrew formulae (that tells the <code>brew</code> command how to build each package) are all stored in a Git repository.</p>
<p>All we need to do is to roll back the formula for the package we want to build to the latest commit that was active for that package.</p>
<p>Up until around October 2014, Homebrew had a <code>brew versions</code> command that would list all the versions of a package, and the corresponding Git commands to roll the formula back.</p>
<p>If your version of homebrew is more recent than October 2014, you'll need to install the <code>boneyard</code> tap in order to make the command available:</p>
<pre><code>$ brew tap homebrew/boneyard
</code></pre>
<p>Then you can run <code>brew versions</code>. Here's the first few lines of output for Elasticsearch:</p>
<pre><code>$ brew versions elasticsearch
Warning: brew-versions is unsupported and will be removed soon.
You should use the homebrew-versions tap instead:
 https://github.com/Homebrew/homebrew-versions

1.3.2 git checkout 55c1ef3 /usr/local/Library/Formula/elasticsearch.rb
1.3.1 git checkout f19e447 /usr/local/Library/Formula/elasticsearch.rb
1.3.0 git checkout afe760c /usr/local/Library/Formula/elasticsearch.rb
1.2.2 git checkout 97e96ed /usr/local/Library/Formula/elasticsearch.rb
1.2.1 git checkout 3bbd4f1 /usr/local/Library/Formula/elasticsearch.rb
1.2.0 git checkout 53d3a63 /usr/local/Library/Formula/elasticsearch.rb
</code></pre>
<p>There's more information on the <code>brew versions</code> command in <a href="http://stackoverflow.com/a/4158763">this StackOverflow answer</a>, so if at some point in the future you find that this blog post seems to be out of date, try that.</p>
<p>So anyway, back to installing Elasticsearch. I need version 1.2.1, so I'll pipe the versions command through grep and then run the Git command:</p>
<pre><code>$ brew versions elasticsearch | grep 1.2.1
 1.2.1 git checkout 3bbd4f1 /usr/local/Library/Formula/elasticsearch.rb
$ cd /usr/local/Library
$ git checkout 3bbd4f1 /usr/local/Library/Formula/elasticsearch.rb
$ brew install elasticsearch
</code></pre>
<p>If you've already got a version of the package you're building installed, you might need to unlink it before installing it:</p>
<pre><code>$ brew unlink elasticsearch
$ brew install elasticsearch
</code></pre>
2014-08-26T10:25:00+00:002014-08-26T10:25:00+00:00Update your entire project to Ruby 1.9 hash syntaxtag:effectif.com,2013-10-29:/ruby/update-your-project-for-ruby-19-hash-syntax<p>In version 1.9 Ruby introduced new syntax for hash literals whose keys are symbols. Hashes use the "hash rocket" operator to separate the key and the value:</p>
<pre><code>my_hash = { :key => 'value' }
</code></pre>
<p>In Ruby 1.9 that syntax is still valid, but <em>when the key is a symbol</em> we can also write it like this:</p>
<pre><code>my_hash = { key: 'value' }
</code></pre>
<p>If you no longer need to support Ruby 1.8 it's worth updating your code. The new syntax is easier to read and quicker to type. Updating an entire project by hand would be painful, but with the Unix command line and a quick regular expression we can make the computer do the hard work.</p>
<p>So our task is to write a small program that will find all occurrences of <code>:key =></code> and convert them to <code>key:</code>, in all the Ruby files in our project.</p>
<p>Easy, right?</p>
<h2>Finding all the Ruby files</h2>
<p>We're on Unix (well I am, at least), so we don't actually need to write any code. We can use the <code>find</code> command instead, from the top level of our project:</p>
<pre><code>$ find . -name \*.rb
</code></pre>
<p>If we can cook up a command that can replace all the old-style hash syntax in a single file, we can run it against all the Ruby files with the <code>-exec</code> option to <code>find</code>.</p>
<pre><code>$ find . -name \*.rb -exec our_command {} \;
</code></pre>
<p>The <code>{}</code> characters will be substituted for the name of the filename, while <code>\;</code> is used to tell <code>find</code> that we've finished specifying the command.</p>
<h2>Writing a command to update a single file</h2>
<p>There are lots of different ways to approach this, but regular expressions seem like a good fit. We could use sed, a classic Unix utility with decent regex support. Or we could use a one line Ruby command, with it's very powerful regular expression engine and syntax.</p>
<p>I tend to use Perl for tasks like this, which falls somewhere inbetween sed's concise nature and Ruby's power.</p>
<p>Let's build a Perl command to do the job. If we run <code>perl</code> with the <code>-p</code> and <code>-e</code> switches it'll execute a snippet of Perl code for us, reading data from STDIN and printing out the results. Due to the way <code>-p</code> works, we only need to specify a regex substitution command, and Perl will run it on each line of input that we give it.</p>
<p>To get us started, let's replace any text that matches a colon, followed by one or more alphanumeric characters and a hash rocket, with the alphanumeric string followed by a colon:</p>
<pre><code>$ echo "{ :foo => 'bar' }" | perl -p -e 's/:(\w+)\s*=>/\1:/'
{ foo: 'bar' }
</code></pre>
<p>So far so good, but it's a little brittle. It'll break if it encounters a hash key that's a namespaced class, like <code>MyModule::Class</code>.</p>
<pre><code>$ echo "MyModule::MyClass =>" | perl -p -e 's/:(\w+)\s*=>/\1:/'
MyModule:MyClass:
</code></pre>
<p>We can fix that by requiring that the character immediately before the colon can't be another colon, making sure that we insert this preceding character back into the output (that's what the round brackets around <code>[^:]</code> are for):</p>
<pre><code>$ echo "MyModule::MyClass =>" | perl -p -e 's/([^:]):(\w+)\s*=>/\1\2:/'
MyModule::MyClass =>
</code></pre>
<p>Let's just check it still works on hashes...</p>
<pre><code>$ echo "{ :foo => 'bar' }" | perl -p -e 's/([^:]):(\w+)\s*=>/\1\2:/'
{ foo: 'bar' }
</code></pre>
<p>Good stuff.</p>
<h2>The final solution</h2>
<p>Now all we need to do is to run it on every file in our project, by running <code>perl</code> inside the <code>find</code> command:</p>
<pre><code>$ find . -name \*.rb -exec perl -p -i -e 's/([^:]):(\w+)\s*=>/\1\2:/g' {} \;
</code></pre>
<p>The eagle-eyed reader will have noticed that I've slipped the <code>-i</code> switch into the Perl command. It tells Perl to modify files "in place".</p>
<p>Before you run it, just <strong>make sure that you've checked your code in!</strong> Then you can review the diff, run your tests, and throw all the changes away if you find that the regex needs further improvements on your code base (let's face it, I'm not likely to have thought of everything).</p>
2013-10-29T08:30:00+00:002013-10-29T08:30:00+00:00Installing nokogiri with rbenv on Maverickstag:effectif.com,2013-10-24:/ruby/installing-nokogiri-on-mavericks<p>As is often the case after a Mac OS X upgrade, installing Ruby gems that depend on compiled C code can require a bit of fiddling about. I've just upgraded my laptop to Mavericks, and lo and behold, the nokogiri Ruby gem won't install. I should have had déjà vu here, as I went through a similar process <a href="https://effectif.com/articles/installing-nokogiri-on-leopard">installing nokogiri on Leopard</a>!</p>
<p>On the off chance that the solution that worked for me might also work for you, I made a few notes.</p>
<p>tl;dr – Apple's command line tools went awol during the upgrade to Mavericks (even though I have XCode installed), and I had to jump through a couple of hoops to re-install them, then run a binary as root to force Apple to ask me to accept the license agreement.</p>
<h2>The error</h2>
<p>When running <code>gem install nokogiri</code> I got this error:</p>
<pre><code>$ gem install nokogiri
Building native extensions. This could take a while...
ERROR: Error installing nokogiri:
 ERROR: Failed to build gem native extension.

 /Users/graham/.rbenv/versions/1.9.3-p194/bin/ruby extconf.rb
Extracting libxml2-2.8.0.tar.gz into tmp//ports/libxml2/2.8.0... OK
Running 'configure' for libxml2 2.8.0... ERROR, review 'tmp//ports/libxml2/2.8.0/configure.log' to see what happened
.
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.
</code></pre>
<h2>My Ruby setup</h2>
<p>Firstly, I should tell you a bit about where I was starting from.</p>
<ul>
<li>I use <code>rbenv</code> to install different versions of Ruby. The notes in this post were collated while getting nokogiri to build with Ruby 1.9.3p194, but I would expect my solution to work just as well if you're compiling gems for any version of 1.9.3 or 2.0.0.</li>
<li>When this machine was still running Mountain Lion, homebrew and XCode were both already installed. The "App Store" app offered me an XCode upgrade, and I took it. I therefore thought I had the command line tools (i.e. a C compiler, <code>make</code>, etc) available. In reality they weren't there, but we'll get to that in a minute.</li>
</ul>
<h2>How I fixed it</h2>
<p>The top tip in the error message (see above) was that the output had been written to <code>tmp/ports/libxml2/2.8.0/configure.log</code>. I had a look inside, and lo and behold, it turned out that I didn't have a working C compiler.</p>
<pre><code>$ cat ~/rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/nokogiri-1.6.0/ext/nokogiri/tmp/ports/libxml2/2.8.0/configure.log
checking build system type... i386-apple-darwin13.0.0
checking host system type... i386-apple-darwin13.0.0
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... no
checking for mawk... no
checking for nawk... no
checking for awk... awk
checking whether make sets $(MAKE)... no
checking for gcc... gcc
checking whether the C compiler works... no
configure: error: in
`/Users/graham/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/nokogiri-1.6.0/ext/nokogiri/tmp/ports/libxml2/2.8.0/libxml2-2.8.0':
configure: error: C compiler cannot create executables
See `config.log' for more details
</code></pre>
<p>I suspected I didn't actually have XCode at this point. I wish I'd checked, as I'd discovered that it was there, and I'd have launched it to check that it was in fact version 5. See my footnote at the bottom of this post to find out why; if your problem resembles mine at this point I recommend launching XCode and checking that it doesn't also report that bits are missing!</p>
<p>The standard advice online for getting the XCode command line tools installed on Mavericks is to run <code>xcode-select --install</code>. So I did that, and a small dialog popped up and then proceeded to download the command line tools for me. I rather thought I was set at this point. But no...</p>
<p>If, after re-running <code>gem install ...</code> you find that the gem still won't install, and that the <code>configure.log</code> file still complains that you don't have any command line tools, try cd-ing into the directory of the code that won't build and running <code>make</code>.</p>
<pre><code>$ cd ~/rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/nokogiri-1.6.0/ext/nokogiri/tmp/ports/libxml2/2.8.0/
$ cd libxml2-2.8.0/
$ make clean


Agreeing to the Xcode/iOS license requires admin privileges, please
re-run as root via sudo.
</code></pre>
<p>It appears as though <code>xcode-select</code> could have asked me to accept a license agreement. Instead, you're prompted the first time you try and run the command line binary, and the Ruby build scripts had gobbled up the error message.</p>
<p>I tried again with <code>sudo</code>.</p>
<pre><code>$ sudo make


You have not agreed to the Xcode license agreements. You must agree to
both license agreements below in order to use Xcode.

Hit the Enter key to view the license agreements at
'/Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf'

IMPORTANT: BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE
FOLLOWING APPLE TERMS:

A. MAC SDK AND XCODE AGREEMENT
B. iOS SDK AGREEMENT

[snip]
</code></pre>
<p>Result. Once I'd accepted that licence agreement I found that <code>gem install
nokogiri</code> ran without a hitch.</p>
<h2>Footnote about the XCode 5 upgrade</h2>
<p>Note that I didn't run XCode 5 inbetween upgrading to it (in the App Store app) and trying to build any Ruby gems. When I did finally run it (after I'd successfully got <code>gcc</code> installed), I was presented with a dialog box asking if I'd like to "install additional required components?"</p>
<p><img src="/attachments/ruby/xcode-5-required-components.png" class="screenshot" alt="XCode 5: Installing additional required components"></p>
<p>It's as if the upgrade to XCode 5 wasn't finished; maybe installing these components before I started would have made <code>gcc</code> and friends available to me from the outset? Who knows...</p>
<p><em>UPDATE:</em> Since writing this post I've upgraded to Mavericks on a second computer, ran into the same problem, and launched XCode. After it had installed its missing components I could run <code>gcc</code> without being prompted to accept a license agreement, and gem compilation just worked. Also take a look at the comments below, where others have been explaining what's worked for them.</p>
2013-10-24T00:00:00+00:002013-10-24T00:00:00+00:00Silky Markdown editing on Mactag:effectif.com,2013-04-15:/mac-os-x/easier-markdown-editing-on-mac<p>If you write in Markdown on a Mac you'll no doubt have dabbled with TextMate at some point. If you did, perhaps you discovered some of TextMate's marvellous Markdown mode commands, such as "Google for the highlighted text, and convert it to a link to the first search result" (if memory serves, it was Cmd-Alt-Ctrl-L)?</p>
<p>Editor support like that makes writing in Markdown very productive, but these days I tend to pen my blog posts in simpler editors. Luckily, with <a href="http://brettterpstra.com/projects/markdown-service-tools/">Markdown Service Tools</a> you can now setup similar keybindings that work in any app built on top of Cocoa (which is pretty much all of them).</p>
<p>It's pretty easy to do.</p>
<h2>Step 1 - install Markdown Service Tools</h2>
<p>Grab the <a href="http://brettterpstra.com/projects/markdown-service-tools/#download">zip file</a> and uncompress it into your <code>~/Library/Services</code> folder (you may need to create it).</p>
<h2>Step 2 - setup a keybinding</h2>
<p>Open System Preferences and head to the keyboard shortcuts pane. You should find a bunch of services with names that start with "md" (you may also have to wait a minute or so while your Mac reindexes your services before opening the preferences pain or they won't show up).</p>
<p><img src="https://f.cl.ly/items/0r3r2O2j0t3u2y12260Z/keybindings-for-services.png" alt="Mac Keyboard Shortcuts" /></p>
<p>Setup a key binding, and off you go...</p>
2013-04-15T00:00:00+00:002013-04-15T00:00:00+00:00Stay curioustag:effectif.com,2013-03-05:/articles/stay-curious<p>When I was 10 my Dad told me something very disturbing:</p>
<blockquote><p>Kids learn faster than adults because adults lose their childhood curiosity.</p></blockquote>
<p>The news that I was going to slow down didn't go down too well. I think it was a bigger blow than Santa, which was clearly cobblers from the outset.</p>
<p>And so at the age of 10, I resolved to stay curious. Forever.</p>
<p>Last week Brian Cox made it abundantly clear that recently, I haven't been doing so well. Before we get onto that, I want to give you a feel for exactly what I mean by "curious".</p>
<p>I've always been a "button pusher". If something has a button on it, you can bet I'll push it, just to see what happens. Who needs user manuals when you can reverse engineer a user interface by trying to get into the mind of the designer? What design problems would they have been trying to solve? What possible solutions did they have available to solve them?</p>
<p>Once you've got a feel for how a product's designer was thinking, you'll probably find you can use the product without too much trouble.</p>
<p>This approach was largely responsible for me becoming good with computers, and I've built a rather enjoyable career off the back of it.</p>
<p>As a self taught developer I spent the early years of my career thinking that studying Physics (instead of Computer Science) had counted against me. I felt like I was playing catch up.</p>
<p>What I didn't realise at the time was that my curiosity was more than making up for it. I invested hours of free time each week learning Unix, programming, databases, UI design - whatever I needed to solve the problems facing me on my current project.</p>
<p>Everything I know about computers, networking, and software (after 16 years, it's a lot) is a result of my own insatiable curiosity, and a desire to make "stuff".</p>
<p>At the rate at which our development technologies are evolving, I'll need to</p>
<p>Last week a couple of scientists made me realise that I've slipped.</p>
<p>I was at a screening of an episode from Brian Cox's latest series, <a href="https://www.bbc.co.uk/programmes/p012qczg">Wonders of Life</a>. After the screening Brian and Matthew Cobb (another scientist) took questions from the audience.</p>
<p>Brian told an anecdote about Gary Kasparov (the famous chess player) who'd explained the importance of persistence in the face of a challenge. As Brian put it:</p>
<blockquote><p>Getting stuck is a thing … it's very much part of the fun. The people who stop don't become scientists; those who carry on become scientists [or chess players].</p></blockquote>
<p>I think this is applicable to all walks of life.</p>
<p>Matthew explained that while knowing things is cool ("you get to show off at parties"), the important thing about science isn't learning about what we already know. The important thing is what's still to be discovered.</p>
<p>And here's the thing - science is all about the unknown, the things that humankind is yet to discover.</p>
<p>Solving unknowns in science is hard.</p>
<p>Cracking unknowns in software development is typically much, much easier. And yet we allow ourselves to get stuck on tractable problems that could be solved simply by <strong>spending a few hours reading some code</strong>.</p>
<p>It might not be nice code, or we might not know the language in which it's written, but those are just excuses. <strong>If I throw in the towel on a problem it's because I've become lazy. Because I've lost my curiosity.</strong></p>
<p>Getting to grips with the unknown can take a while, but when viewed over the long term the pay off is well worth it. My 16 years in software have taught me that.</p>
2013-03-05T12:00:00+00:002013-03-05T12:00:00+00:00Finding perpetual inspirationtag:effectif.com,2013-02-28:/productivity/maintaining-your-inspiration<p>I've been reading <a href="http://executebook.com">Execute</a> this week, a book about how we can act on inspiration to create great things, fast. It tells the story of how Drew Wilson conceived, <strong>built</strong> and shipped a competitor to <strong>PayPal in a week</strong> (as if to make the point, Josh Long and Drew Wilson wrote the book itself in a week). One of the ideas that has resonated most strongly with me is the "inspiration battery".</p>
<p>It's all well and good getting pumped up and working hard when the inspiration from your latest great idea is fresh, but inspiration (and therefore motivation) comes and goes. We'd all get more done if we were <strong>perpetually inspired</strong> to do great things, but it doesn't tend to work like that.</p>
<p>The energy we get from feeling inspired can wane, but we can get it back (recharging the battery) by working on something that excites us. As Josh wrote:</p>
<blockquote><p>Everyone of us has an element of what we do that we enjoy more than all of the others. For Drew, it's design. He loves it. [snip] Design recharges Drew.</p></blockquote>
<p>It's useful to acknowledge that we shouldn't always work on the next most important thing. Maintaining our energy (through enjoyment and satisfaction) is often a more important factor for the progress we can achieve on a project.</p>
<p>Once you know which tasks recharge your batteries you can allow yourself to work on these things whenever you feel your motivation starting to wane.</p>
<p>I've sometimes struggled to justify to others quite why I've prioritised a particular feature, knowing full well that I've chosen to work on something that will keep me excited. As a recent example, <a href="https://www.agileplannerapp.com/tour">Agile Planner</a> had a fully fledged <a href="https://www.agileplannerapp.com/developers/api">REST API</a> before I'd enabled sign ups to the free trial.</p>
<p>I built the API earlier than necessary because I knew that I'd get fired up about the impact that it would have on the code, and would give me more opportunity to benefit from the <a href="https://www.agileplannerapp.com/blog/building-agile-planner/refactoring-with-hexagonal-rails">hexagonal architecture</a> that is evolving in Agile Planner.</p>
2013-02-28T12:00:00+00:002013-02-28T12:00:00+00:00Finding bugs with git bisecttag:effectif.com,2012-11-21:/git/simple-approach-to-finding-bugs-with-git-bisect<p>When a bug has crept in to your code that you're having trouble fixing, it
helps to know when it was introduced. If you can prove which code caused the
bug you can normally work out why. The <code>git bisect</code> command is here to help you
track it down...</p>
<p>It works like this. You tell git three things:</p>
<ol>
<li>The SHA of the <strong>most recent good commit</strong>.</li>
<li>The SHA of <strong>a bad commit</strong> that you know has the bug.</li>
<li>A command that git can run that will exit with a non-zero exit status when
the bug is present (in other words, you <strong>tell it how to run your tests</strong>).</li>
</ol>
<h2>Setting up the bisect</h2>
<p>Early today I managed to introduce a bug somewhere in my topic branch, while
doing some copy writing and tidying up my sales pages. I hadn't edited any real
code, but my tests were failing anyway. I had no idea why.</p>
<p>I quickly ran the tests on the <code>master</code> branch to prove that it wasn't a
problem with my environment. They passed – the problem was definitely in one of
the commits on my topic branch.</p>
<p>I knew that my <strong>last good commit</strong> was <code>master</code>. The <strong>earliest bad commit</strong>
that I'm aware of is the head of my topic branch.</p>
<p>This is how you pass that information to git:</p>
<pre><code>$ git bisect start [<bad> [<good>]]
</code></pre>
<p>So in my case, I typed:</p>
<pre><code>$ git bisect topic-branch master
</code></pre>
<h2>Testing all the commits</h2>
<p>To kick things off you give git the name of a command to run. It needs to exit
with an exit status of 0 if the commit is good, and non-zero if it's a bad one.</p>
<pre><code>$ git bisect run <command>
</code></pre>
<p>My command was a simple one; I just ran some of my tests.</p>
<pre><code>$ git bisect run ruby test/functional/activities_controller_test.rb
</code></pre>
<p>My computer churned away for a bit, continually re-running the tests on
different commits. Rather than just running the tests against each commit on
the branch, it's smart enough to optimise the full run by selecting which
commit to test next with a binary chop.</p>
<p>When it finished I checked the output of <code>git bisect log</code> to see the results.
Look towards the bottom of the output and find the last commit marked as bad.
In my case, it looked like this:</p>
<pre><code># bad: [61a0e9249a2ef2b1a1cb31562782bf2de05c782c] Added pricing page with the Early Adopter plan.
</code></pre>
<p>Adding a new page seemed pretty innocuous, but finding the problem was pretty
straightforward when I looked at the diff. An innocent change to the routes
file had uncovered a badly written (unrelated) test that started failing as a
side effect.</p>
<h2>Cleaning up</h2>
<p>When you know where the problem came from, a quick reset will get you back
to the head of your branch:</p>
<pre><code>$ git bisect reset
</code></pre>
2012-11-21T21:00:00+00:002012-11-21T21:00:00+00:00Testing IE on development sitestag:effectif.com,2012-11-13:/automation/testing-ie-on-development-sites<p>When was the last time you finished some web development work (on your shiny, modern operating system) only to find that it didn't work in IE8. Or in IE9. Or a reasonably recent version of Opera. If you're developing web sites profesionally, you need to test them in multiple browsers running on multiple operating systems. I used to maintain virtual machines running Windows that could connect to my local dev server. These days I use BrowserStack.</p>
<p><a href="http://www.browserstack.com">BrowserStack</a> gives you access to a long list of different web browsers, running on a wide selection of operating systems. It works like this:</p>
<ul>
<li>A virtual machine running the browser of your choice is fired up for you on demand.</li>
<li>You use the remote browser to connect to your site, satisfy yourself
that it works</li>
<li>You tell BrowserStack to load the next browser.</li>
</ul>
<p>Here's a screenshot of the UI, showing which browsers are currently available for testing on Windows XP:</p>
<p><img class="screenshot" src="/attachments/browser-stack-browsers.png"></p>
<p>Now, because the virtual machine is running on BrowserStack's servers, the browser you're testing won't be able to access your local development server. To get around this, BrowserStack supports tunnelling. If you enable Java in your browser and (on Mac at least) configure the right security settings in your system's Java config, it works rather well.</p>
<h2>Setup a tunnel from the command line</h2>
<p>I'd rather not meddle with a browser plugin. Luckily BrowserStack has given us a rather nifty alternative, and we can setup a tunnel via the command line. Like this:</p>
<pre><code>$ java -jar BrowserStackTunnel.jar <key> <host>,<port>,<ssl-flag>
</code></pre>
<p>The <code>BrowserStackTunnel.jar</code> file can be <a href="http://www.browserstack.com/BrowserStackTunnel.jar">downloaded here</a>.</p>
<p>The only problem is, I'll never remember that incantation, and most of the time the settings I want to use are the same.</p>
<p>Time for a little automation. I wrote a script that let's me setup a tunnel to a local Rails app like this:</p>
<pre><code>$ browser-stack-tunnel
</code></pre>
<p>I'm usually testing a Rails app, that runs on port 3000 on my localhost. The script takes the port and hostname as optional arguments, so if I wanted to test a Sinatra app on port 9393 I could just type this:</p>
<pre><code>$ browser-stack-tunnel 9393
</code></pre>
<p>The hostname can be specified as a second optional argument. I'm unlikely to need to specify anything other than localhost, but I exposed it in case you do.</p>
<pre><code>$ browser-stack-tunnel [port] [hostname]
</code></pre>
<p>Here's the script:</p>
<pre><code>#!/bin/sh
#
# See http://www.browserstack.com/local-testing to get the jar file.

KEY_FILE="$HOME/.browser-stack.key"

if [ ! -f $KEY_FILE ]; then
 echo "Error: Can't find $KEY_FILE"
 exit 1
fi

KEY="$(cat $KEY_FILE)"
PORT="${1:-3000}"
HOST="${2:-localhost}"

java -jar /usr/local/share/BrowserStackTunnel.jar $KEY $HOST,$PORT,0
</code></pre>
<p>You'll notice the <code>KEY_FILE</code> variable. Every user has a different key, which BrowserStack needs in order to identify you. You can find it on the <a href="http://www.browserstack.com/local-testing">local testing</a> page. Add it to a file called <code>~/.browser-stack.key</code>, like this:</p>
<pre><code>$ echo 'YOURKEYHERE' > ~/.browser-stack.key
</code></pre>
<p>You can also download the script <a href="https://github.com/gma/gma-utils/blob/master/bin/browser-stack-tunnel">from GitHub</a>.</p>
<h2>What's the point?</h2>
<p>Some might argue that the script is so simple that it's barely worth writing. But, lowering the barrier to testing my CSS in different browsers <em>while I'm writing the CSS</em> has sped up my front end development. Layout bugs get less chance to creep in if I'm testing in IE every half hour, and that's definitely worth it!</p>
2012-11-13T17:00:00+00:002012-11-13T17:00:00+00:00Fancy an iPad? Get the Minitag:effectif.com,2012-11-06:/articles/choose-the-ipad-mini<p>Shortly before Apple announced the first iPad the rumour mill was hard at work; we all knew it was coming. I was sat in the pub with my Dad and his friend, who asked me what I thought – would it be a success? To me, there was no doubt it would be a winner. To my Dad's friend, it looked like the <em>biggest flop since the Newton</em>.</p>
<h2>An iPad pays for itself</h2>
<p>I'm not normally an early adopter of new hardware, but the first iPad was different. I'd spent a small fortune on technical books over the years, and in an attempt to reduce the metres of bookshelf required to house them I'd long since switched to buying my technical books in electronic form.</p>
<p>The problem was, I wasn't reading them. Slouching in front of my computer, leaning on my elbows, I'd rarely make it through two pages before giving up to browse the web. The iPad was an obvious solution.</p>
<p>At the time my ebook collection was predominantly in the PDF format, typically produced for A4 or US Letter paper. The iPad seemed like an ideal size for reading a digital version of an A4 sheet; not too big to carry around but big enough that I could read each page without pinching and zooming.</p>
<p>Paying a few hundred pounds to <strong>unlock my digital library</strong> seemed like a bargain. If all I used an iPad for was educating myself with all this content, it would be well worth the investment. No, better than that. It would <strong>make me money</strong> – all I had to do was read.</p>
<h2>Why upgrade?</h2>
<p>That first iPad served me well.</p>
<p>When the second generation came out I couldn't understand why people would want to upgrade. It was thinner. So what? I'd put mine in a chunky leather case that let me prop it up at any angle I chose, and that was far more useful than "thinner". Apparently it was faster, but performance of the iPad 1 just wasn't an issue.</p>
<p>When the iPad 3 came out I took a look at the retina screen, thought "nice" but still didn't feel compelled to upgrade. It would be a waste of money. It wouldn't actually change anything.</p>
<p><em>Last weekend, I bought an iPad Mini.</em></p>
<p>There's only one significant difference: <strong>Size.</strong></p>
<p>For reading technical books, it's far better. Why?</p>
<ol>
<li>Most of <strong>my technical library is now available in ePub format</strong>, so I rarely want to squeeze an entire A4 page onto the screen. Now that text can be resized and flows smoothly between the pages, crisp lettering has become more important.</li>
<li>The Mini has the same number of pixels as the iPad 1, but they're squeezed onto a smaller screen. <strong>Text is crisper and easier to read.</strong> Granted, it's not as crisp as a retina, but it's plenty good enough.</li>
<li><strong>The Mini is a lot lighter.</strong> Holding the iPad 1 for long periods of time required two hands and a good grip.</li>
</ol>
<p>And it's not just books. I've already managed to fly through a big backlog of Instapaper'd articles, learning a lot of useful stuff in the process.</p>
<p>For everything else, it's just a lot more likely to be with me when I need it. Having recently switched to an Android phone I'm finding I don't have my todo list (Things) with me as often as I'd like. At least now I'll have it a bit more often.</p>
<p>The only time I'd prefer a bigger iPad is when watching films, but I tend to do that on a laptop. The iPlayer is better on a 10" screen, but it's perfectly watchable (and the speakers are better) on my Mini.</p>
<h2>Picking a colour</h2>
<p>If you're going to get one but can't choose a colour, the black one is gorgeous. I had a quick look at the white ones on my way out of the store, but was seriously underwhelmed. For some reason the white ones sold out sooner. God knows why – maybe they overstocked on black?</p>
<p>This is obviously personal preference. Ignore me.</p>
<p>Choosing the colour of your smart cover is harder. I thought I'd go for blue or green, but when faced with a wall of colour I surprised myself with the red one. It looks great.</p>
2012-11-06T17:00:00+00:002012-11-06T17:00:00+00:00