The Well-Bred Grapefruit

Musings on Software Development

On Higher Education

I’m writing this post in reference to a tweet from Chris Strom:

This is a pretty common mindset these days. As someone who works at Treehouse, I obviously either agree that college is a horribly inefficient way to prepare yourself to enter the workforce, or… well… I need to find a new job. :) Treehouse bases its value on the idea that you can gain all the skills you need to get a job in the tech sector - not by paying thousands of dollars a year and spending four years taking classes, but by paying tens of dollars a month and learning what you want, when you want.

It seems like a no-brainer, right? The “higher education” system is a dying leviathan that refuses to acknowledge its own mortality; much like newspapers, phone books, and the once-burgeoning pager industry.

I think there is a nugget of truth to all of this, but it’s not new and it’s definitely not a product of the internet age. That nugget is:

If your aim is to become proficient in a specific profession, attending college for four years is one of the most inefficient ways to achieve that goal.

This is true for a number of reasons:

  • Colleges are always behind the times on industry standards. This isn’t really the fault of colleges or professors, it’s just how it works. It takes time to learn about new techniques, realize their importance, update curriculums… and that assumes that the professors have the time and energy after fulfilling their other duties to keep a close eye on the industry.
  • You’re spending four years out of the workforce. Since you can’t get up-to-date information on your industry (per the above bullet point), you’ve effectively delayed your real expertise-gathering experience by several years.
  • There’s a lot of stuff you don’t need. None of those pesky graduate requirements apply directly to your field, but you still have to spend weeks (if not months) of your time learning about literature and history and philosophy.

So why do we pay tens of thousands of dollars to go to college? If it’s such an inefficient return on our investment and doesn’t provide us with up-to-date experience we can use to be a better entry-level employee, then why do companies require us to have a degree before we can apply for employment?

College was never intended as a means of preparing ourselves to enter the workforce; it was originally intended as a means of further preparing ourselves to enter humanity. Much like teaching children things they may never find practical in grade school - art, music, algebra, poetry - college was a guided tour to broaden our horizons and allow us to gain a certain communion with the greater history of western science and culture. It was an experience interesting to few and one that fewer could take advantage of. If you were interested in learning a trade, you didn’t go to school - you apprenticed.

What blog post is complete without an XKCD comic?

Over the last fifty+ years that has changed - various programs (including the grossly bloated student loan industry) encouraging attendance in college has shifted the idea of college from being a luxury of those who had the money and the desire to being almost as compulsory as grade school. Job recruiters turned to the possession of a college degree as a quick and easy filter to cut down on the number of applicants they needed to consider, which in turn drove up demand for college education even further and put pressure on colleges to impart “useful” skills to their students. The whole mess very quickly descended to the point where people who wouldn’t have even considered college 60 years ago now see it as a necessary (and horribly expensive) evil.

But in a lot of ways, a college education still retains a lot of its earlier value - it’s not great for training you to fill a certain position, to be sure, but much like those music lessons you took in grade school it’s a fantastic way to expand your mind and expose yourself to new ideas and ways of thinking.

Does that mean that everyone should go to college? Of course not. Intellectual pursuits like that aren’t going to be valuable to everyone, and employers seem to be coming around to the idea that a college degree isn’t always a value-add when it comes to the worth of a potential employee.

That said, I got a lot of value out of my college education. The technical training I got in computer science hasn’t had much of a direct impact on my career, but I wouldn’t be anywhere near the person I am today without the general education I received. College may not have a lot of value for preparing you to enter the workforce - which is why I believe so strongly in Treehouse and others like it - but that doesn’t mean that it’s without value altogether.

OS X Apps, Environment Variables, and You

There are a lot of things I really don’t like about OS X. This isn’t a secret. At the top of my list right now is the weird pseudo-shell OS X uses when it launches native applications. Don’t know what that means? I don’t either, really. I still haven’t figured it out. Here’s what happened, though, and maybe someone will find it useful.

