Teachable Moments in Software Pairing
My last week at CoverMyMeds was a lot of fun. It was satisfying to have no loose ends left untied. One of the benefits was being able to work with a co-op on our team, Braden. Braden started a few months ago and pairing in the office made me wish that I had spent more time pairing with him since he started. Pairing with Braden reminded me of what it was like when I first started, deer in the headlights, confused about everything going on. The inspiration for this post started when he asked me to review his code, and that led me down this rabbit hole.
It’s pretty typical to get a hipchat message asking to have me review someone’s
code. I’m sure this happens to most developers. We look at it, send back our
comments, start a conversation, and inevitably, give it a :+1:
. I was going to
do that again today; but, I got in early, I didn’t have much on my agenda, I
told Braden I was going to review it with him. This allowed me to do more than
just review his code. I could give him insights on what I think about when
reviewing. What kinds of questions I ask myself, like “could this be
simplified?”, “how clear and readable is this code?”, “if this test failed,
would I be able to figure out what went wrong?”, “are there any cases that don’t
seem to be tested but should be?”
As we were walking through his code, I could tell that there were some points of
weakness that could be strengthened. When I noticed these, I stopped what we
were doing. Reviewing code was nowhere near important as this teachable moment.
It was very trivial. Should this method test be describing #open
or .open
?
There’s a 50/50 chance of getting this right, and luckily for Braden, he got it
wrong. The Chat.open
method was a scope listed on this model. Unfortunately, I
don’t have the code available to me anymore, but it looked something like this:
scope :open, -> { where(active: true) }
This was a great example. We quickly moved to a blank text document and I asked to take the Chat model and remove everything except this line. From here, I asked him to write the ruby code that this is a shortcut for. He looked at it, and couldn’t figure it out.
So we broke it down.
How would we call this? He looked for a little and ended up with: Chat.open()
Which is correct. So then I asked, how would you write that method?
def self.open
self.where(active: true)
end
Great, we had written it out. Now I moved from intermediate to advanced, how
would we rewrite the .scope
method?
This took a while as well. We had to break it down. What is calling scope in the
middle of this line actually doing? Well it’s just calling a method called
scope
where we pass in 2 arguments, a symbol, and a block. So the method
declaration became easy.
def scope(method_name, method_call)
#blah
end
This is where we had to dive into metaprogramming. Something that I hadn’t
touched until months after starting, and Braden was getting a taste in just a
few weeks. Once we talked about define_method
, it was easy to come up with
replacing #blah
with the dynamic definition of a method.
And that was it. A whirlwind introduction to metaprogramming and ruby macros in
a nutshell. Just to ensure understanding, I asked Braden to rewrite another
rails method, like validates
just to ensure that he understood the concept of
macros.
Later in the afternoon, we ran across an example of a macro, and he was easily able to understand what was actually going on. This was probably one of my proudest moments at CoverMyMeds. Less than 72 hours from my last day, and I felt a strong sense of pride and hope for my team.
To summarize, Mentor-Mentee pairing starts as Driver-Navigator, where the mentee is an active navigator or active driver. And when a concept comes up, that’s confusing, the mentor steps in and discusses the concept, and walks the mentee through examples to ensure understanding. Finally, the pair returns to their work. Very much a teach a man to fish scenario.