My Biggest Career Mistake


My software career path has been a planned affair for many years. It started out as a happy accident with some exposure to a very early internet startup and an opportunity to build out a few web sites. It only took a few months to determine I really liked doing web development and I began my love affair with the computer section of local bookstores, devouring titles in an effort to come up to speed.

As my career progressed I always stepped into the next job to take on new challenges. I went from Perl CGIs to Java, from in-house development to professional services, and from being an individual contributor to managing a development team. The learning curve was exhilarating and enjoyable and when the position ran out of challenges I started looking at new opportunities. Learning new skills is a large component of what keeps me happy on a daily basis.

I didn’t realize it at the time, but I made my biggest career mistake on what seemed a very orthogonal concern about 5 years ago. At the time I was managing a corporate development team, having led them through an Agile adoption process that had been successful at a team level, but generally a failure at the larger corporate level where the management teams simply weren’t interested in changing. Having accomplished much of what I could I started a process of looking for new opportunities again.

My big mistake? Taking on a large home mortgage. In that year we moved from a nice modest home with a very affordable mortgage into a larger remodeled house with two bathrooms. Both my wife and I were advancing in our careers and bought into the idea that while the mortgage was a bit tight to begin with it wouldn’t seem that bad as our salaries grew.

At the time I started my job search I was aware that I had become disillusioned with corporate development. I loved mentoring up teams and bringing them up to speed on testing, refactoring, and CI, but I had begun to doubt that I could win many battles at the CIO level with making a greater impact. I pursued several opportunities at small software firms that sounded really exciting, but I ultimately said no because I wasn’t ready to take even a small drop in salary. I ended up taking another corporate management position at a company that was 7 years into a 200 million dollar death march project. There were some other warning signs going in beyond the death march project, but the compensation package was very respectable and in line with my new mortgage.

Up until this point my criteria for switching jobs had been:

  • The chance to make a real change in the organization
  • The opportunity to learn new skills
  • Working with great people who I could learn from

At the time I convinced myself the positives outweighed the negatives, but again it was really the mortgage that made the difference. The job had aspects of my criteria in it, but I had turned down several others that really fit the criteria completely, but involved taking a salary hit.

It took four years for me to undo the side effects of making the wrong career decision.

6 Months with Vim


College Roomate: So you know vi?
Me: Of course, that would be command shift-Z-Z

This is a conversation I had about twenty years ago. For most of my Unix editing I got by with pico and I found the modal nature of vi downright frustrating. Hence the importance of knowing the command to escape from modal hell.

At my current company vim was the default text editor, I even paired in the interview on vim. Over the years I’ve bounced between text editors and IDEs depending on the languages and environments. One key point though was that when I reached for a text editor it was always one with a GUI front end like BBEdit or TextMate. Despite working in vim most of the day I still default to MarsEdit for writing blog posts.

I jumped into vim with some lingering fear remembering my dislike of its modal nature and the lack of any mouse support. I tried out VimGolf and spent some time trying to memorize basic navigation and selection commands. It came pretty slowly at first. I bogged down my pair quite a bit fumbling around with arrow keys or splitting the screen the wrong way. About two months in I had developed some basic proficiency, but I found myself wondering if RubyMine or TextMate wouldn’t be a better option.

At about the 6 month mark I looked back and realized I was finally comfortable in vim as I found myself defaulting to it for most of my text editing even when I wasn’t working on code. I still have a few cases where I prefer using a visual editor or IDE for tasks like:

  • blogging
  • email
  • exploring large projects
  • larger refactorings

Looking back there were several items that accelerated my vim mastery. One was our switch to sharing a single base .vimrc so when you pairing with anyone you had the same configuration of the editor. It also included several features like macros for commenting, formatting, auto-complete, and running inline RSpec. After setting up that .vimrc I saw how vim could be a more powerful tool.

Another big step was learning to love ‘hjkl’ over the arrow keys. That took about a week or so to break the habit and it was painful, but the speed difference was worth it. The mouse is already gone, so might as well toss the throwback to the arrow keys. (I found the hack here on Stack Overflow.)

A critical change that I arrived at fairly late was remapping my caps lock. Normally you rarely touch caps lock, but it is in a very convent position especially compared to the escape key. I remapped my caps lock to tap it to get an escape and holding it down yields a control which are the two most commonly used modifier keys in vim. That made my fingers very happy.

Finally, the biggest learning expeditor was pairing with a number of developers who had more expertise than myself. Since the team had standardized on vim before I arrived they had all gone far past where I was on the learning curve and were able to quickly demonstrate how to use vim or which keystroke to use as I fumbled along. I greatly appreciated their patience and willingness to let me bang something out that they could have typed in half the time.

I still don’t feel anything like a vim expert, but I do feel comfortable in a modal editor. Never thought I would be typing those words all these years later.

Jenkins: My Personal Bodyguard

I’ve been running Jenkins as my CI solution for years now, but for the first 6 months at my new job I used it in an entirely new way. The typical CI pattern is you setup to run against checkins to your master branch run all the unit tests, and depending on how sophisticated you are integration tests, static analysis, or even performance tests.

In my current shop we had a standard CI build using CC.rb against checkins to our master branch. It ran about 5000+ specs sequentially and if everything’s green master is available for production pushes. That fulfills the standard case for CI just fine, but I quickly found that it a little light for my needs. The issue is we relied on feature branches for rolling out all of our stories and while those stories are being worked there’s no CI job at all. Another pain point is even with parallel specs and a nice 4-8 core processor the full test run takes 5-10 minutes so it doesn’t get run nearly as often as one might like.

