Dahlia Bock

29Jan/121

Layered teams and how to do it wrong

I have previously expressed my disapproval of layered teams in the past, so I won't do it again. (Who are we kidding...)

Here's a list of things you can do so that everything will go as smoothly wrong as possible:

  1. Limit communication between teams to the 'leads'. Don't encourage each team member to learn how to collaborate with other teams without depending on their 'lead'.
  2. Allow each person to go off into a silo and develop something and declare that it is done without confirming that it is consumable by other teams.
  3. Collaborate on API design? That's absurd.
  4. Make sure your team members don't learn the domain and understand what they are building. This includes not talking to the business people (Refer to #1).
  5. When actual communication is needed between teams and their leads aren't around to facilitate the discussion, use a ticketing system as a starting point and direct all future communication there. Face-to-face conversations should be kept to a minimum because everything needs to be tracked and we can't track real conversations.

I think teamwork has just been redefined. Sigh.

 

Filed under: teamwork 1 Comment
25Jan/120

ActiveRecord: Avoid N + 1 queries

Ruby 1.8.7, Rails 2.3.8

I made a rookie mistake a few days ago but thanks to a colleague of mine who smacked me on the hand, I had a chance to correct it. Consider the following model:

class Order < ActiveRecord::Base
  belongs_to :account
end
class Account < ActiveRecord::Base
  has_many :orders
end

If you are retrieving a group of accounts and accessing each of its orders, you would be encountering an N + 1 query problem. Meaning you would be firing 1 query to retrieve 1 account, and if that account has N orders, N + 1 queries would be executed.

accounts = Account.find(:all, :limit => 10)
 
accounts.each do |a|
  puts a.orders
end

ActiveRecord uses default_scope to avoid the N + 1 situation.

class Account < ActiveRecord::Base
  default_scope :include => :order
  has_many :orders
end

This will execute just 2 queries:

SELECT "accounts".* FROM "accounts" LIMIT 10
SELECT "orders".* FROM "orders" WHERE "orders"."account_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

The :include option can be used in a named scope as well. Long running queries are bad (of course), especially when you are dealing with tens of thousands of records.

Lesson well learnt (and remembered). Thanks Blake.

30Dec/111

Inspiration for 2012

I've always been a pragmatist. It has to be realistic before I decide to do something. I have to admit that I might have missed out on a lot along the pragmatic way but with all the responsibilities of life and family, I don't think I will ever be able to let that side of me go.

I also want to be useful. I want to use my skills (whatever they might be) for the benefit of a life or two, and no, corporations don't count.

In most cases, those two sides of me don't mix very well because doing one might cause the neglect of the other. So in the last few months I've been searching for ideas on how to be pragmatic and useful at the same time. I haven't thought of anything yet (not surprising) but I know that I should stretch the practical side of me this coming year.

As much as I prefer being comfortable, curve balls, come get me!

Filed under: ramble 1 Comment
12Oct/110

ThoughtWorks University: Effective use of pairing as a coaching tool

Part of the current format of ThoughtWorks University (TWU, the graduate training program at ThoughtWorks) is to place grads on a project to get their hands dirty and experience what it would be like to be on TW project with a real client. There have been debates about whether or not a project run at TWU is indicative of what a real TW project would be, one of the reasons being the ratio of experienced to inexperienced team members is really low, but we shall put those arguments aside for now.

As a trainer, one of my responsibilities is to pair with the grads on my team as I would've done on any other project. However, things are not as straightforward as just pairing because it involves other sub-responsibilities as well, e.g. assessing their technical skill levels, figuring out their problem solving techniques, understanding how best they learn and adjusting my coaching responses to them accordingly. Of the two terms of TWU that I worked with, we had an average of 5 grad developers to a trainer. Ideally, I would like to have at least 3-4 days of pairing time per grad, broken into 2-day slots where the former would be a chance for me to assess where they are at and how to form a customized coaching plan for them and the latter for them to have a chance for them to work on the feedback they received from the first pairing session (if any) or get more out of pairing with someone with more experience since that really is one of the main goals in the first place.

At 4 days per grad and 5 grads per trainer, that works out to be 20 days in total. With only 6 weeks per term, that doesn't allow room for edge cases or other work that will take away time from pairing (surprisingly enough, there are lots of it).

What I think would be preferable is to have a 3-1 grad/trainer ratio and a smaller number of grads per group. I don't think piling on more trainers to the mix will improve the situation as more people means more overhead. I would like to hear other TWU trainers' experiences related to this (apologies for this being very TW-specific) because circumstance seemed to have dictated that my 2 terms were (somewhat abnormally) large ones and I wished that things had been different.

28Aug/111

Grails: Speeding up dependency resolution

Something you might want to consider doing in your project is to lock down specific version of your dependencies instead of getting the latest release. The dependencies closure in our BuildConfig.groovy used to look like this:

    dependencies {
        test "org.codehaus.geb:geb-core:latest.release"
        test "org.codehaus.geb:geb-spock:latest.release"
        test "org.seleniumhq.selenium:selenium-chrome-driver:latest.release"
        test "org.seleniumhq.selenium:selenium-firefox-driver:latest.release"
        test "org.seleniumhq.selenium:selenium-ie-driver:latest.release"
        test "org.spockframework:spock-core:0.5-groovy-1.7"
    }

Every script we ran took about 30-45 secs to resolve dependencies before it did anything, which was quite ridiculous. So after some digging around, Ben and I found out that if we specified the version of the plugins we wanted, that would drastically reduce the time spent resolving those dependencies.

