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.