Taming a Linux dev environment with Vagrant

Last November I wrote a small rant on this blog about the frustrations that I’ve had with Linux. Specifically, I outlined what my usual solution is if I can’t get something working after about 15 minutes:

I’m tempted just to toss my VM, get the latest Ubuntu ISO and reinstall from a known-good state. But again, you can only do this so many times before it becomes tiresome.

So, enter Vagrant. Vagrant takes this annoying, manual process that I’d resigned myself to doing from time to time and provides a way to automate it (and, in doing so, mostly replaces the need to). Now, instead of messing around with package managers and permissions, I just specify how I want the server configured in a Vagrantfile and Vagrant goes and creates it for me. And if something gets messed up for whatever reason, the process of blowing the VM away and starting over is fast and painless:

$ vagrant destroy
$ vagrant up

And you’re back in business.

Of course, automated installation of packages is all well and good, but the real power of Vagrant comes as part of a development workflow. When Vagrant starts up the VM, it mounts the directory with the Vagrantfile onto the /vagrant path on your virtual machine, allowing you to make changes to your project files locally with a native editor and have them immediately available on the VM. Gone are the days where you’d have to fire up an editor on the VM or have to constantly copy over the project files - it all just works now.

Having a single point on the VM where everything’s stored also makes it possible to specify things like VirtualHost configurations for Apache. So, when the VM boots, in addition to loading all the required packages, it can also configure the installed servers with the necessary parameters for your project. The scope of this sort of configuration is outside that of the Vagrantfile, but Vagrant has built-in support for Chef and Puppet that you can use to do the job.

Finally, if you commit the Vagrantfile (and whatever associated Chef or Puppet files you might have) to your version control system, you can share that development environment with all the members of your team. If you need to add or upgrade a package, just commit the change, have all members of the team pull and vagrant reload and boom - everyone’s development environment now contains that new change. And in the future when you want to pull up the code from the past, you’ll not only be able to see the code but instantly boot up the development environment as it existed and run it.

The Vagrant team has put together a great Getting Started walkthrough to give you an idea of the power and flexibility Vagrant provides. Personally, I now find Linux a lot more manageable now that I don’t have to worry about stuff getting messed up on my development VMs.


I hate "you should follow me on Twitter"

Three years ago Dustin Curtis blogged about the conversion rates for different ways he tested of inviting his readers to follow him on Twitter. The phrasing that he found with the highest conversion rate, “you should follow me on Twitter here”, where “here” is a link to his Twitter profile, has since been widely adopted by lots of bloggers; a search for the phrase on Google yields over 700,000 results.

However, the phrase is a complete turn-off for me. I really dislike being told what I “should” do, especially when it’s clearly self-serving on the part of the person that is saying it. If I follow you on Twitter, it’s because I think that you have interesting things to say that I might want to read; it will never be because you told me I “should” do it. Actually, telling me I “should” follow you on Twitter is pretty much a guarantee that I won’t.

I suspect one of the reasons for the high conversion rate in Dustin’s test in 2009 was its novelty. It was new, assertive, and I believe it was always found below one of his well-written and skillfully designed blog posts. Once he posted his findings people soon began to copy it, believing that he had proven that the phrasing would definitely get them more followers. Some people even go so far as to put it in their comment on someone else’s blog. But now that the phrase is in wide circulation, the novelty has worn off and the assertiveness has turned into abrasiveness. Being told by one person that you should follow them on Twitter gets your attention, but when lots of people tell you that it becomes extremely annoying.

As for me, you’ll never see me beg for Twitter followers. If you like what I say and want to follow me, great. If not, that’s fine too. But nobody, least of all me, is in any position to tell you who you “should” follow.

p.s. I know I didn’t provide any actual examples of this phenomenon, but I didn’t want to call anyone out explicitly except the comment that “broke the camel’s back” and provided the impetus for this post.


I'm moving to the Boston area

In September I will turn 25 years old, thus marking the halfway point in my 20s. This fact is bit of a pain point for me, because it shows how fast time passes and makes me think how poorly I’ve made good use of it. I’ve stagnated, personally and professionally, for years, and have little to show for it. With that in mind, my New Years’ resolution this year was to find a professional job in the software development field before my birthday. To that end, I’m happy to report I succeeded: I found a great new job in the Boston area and will be starting in just a few days.

The story of how I got the job, though, requires stepping back a few years to the fall of 2009 when I attended the Stack Overflow DevDays conference in Boston. The conference was interesting (though the chairs were uncomfortable!) and I got the chance to meet some people I had interacted with on Stack Overflow for the past year, as well as meet some new people from the area. One of the people I met and talked with worked for an area company and was hiring new people. I was interested in the idea of getting a job in the software industry, but at the time I wasn’t immediately prepared to move to the Boston area. We ended up following each other on Twitter, but nothing further really came from it.