I use ZSH for my default shell. I have a lot of customizations to it, and some very important shell functions that get instantiated (especially RVM, which I use to manage the various versions of Ruby I have installed for different projects). Normally, my $PATH variable looks like this:

1
/Users/duwanis/.rvm/gems/ruby-1.9.3-p0/bin:/Users/duwanis/.rvm/gems/ruby-1.9.3-p0@global/bin:/Users/duwanis/.rvm/rubies/ruby-1.9.3-p0/bin:/Users/duwanis/.rvm/bin:/Users/duwanis/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin

I wanted to poke around with Sublime Text 2 (I’m a vim guy at heart, but I like to play around with alternatives to expose myself to new ideas). However, I noticed that most of the plugins that interacted with a shell process were failing (I couldn’t run ruby tests, generate ctags… a whole host of issues). With a bit of hackery I was able to determine that my $PATH variable from inside ST2 looked like this:

1
/usr/bin:/bin:/usr/sbin:/sbin

…Well, that’s not right. As far as I’ve been able to determine, OS X starts up applications with a very basic shell environment, regardless of your user settings or shell profiles.

After lots of futile attempts at fixing the problem by trying to figure out where I could configure that basic shell environment, I finally found a workaround in a StackOverflow question. By creating a shell script that wraps the default application executable like so:

1
2
3
4
5
6
7
#!/bin/sh                                                                       
                                                                                
source ~/.profile                                                               

logger "`dirname \"$0\"`/Sublime Text 2"                                        

exec "`dirname \"$0\"`/Sublime Text 2" $@

…and updating the application’s Info.plist file as described in the first answer to the SO question I linked above, ST2 now always starts up with the appropriate environment configuration and child processes have all the information they need in order to execute correctly.

Why this doesn’t happen by default, I’ll never know.

Why Toolsmithing Is Important

This weekend I took a few hours and read through Brian P. Hogan’s book on tmux.

While I did get a lot out of the book, I’m not going to talk about tmux itself. Instead, I’d like to talk a bit about toolsmithing.

It’s generally understood that as software developers, we don’t actually spend a whole lot of time writing code. A significant portion of the time we spend in our code editing environments is actually spent reading and understanding code - there’s a comparatively significant amount of effort involved in getting to the point where we can contribute anything material to the code base. On top of that, most of us actually don’t spend all day in the editor - there are calls/chats with coworkers and bosses, support issues to look through, data the client needs gathered, and all manner of other non-coding tasks that we get sucked into over the course of a normal day.

Often people look at toolsmithing as a means of gaining efficiency - by becoming more familiar with your tools overall and discovering shortcuts, you can shave seconds off of common tasks and end up being more productive in the long run.

This is one of the attitudes conveyed in the tmux book. The reason you should familiarize yourself with tmux is because it will make you faster and save you the excruciating few seconds it takes to reach for your mouse.

But if we don’t spend all that much time, comparatively, using our tools… how much does a few extra seconds actually buy us? Even if we’re generous and assume that we’ve saved ourselves 5 minutes over the course of the day, is 5 minutes of extra productivity really going to do us that much good?

(A common fallacy here is to say “Well, that adds up to 25 minutes per work-week, or about 100 minutes a month, or about 20 hours over the course of a year - that’s like getting two and a half extra days of effort every year!”. If only the world worked like this, though. I can’t take the 5 minutes I saved today and put it into some kind of time-bank where I can redeem it later - I’ll either use it to work on something right now (which has to be simple if it’s going to be done in 5 minutes) or I’ll waste it on leisurely pursuits, like taking an extra little break to walk around the house.)

So why do it, then? If it doesn’t provide us with huge daily wins in our productivity, is there any point in trying to improve our tools?

Obviously I think so, or I wouldn’t have wasted my Saturday doing so. To me, the real answer is about pride (the good kind), and passion, and motivation to a much greater extent than it is about efficiency and productivity.

