The Consulting Legitimacy Cycle: 4+ years to 2 weeks

Four years ago this month, I wrote “The Consulting Legitimacy Cycle,” a post about cycling between predominantly consulting/training and predominantly in-team software development. At the time I’d been consulting for about 15 months, and was pondering when I might next return to full-time development.legitimacy

It turns out that the answer was “a little more than a year.” I signed on to Outpace Systems as a remote developer in August 2013, and wound down my other engagements to be fully engaged with Outpace by the end of the year. Thus after about 2 and a half years on the consulting side of the cycle, I switched to the development side, where I would spend almost 2 and a half years.

Outpace would turn out to be the biggest challenge I’d had in a long time: a pile of new technologies with which I had little familiarity kept me under water for at least the first six months. I’ll be honest and blunt: I felt like an idiot for a half year.

During those first six months at Outpace, I would bounce virtually every day or every other day to something completely different. It kind of works when pairing… but it sure takes a long time to ramp up on something! We began to replace Ruby with Clojure a couple months in, which was great. But when you code in a new language for a day, and then don’t touch it for a week, it takes a long time to get proficient. At maybe a day a week, it took me six months before I began to feel reasonably comfortable in Clojure.

(Among the bigger learning curve elements: using a Mac daily for the first time, the sheer hell of learning Emacs for someone with a solid preference for vim, and for the longest time, a New Library of the Week. See “Surviving Chaos With Pairing” for the complete list of technologies.)

The upside: I picked up a pile of skills and an updated understanding of the daily feeling of being a real team member, as opposed to experiencing it from the outside as a consultant/coach/trainer. And the regular success we had in delivering software to happy customers lends a lot of credibility to what I learned about process and technique.

I’m convinced that my regular cycling back into “real” development is what helps me relate so well to teams I work with as a coach. They can tell if you really appreciate and understand what their daily life is like.

The downside: the business languishes. I managed to sneak in a few short engagements (mostly training) each year by using vacation. But I was too swamped to invest much energy otherwise: I wrote only a single blog post in two years, my web site started to crumble a bit (and continued to look increasingly outdated), I didn’t tweet much, and most other forms of outreach to customers, existing or potential, languished.

In February of this year, I chose to re-start Langr Software Solutions based on the financial assurance of a regular bi-weekly gig that should last until the end of the year. This time around, I decided that continuing to help deliver real software was going to be in important aspect of sustaining the viability of the business as well. As such, I chose to continue providing services to Outpace, and I’m also seeking to close a freelance development gig.

I’m hoping this continued involvement in “real” software deliver will prevent me from ever having to halt in order to take a full-time development gig again, and will help me keep the business continually vibrant and available. Maybe my Consulting Legitimacy Cycle will change from 2+ years for a half cycle (4+ years for the full cycle) to about a week.

The Compulsive Coder, Episode 5: Extract Method Flow

To be a refactoring wiz in Eclipse or IDEA, you don’t need to memorize dozens of keystrokes. Combined with a few mega-important keys (particularly Ctrl-1, “quick fix”), seven fairly mnemonic keystrokes will supply the bulk of your refactoring muscle. In Eclipse, they happen to be the top seven on the refactoring menu:

refactorMenu

Your version of Eclipse won’t have a key assignment for Extract Constant. It’s one of the rare keys I custom-assign, and K makes sense if you remember enough high school math.

There are about 20 more refactoring menu items in Eclipse, yet I use most of those so infrequently that I don’t find value in trying to memorize the keys to which they’re bound. I use Convert Local Variable to Field often enough, but rather than assign and remember a keystroke, I simply delete the type declaration and use Ctrl-1 to define the field.

I use these “Super Seven” shortcuts frequently throughout a typical coding day. They (a) minimize the amount of typing I do (and subsequently reduce the opportunity for mistakes) and (b) minimize the amount of mouse clicking I do, which is about an order of magnitude slower and worse for my wrist.

I’m amazed at how often I’m able to accomplish some fairly significant refactoring by solely using combinations of the Super Seven.

One such ultra-common sequence is the extract method flow, a bread-and-butter operation for any developer.

Let’s do a bit of extracting against the following test method:

   @Test
   public void answersDaysLateWhenReturnedAfterDueDate() {
      holding = new LibraryHolding(THE_TRIAL, BRANCH_EAST);
      holding.checkOut(TODAY);
      Date threeDaysLate = new Date(holding.dateDue().getTime() + 3 * MS_IN_ONE_DAY);

      int daysLate = holding.checkIn(threeDaysLate, BRANCH_EAST);

      assertThat(daysLate, is(3));
   }