This configuration shaved off about 20-35 seconds from our build:

    dependencies {
        test "org.codehaus.geb:geb-core:0.6.0"
        test "org.codehaus.geb:geb-spock:0.6.0"
        test "org.seleniumhq.selenium:selenium-chrome-driver:2.4.0"
        test "org.seleniumhq.selenium:selenium-firefox-driver:2.4.0"
        test "org.seleniumhq.selenium:selenium-ie-driver:2.4.0"
        test "org.spockframework:spock-core:0.5-groovy-1.7"
    }
Filed under: grails 1 Comment
27Aug/112

Grails: Mocking domain classes in controller specs

I've been working in the Grails space for the last few months and after having done some work in Rails before, I've found Grails to be severely frustrating. One of the problems we faced when writing specs for our controllers is that the available testing frameworks (e.g. Spock) doesn't really have the capability to mock out all domain methods (instance and static) properly when they are called from within an event (e.g. beforeUpdate, beforeDelete).

One way that Ben and I tried was to use Groovy's metaClass to essentially mock out those methods that were called within the domain class events. For example, given the Contact domain class:

public class Contact {
    def beforeUpdate = {
        someLocalMethod()
    }
}

And the ContactControllerSpec:

public class ContactControllerSpec extends ControllerSpec {
    def "should update contact"() {
        given:
        def contacts = [new Contact(name: "John Smith", phone: "123456789")]
        mockDomain(Contact, contacts)
 
        when:
        controller.update()
 
        then:
        ...
    }
}

This test will throw an exception saying that it doesn't recognize the call to

someLocalMethod

So we had to mock it out:

registerMetaClass(Contact)
Contact.metaClass.someLocalMethod = {}

The call to

registerMetaClass

ensures that any modifications you've made to the class gets cleaned up at the end of every test.

If someone else knows of a better way to do this, I'd would much appreciate some tips.

Filed under: grails, mocking 2 Comments
24Aug/110

Mac OS X: Un-minimizing windows

Some things in the Mac-land aren't as straightforward as I would like, so I thought this was really helpful. To un-minimize windows:

  1. Press and hold the Apple key.
  2. While still holding down the Apple key, press and release the Tab key until the application you want is selected.
  3. While still holding down the Apple key, press and hold the Option key.
  4. While still holding down the Option key, release the Apple key.
  5. Release the Option key.

It sounds more complicated than it is, so just try it out. Thanks to adsfushi72 who posted this solution here.

Filed under: osx No Comments
23Jun/112

ThoughtWorks University: Balancing spoon-feeding and encouraging self-sufficiency

I'm finally back in Bangalore realizing a secret goal of becoming a TWU trainer after going through the program as a grad myself 5 years ago. It's been an extremely enriching and eye-opening experience so far and I'm learning a lot about my strengths and shortcomings. I'm constantly amazed at how well the current team of trainers are gelling and working off the same page for the most part.

The group is reaching the end of Week 2 of the 6 week program and we're all getting ready to start a proper software project. One of the things that I have been consciously trying to get better at is knowing when dive in and fix a problem I see happening, and when to step back and let the grads figure it out themselves, and if there is an in-between. I find it very difficult to not do anything when I see something go wrong and in a learning environment it is obviously detrimental to a person's learning process if all the problems are shielded from them.

One approach that I'm currently trying is to only step in if it's a quick fix and it's something that I can show them in less than 5 or 10 minutes. If it takes any longer than that, then I will discuss with them the ways I would go about solving the problem and take my hands off after that, or just ask, "Did you ask Google?"

Let's see if this works or if I remember to do it at all!

Filed under: ThoughtWorks, twu 2 Comments
6Jun/110

Pairing: Engaging your R-mode

In his book, Pragmatic Thinking and Learning, Andy Hunt describes the 2 different kinds of processing in your brain, L-mode or linear mode, and R-mode or rich mode. R-mode is behind intuition, problem solving and creativity while L-mode enables you to work through details and make things happen. He believes that to use your brain to its full potential we would want to unleash your R-mode and give it free reign. However, this is physically impossible because when the L-mode is active it actually blocks the R-mode from doing its job.

When pair programming, one person is typically called the driver and the other the navigator. One of the purported benefits of pairing is that it technically should speed up the solving of difficult problems since 2 heads are better than one. Hunt articulates a strategy of pairing that actually does help illustrate how it helps problem solving when done right.

An interesting way to get L-mode to work with R-mode is to use another person for the other mode. In other words, have your L-mode work with another person's R-mode or their L-mode work with your R-mode.
-- Andy Hunt.

Why this works well is because while the driver is engaged in L-mode at a particular level of details (i.e. trying to write a failing test, or write enough code to get a test passing) the navigator is able to engage in other non-verbal matters (i.e. think about the what the next test should be, or how the design of the code fits in the larger picture, or if there are any loop holes they can spot at this point, etc).

I thought this was a great visualization of the benefits of pairing.

Filed under: pairing No Comments
30Mar/110

RapidFTR NYC Code Jam

Since our code jams have been stabilizing over the past few months I thought I'd do a public service announcement for it.

RapidFTR is a tool that allows aid workers to collect, sort and share information about children in emergency situations so that they can be cared for and finally reunited with their families. A bunch of ThoughtWorkers (and friends) have been involved with this project for the past year or so and we get together every Tuesday evening at the ThoughtWorks New York office. Our counterparts have also started weekly code jams in London and Melbourne, Australia.

Details for the NY RapidFTR Code jam:
1515 Broadway, 12th Floor
Every Tuesday evening, 7pm onwards
Pizza and beer will be provided.

Sign up on the google group: rapidftr@googlegroups.com to get connected and to let us know you'll be joining us so we can put your name on the building security list!

Filed under: ThoughtWorks No Comments