A carpenter can build great things with tools from Wal-Mart. A chef can cook delicious dishes with pots and pans from IKEA. A writer can pen a brilliant novel using a Bic and a $0.79 college-ruled notebook. But when you look at how the great artists in their field work, you find that they tend towards more expensive tools. Does the soft leather cover on a writer’s notebook enable them to write faster? Does the chef’s copper cookware help her prepare more dishes at once? Does the carpenter’s sleek titanium hammer help him drive more nails?

Great tools are inspirational. When we’re confronted with tools that are interesting we are inspired to work with them, whether that interest comes from their beauty, elegance, simplicity, or specification. This inspiration helps to yield better results from our labor.

So the next time you get a chance to mess around with a new tool or tweak your existing workflow, I would encourage you to get in there and do it. Even if you decide not to change anything, taking the time to appreciate the tools of your trade will push you to become better.

Introducing Nutrasuite

Just a quick note about a little minitest-enhancing library that Alan Johnson and I hacked up today. Nutrasuite is a dirt-simple gem that adds contexts to minitest for you. It might do more in the future, it might not. But for now you can get organization in your tests as easy as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require 'nutrasuite'
class SomeTest < MiniTest::Unit::TestCase
  a "newly instantiated test object" do
    setup do
      some_setup_stuff
    end

    it "tests for stuff" do
      assert true
    end

    that "has some other setup stuff done" do
      setup do
        some_other_setup_stuff
      end

      it "tests for more stuff" do
        assert true
      end
    end

    teardown do
      some_teardown_stuff
    end
  end
end

A few notes:

  • a, an, and that all define contexts. Between those three you should be able to put together grammatically-correct sounding tests.
  • it defines a new test.
  • Setups and teardowns are run for each test. This means that you can safely take advantage of minitest’s natural test randomization.
  • If you care about LOC (I don’t, really, but it kind of speaks to the simplicity) this stuff is set up in 122 lines, and doesn’t monkeypatch anything or pollute the kernel namespace. Hard to get much simpler than that.

So nothing too special, but we found a need for it and put it together (in fact, if you’re curious, it’s already in use over on Timberline, which I haven’t announced yet). And by “we put it together” I mean Alan figured out how it was going to work and I filled in the code and came up with a quirky name (p.s. Nutrasweet - please don’t sue me. You have better things to do).

Introducing Redis::ExpiringSet

Yesterday I released a new gem: Redis::ExpiringSet. It creates a new datatype for use with Redis - an Expiring Set.

What’s an Expiring Set and why should I care?

Expiring Sets behave exactly like normal Sets in Redis, with one exception: each item in the set has an expiration time, and once that expiration time is past the item will be removed from the set. This is particularly useful for keeping track of recent items.

Suppose, to create a contrived example, you want to keep statistics on the number and type of emails you’ve sent from your site in the last 24 hours. Suppose that this data has a string representation. Every time you send an email you can just put that data into an expiring set along with an expiration time:

1
2
3
4
5
6
7
require 'redis-expiring-set'

# assume @redis is your redis database connection,
# and @email is your email job
expset = Redis::ExpiringSet.new(@redis)

expset.xadd("email_data", @email.to_s, Time.now + 1.day)

Now if you want to access your data, you can just call xmembers, and you’ll be guaranteed to only get info from the past 24 hours:

1
expset.xmembers("email_data")

There’s also a “monkeypatch” file you can include to make all of this available directly off of your Redis objects:

1
2
3
4
5
6
# again, assume @redis is your redis database connection
require 'redis-expiring-set/monkeypatch'

@redis.xadd("email_data", @email.to_s, Time.now + 1.day)

@redis.xmembers("email_data")

This isn’t the default behavior because I didn’t want to force you to monkeypatch the Redis library if you didn’t want to.

More details and documentation are available at the github page.