We want to isolate the ugly code to derive threeDaysLate into a helper method, perhaps named addDays. But if we highlight the entire line and simply do Extract Method (Cmd-Option-M), Eclipse doesn’t quite do what we want:

   @Test
   public void answersDaysLateWhenReturnedAfterDueDate() {
      holding = new LibraryHolding(THE_TRIAL, BRANCH_EAST);
      holding.checkOut(TODAY);
      Date threeDaysLate = addDays();

      int daysLate = holding.checkIn(threeDaysLate, BRANCH_EAST);

      assertThat(daysLate, is(3));
   }

   private Date addDays() {
      Date threeDaysLate = new Date(holding.dateDue().getTime() + 3 * MS_IN_ONE_DAY);
      return threeDaysLate;
   }

We want holding.dateDue() and 3 to be arguments to the method. Undo!

A better sequence:

  1. Extract to local variables any expressions we want as arguments.
    1. Highlight holding.dateDue() and press Cmd-Option-L (Extract to Local Variable). Change the variable name to simply date. The result looks like this:
            Date date = holding.dateDue();
            Date threeDaysLate = new Date(date.getTime() + 3 * MS_IN_ONE_DAY);
      
    2. Similarly highlight the 3 and extract it as a local named days:
            Date date = holding.dateDue();
            int days = 3;
            Date threeDaysLate = new Date(date.getTime() + days * MS_IN_ONE_DAY);
      
  2. Extract the method. First select either the whole line, or just select the right-hand side of the assignment to threeDaysLate. Then press Cmd-Option-M. Type in the new method name of addDays. The result:
       @Test
       public void answersDaysLateWhenReturnedAfterDueDate() {
          holding = new LibraryHolding(THE_TRIAL, BRANCH_EAST);
          holding.checkOut(TODAY);
          Date date = holding.dateDue();
          int days = 3;
          Date threeDaysLate = addDays(date, days);
    
          int daysLate = holding.checkIn(threeDaysLate, BRANCH_EAST);
    
          assertThat(daysLate, is(3));
       }
    
       private Date addDays(Date date, int days) {
          Date threeDaysLate = new Date(date.getTime() + days * MS_IN_ONE_DAY);
          return threeDaysLate;
       }
    
  3. Inline the arguments.
    1. Click on (no need to select) either occurrence of the date local variable (either the declaration+assignment, or its use as an argument to addDays). Press Cmd-Option-I (Inline). You’ll receive a confirmation dialog asking whether or not you want to Inline 1 occurrence of local variable ‘date’; simply press enter.
    2. Similarly, click on either occurrence of the days local variable, and press Cmd-Option-I to inline it. The result:
         @Test
         public void answersDaysLateWhenReturnedAfterDueDate() {
            holding = new LibraryHolding(THE_TRIAL, BRANCH_EAST);
            holding.checkOut(TODAY);
            Date threeDaysLate = addDays(holding.dateDue(), 3);
      
            int daysLate = holding.checkIn(threeDaysLate, BRANCH_EAST);
      
            assertThat(daysLate, is(3));
         }
      
         private Date addDays(Date date, int days) {
            Date threeDaysLate = new Date(date.getTime() + days * MS_IN_ONE_DAY);
            return threeDaysLate;
         }
      

      (In addDays, I find the local variable threeDaysLate personally useless, so I also inline it.)

What I love about extracting small abstractions like this is that they open my eyes to additional opportunities to clean things up. It’s now obvious that the method we created belongs elsewhere, perhaps in some sort of date utility class where it broadcasts its existence and thus entices folks to reuse it. What also becomes evident is that the local variable threeDaysLate no longer adds much value. We inline it:

   @Test
   public void answersDaysLateWhenReturnedAfterDueDate() {
      holding = new LibraryHolding(THE_TRIAL, BRANCH_EAST);
      holding.checkOut(TODAY);

      int daysLate = holding.checkIn(addDays(holding.dateDue(), 3), BRANCH_EAST);

      assertThat(daysLate, is(3));
   }

Three steps: extract locals, extract method, inline. No direct typing in the editor. Repeat and ingrain.


Previous Compulsive Coder blog entry: You Create, It Assigns
Next Compulsive Coder blog entry: this Duplication is Killing Me

Atom