I’d let Jenkins be my default choice for CI in Javaland, but I was really open to switching it out for a more Ruby style CI server. I figured the first place to look was our already running CC.rb implementation. I tried out CC.rb long ago and remembered liking it a lot better than the original cruise control, but with years of development on it I figured it had evolved. Turns out CC.rb is a pretty basic solution for CI and it hasn’t had much love over the years. It runs a build showing the console output and a very basic web console. Coming from Jenkins the lack of features and plugins was pretty shocking.

Given the Ruby community’s love for XP practices there must be a better option available. I looked at numerous CI servers for Ruby including CI Joe, Integrity, and Travis. All of them followed the lines of providing a very simple CI server much like CC.rb. Travis CI appeared to be a bit more with its use of a hosted open source solution, but it is completely tied to hosting your project on Github. None of these projects showed the depth of a solution like Jenkins.

So the solution was to run Jenkins as my own personal bodyguard. We were looking at swapping out the CC.rb implementation, but it wasn’t a priority right away. So I dived in and setup Jenkins to run a build on my laptop. Instead of just building master I added whatever git feature branch I was working on and hooked up an audible trigger to play James Brown “I feel good!” for successes and “Houston I think we have a problem” for failures. I expected to use the rake plugin to launch the build, but it turned out it was much easier with using things like rvm and bundler to simply execute a script. My final scripts for the build looked something like the following:

1
2
3
4
5
bash -l -c "rvm use 1.8.7-p330@acme"
bash -l -c "bundle install"
bash -l -c "rake db:migrate"
bash -l -c "rake parallel: prepare"
bash -l -c "rake parallel: spec"

So finishing up a bit of functionality, I’d commit and about 10 minutes later my laptop would exclaim “I feel good”, or occasionally “Houston I think we have a problem” to let me know I missed something. So I had my own personal bodyguard build and I could happily let it run in the background.

This year we replaced CC.rb with Jenkins and dropped feature branches so I’ve retired my laptop Jenkins, but I recommend the practice if you find yourself in a similar spot.

Stubbing Partials with RSpec in Rails View Tests

Working with my pair yesterday we ran into an issue testing a view that pulled in several partials. In the interest of making progress we punted after about half an hour of trying to setup expectations on the partials and just tested the negative cases where we didn’t have to worry about the partials being called. Intellectual curiosity and not wanting to leave the views lightly tested I dived into seeing how we could effectively test that the partials were called as expected.

Say you have a view like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="content">
<div id="page_title" style="padding-bottom: 20px;">
<h2>Books</h2>
</div>
< %= render :partial ='tabs' %>;

< % if @books.empty? -%>;
<em>No Books</em><em>
< % else %>
< %= pagination_links = render :partial => 'shared/pagination', :object => @books %>;
< %= render :partial => "book_rows", :locals => {:books => @books} %>
< %= pagination_links %>
< % end %>
</em>

</div>

You want to test the conditional to see that the partials to display the list of books work correctly. You don’t want to worry about concerns like setting up the books collection, and you might even want to stub out the call to the partial that displays the tabs a the top of the page.

The Rspec example group for this looks like the following:

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
27
28
require 'spec_helper'

describe "books.rhtml" do
  before(:each) do
    assigns[:books] = []
  end

  describe "with no books" do
    it "should display 'No Books' message" do
      render
      response.should have_text(/No Books/)
    end
  end

  describe "with books" do
    before(:each) do
      assigns[:books] = [Factory.build(:book)]
      template.stub(:render).and_call_original
      template.stub(:render).with(hash_including(:partial => "tabs"))
      template.stub(:render).with(hash_including(:partial => "shared/pagination"))
    end

    it "should render book rows" do
      template.should_receive(:render).with(hash_including(:partial => "book_rows"))
      render
    end
  end
end

The key find was to use with(:hash_including()) which I found from a helpful link at Stack Overflow.

Breaking the Build at the New Job

I broke the build

My first break of the CI build on a new team came about two weeks into starting the new job. We had made a small change to a dynamically created URL on a single page of the application. Normally this would fall into the category of “too simple to test” for me. My pairing partner pointed out when we started the story that we should put a test in for the change. I argued that changing a URL was too simple a change to bother writing a test for. He disagreed, but let me go ahead after some further discussion. After checking in the feature, about an hour later a developer on the other side of the room piped up with “Someone broke the build.” My pairing partner smiled and said, “I guess we didn’t need to test that.”

It turned out there was another test I didn’t realize had a dependency on that same link and by changing it we had broken an assertion on the specific URL. A bit embarrassed I learned an important lesson. My assumptions about “too simple to break” needed some adjusting.

Over the course of several weeks I came to appreciate that many things were worth testing. A particularly revealing example was testing a new javascript dialog. Javascript is always a pain point when it comes to unit testing, and I’ve often let that coverage of javascript functionality be covered by functional tests usually with Selenium. My pairing partner walked me through a complete TDD approach asserting every part of the function we created and the various DOM elements we used to create it. I did ask a few questions about whether we really needed to test that we had created a DOM element in some exact order at points, but he was firm about testing in every piece. By the end of the feature I had a new appreciation for doing very low level unit testing.

I love that I’m being challenged on not writing enough tests. For so long in past shops I was the hardcore TDD advocate constantly questioned about the real need for testing some component. Now I’m learning to test in even very small changes.