That is, until about three weeks ago. He posted a message on Twitter saying that he had hired someone, and was looking to hire an additional person for his team. I had been looking for jobs for the previous month or so and even had just had an interview that didn’t work out, so I the tweet couldn’t have come at a better time. I sent him my Stack Overflow CV (something that, given that we met at a Stack Overflow conference, I thankfully didn’t have to explain what it was) and the next day we had a phone interview. The following week I had an on-site interview and was offered a job, which I accepted, on the following day.

Since that time I’ve been involved in the surprisingly complicated details of finding a place to live, as well as tying up loose ends here in Maine. My parents have been extremely supportive thorough this whole process (I think they were just relieved I finally got a good job!). This past Thursday and Friday my father and I looked at the listings for dozens of apartments, called 20-30 of them and visited 6, ranging from a $999 studio to an $1899 one-bedroom place, with a median of around $1400-$1600. There was one that clearly stood out to me as a very desirable place to live, and even though it was pretty expensive I think I made the right decision when I applied for it. I’ll be moving in on May 19th, and my parents are coming down on Memorial Day weekend to help me move some of my larger stuff from my current apartment and to go shopping to help furnish the space with what I need.

I am incredibly grateful to my new employer for taking a chance on me; providing someone with no professional work history and no degree with a very generous offer of employment. I will do everything I can to continually exceed all the expectations they have for me. I’m also grateful for all the help my family has provided in getting me situated in this new job, and I’m really looking forward to starting!

P.S. – If you, the reader, are in the Boston area, and you want to meet up, feel free to send me an email. I’m hoping to meet new people, and if you’re reading my blog then I like you already.


A clever Ruby equality trick

Consider the following Ruby class:

class Site
  def initialize(domain)
    @domain = domain

A simple class, Site, that is initialized with a value, domain, that is then stored as an instance variable. Suppose we now want to add equality testing. Specifically, we want to establish that two Sites with the same domain are equal. In a language like Java, in the class definition we have access to all the private instance variables, so the solution would look something like:

public boolean equals(Site other)
    return domain.equals(other.domain);

However, in Ruby, instance methods do not have such access. Private data remains private even among other instances, so the following would not work:

def ==(other)
  @domain == other.domain

So how should we go about solving this problem? One approach would be to add domain as a reader on Site:

attr_reader :domain

This would add the necessary method to Site to enable the == method we wrote earlier to work. However, the downside to this is that it makes the private variable public. Let’s assume for this example that we want to keep the domain variable private for some reason. What other alternatives are there?

One solution would be to provide a method that takes the domain as an input and compare that with the locally stored domain:

def domain_equal(domain)
  @domain == domain

Our == method can then be constructed using this method:

def ==(other)

This is better - the value of the domain is no longer directly available, and although passing an object into == that responds to domain_equal would still expose it, this level of protection is sufficient for our purposes.

However, we can still get a bit more clever. Instead of having two methods, we could combine the functionality of domain_equal into == by testing for the class of other. If it’s the same class as domain, we’ve passed in a domain instead of another Site object, so we perform the operation in domain_equal. Otherwise, call the operation as if it were domain_equal:

def ==(other)
  if @domain.class == other.class
    @domain == other

Not bad! Note that in Ruby, other.==(@domain) can be rewritten as other == @domain. Also note that because @domain.class and other.class are equal, and because equality is commutative1 (i.e. a == b is the same as b == a) we can swap the order of @domain and other:

def ==(other)
  if @domain.class == other.class
    other == @domain
    other == @domain

Now notice that the bodies of both the if and the else are identical. Therefore, we can remove the test and write == like so:

def ==(other)
  other == @domain

Pretty amazing!

This method is deceptively simple - let’s step through how it works. I’m going to use the notation of X.domain to indicate the private variable domain on X:

a ="")
b ="")

a == b
 ↳ b == a.domain
    ↳ a.domain == b.domain

When a == b is called, this in turn calls b == a.domain, which in turn calls a.domain == b.domain and performs the desired equality comparison. However, while this trick is clever, it probably should be avoided in actual code because how the method operates may not be obvious to the casual reader.

1 Actually, this whole trick works because equality in Ruby is not commutative - it’s just an instance method on the left operand. However, we can make the switch from other.==(@domain) to other == @domain because the if tests to make sure that the classes of both @domain and other are equal. Since they are, and since we are assuming that equality on instances of those classes is commutative, we can make this swap. Interestingly, even if == is not commutative on the domain class, the operation still preserves the order, meaning that a == b if a.domain == b.domain and b == a if b.domain == a.domain.


Sparrow for iPhone review

This morning I wrote and published a review of the new Sparrow for iPhone for the Ask Different Blog.

Conclusion: once they sort out the push notifications, I’m there.