Team Debt

I’m currently having a blast leading the technical team behind the LivingSocial Takeout & Delivery web site. One of the challenges of a growing team is maintaining appropriate amounts of communication. You want everyone to know everything that’s important, but not everything. Otherwise, you end up being a case study in The Mythical Man Month.

Although our team did not follow this plan when it was ramping-up, hindsight reveals the need for a team debt management strategy as it grows. After mulling over it for awhile, I’m fairly sure that if I lead a new team in the future, we will follow this path:

First engineer to join the team

  1. Sets-up the source code repository
  2. Writes a starter project README
  3. Provisions the application and team notification email addresses
  4. Wires-up application notification email(s)

Second engineer

  1. Sets-up the continuous integration (CI) server
  2. Provisions the CI notification email address(es)
  3. Wires-up CI notification emails

Third engineer

  1. Sets-up the team’s Campfire
  2. Wires-up commit and deployment notifications (Campfire and/or email)

Fourth engineer

  1. Sets-up a scrubbed production database dump that engineers can use for local development

What tech team debt tools do you typically employ, and when do you employ them?

The Art of Innovation by Tom Kelley and Jonathan Littman

Several years ago, my dad, Bo Lotinsky, showed me the infamous 60 Minutes special on IDEO–the mecca of innovation. After watching it, I couldn’t help but buy their book The Art of Innovation. I finally got around to reading it, and boy is it good. As always, a bulleted list of ideas and quotes don’t do the book justice. They’re more for me to remember what I read and for you to be intrigued enough to read it yourself. Enjoy!

Chapter 3: Innovation Begins with an Eye

  • Keep a list of what bugs you in products.
  • Ask “why/why not?” to understand and challenge what has already been done.
  • Observe the action–not what people say.
  • “Think of products in terms of verbs rather than nouns…as animated devices that people integrate into their lives–and you’ll become more attuned to how people use products, spaces, services–whatever you’re trying to improve.”

Chapter 4: The Perfect Brainstorm

  • Stick to one hour (one and a half max).
  • “Start with a well-honed statement of the problem…at just the right level of specificity…open-ended.”
  • Play: “go for quantity,” “encourage wild ideas,” and “be visual.”
  • Number each idea. Aim for 100 per hour.
  • Build on ideas with variations. Jump to other trains of thought when the current thread has died.
  • Use giant whiteboards, Post-It notes, or butcher paper. The brain is wired for spacial memory, so move around the room to write and to revisit topics.
  • Start with a mental warm-up exercise if people seem to be elsewhere. One great exercise is to survey products in the same category you’re trying to brainstorm in.
  • Sketch, mind-map, diagram; don’t just write words.
  • Spend much more time brainstorming than writing. You want to stay on the creative side of the brain.
  • Everybody is on the same level. No one is the boss, expert, or auditor.
  • No idea is to be critiqued. Just write it down and continue.
  • Don’t make up any other rules.

Chapter 5: A Cool Company Needs Hot Groups

  • Even the world’s best historical innovators worked in teams. Loners don’t succeed.
  • Build teams around problems to be solved, not a team role.
  • Bring in people from all roles and experiences.
  • Look outside the group for ideas, solutions, and feedback.
  • Team leaders pitch potential project members. No one “owns” people. (Note: movie studios, Google, and Netflix do the same thing.)
  • Don’t mandate attire or business hours.
  • Provide snacks.
  • Have a geek club where people can show off the latest technology or demo something they have built.
  • Play hooky as a team and go on a field trip.

Chapter 6: Prototyping Is the Shorthand of Innovation

  • “A playful, iterative approach to problems is one of the foundations of our culture of prototyping.”
  • “A prototype is almost like a spokesperson for a particular point of view.”
  • “A prototype is worth a thousand pictures.”

Chapter 8: Expect the Unexpected

  • “History teaches that innovation does not come about by central planning. If it did, Silicon Valley would be nearer to Moscow than San Francisco.”
  • It’s almost impossible to predict how the market is going to use a product.
  • Spend time absorbing what’s going on around the world. IDEO has subscriptions to at least 100 magazines.
  • Observe people in the wild accomplishing tasks.
  • Hold an open house to solicit feedback and ideas from people.

Chapter 9: Barrier Jumping

  • Organizational checklist: merit-based, employee autonomy, familiarity among staff, messy offices, lots of tinkering.

Chapter 10: Creating Experiences for Fun and Profit

  • “As you step through the innovative process, try thinking of verbs not nouns.”

Chapter 11: Coloring Outside the Lines

  • “The person who toils endlessly at his desk is not likely the person who is going to hatch a great innovation.”

Best Kept Secrets of Peer Code Review by Jason Cohen

Best Kept Secrets of Peer Code ReviewIt has been three years since I have been under the oppressive finger of the waterfall software engineering process, but that is still what comes to mind when I hear the words “peer review.” Corporate software outfits typically require programmers to present their code to other engineers in hopes of finding bugs and fixing them before they become a problem. Usually it involves some form of screen-sharing and walk-through of code snippets developed in the past few days. From my five years of experience doing this sort of review, reviewers rarely found bugs in code–no matter how poor a software engineer or how great a reviewer.

I know book-editing is a great practice, and I know that no software engineer is perfect, but my experience has prevented me from seeing benefit in the concept. Best Kept Secrets of Code Review by Jason Cohen renewed my perspective on peer reviews by presenting a more effective way of doing them. The book’s purpose is two-fold: (1) present compelling arguments and practices for effective code review and (2) sell a peer review tracking product called Code Collaborator. Thankfully, the book reserves the sales pitch for the last chapter and does a great job presenting the facts and arguments that ultimately led Smart Bear to build a peer review product. Here are some of my notes, but, like the reviews before this one, I must encourage you to snag your own copy.

Chapter Four: Brand New Information

  • Time is the one factor that a reviewer can control that will effect their ability to identify bugs. The reviewer cannot control the language, algorithmic complexity, or the experience of the developer who wrote the code.
  • 60 minutes of peer review is the sweet spot. Spend more or less time than that and you will statistically either miss bugs or waste time looking for bugs that don’t exist. (On that note: do not spend more than 90 minutes…ever.)
  • The more time a reviewer spends during his first pass over the code, the faster he will be at spotting bugs during his second pass. In other words, go slower the first time around.
  • Private inspection of code produces better results than being guided by the developer in a presentation format. Often reviewers will raise questions that are about how something works, not whether or not a particular piece of code is correct. (More proof that meetings usually waste people’s time and companies’ money.)
  • The hardest bugs to find are code omissions, so arm reviewers with checklists. This list might include items like “should this page require SLL?” or “is allocated memory properly destroyed?” Have your team keep a running list of common bugs to look out for.

Chapter Five: Code Review at Cisco Systems

  • Formal peer review meetings don’t uncover more bugs but do add to the cost of software engineering. (Yes, this is a repeat comment–just driving it home!)
  • The one benefit of a formal meeting is that it motivates the presenter (developer) to be more careful and produce higher quality material (code). Knowing that someone else is going to formally inspect your code will compel you to write better code.
  • Only 200-400 lines of code should be reviewed at any one time. (Recall our 60 minute sweet spot from above? 200 lines / 90 minutes = 2.22 lines per minute. 400 lines / 60 minutes = 6.66 lines per minute. That’s a lot of time.)

Chapter Seven: Questions for a Review Process

  • Keep your peer review checklist in-between 10 and 20 items. Too many, and the reviewer’s effectiveness drops.
  • If necessary, create different flavors of checklists to cover more than 20 items: logic bugs, security, design, etc. Have different reviewers use different checklists.

The book is also full of really nice references, case studies, techniques for measuring team effectiveness, and points for team leads. It’s worth the read, so check it out.

Importing a Contacts CSV into Gmail and BitPim Correctly

Snowmageddon was the perfect excuse for me to initiate my migration over to Google Gmail and play with Google Voice.

I had to start by exporting and merging my contacts out of an LG EnV via BitPim, Microsoft Windows XP Address Book, and Microsoft Hotmail Contacts. The export to comma-separated values (CSV) in each application was straightforward. The merging I did manually in Microsoft Excel because Address Book and Hotmail stick to the human-readable Mobile Phone, Home Phone, Office Phone, but BitPim spits-out primary, secondary, and tertiary phone numbers as numbers_number, numbers_type three times over. As for email addresses and email types, Address Book and Hotmail do the primary, secondary, tertiary dance, while BitPim limits it to primary and secondary email addresses and types.

After having a cleaned-up contacts list, I was ready to charge forward. However, to my dismay, the Gmail Contacts CSV importer prefers a different format. It wants primary, secondary, and tertiary phone number and phone number type columns and primary and secondary email and email type columns, but the type column data is different depending on what sort of data a record has. So, while Home may work for one record, another record requires * Home. Mind-blowing.

With inspiration from others who have walked a similar path, I decided to write a simple Ruby script to convert contacts from a human-readable CSV format into something Google Contacts likes.

The format of the input CSV is as follows (you might as well throw these column headers into your input CSV as well):

First Name,Last Name,Home Email,Work Email,Mobile Phone,Home Phone,Work Phone

The output CSV matches what Google likes.

And here is the script:

# Simple CSV to Gmail Contacts CSV
# by Ian Lotinsky (https://ianlotinsky.com/)
# Released under the MIT License (http://en.wikipedia.org/wiki/MIT_License)

# Run like
#   ruby gmailcsv.rb my_contacts.csv > import_into_gmail.csv

require 'rubygems'
require 'fastercsv'
if ARGV.size != 1
  puts "USAGE: #{__FILE__} <original csv>"
  puts "  First Name,Last Name,Home Email,Work Email,Mobile Phone,Home Phone,Work Phone"
  exit
end

puts "Name,Given Name,Additional Name,Family Name,Yomi Name,Given Name Yomi,Additional Name Yomi,Family Name Yomi,Name Prefix,Name Suffix,Initials,Nickname,Short Name,Maiden Name,Birthday,Gender,Location,Billing Information,Directory Server,Mileage,Occupation,Hobby,Sensitivity,Priority,Subject,Notes,Group Membership,E-mail 1 - Type,E-mail 1 - Value,E-mail 2 - Type,E-mail 2 - Value,Phone 1 - Type,Phone 1 - Value,Phone 2 - Type,Phone 2 - Value,Phone 3 - Type,Phone 3 - Value"

FasterCSV.foreach(ARGV[0], :headers => :first_row) do |row|
  full_name = "#{row.field("First Name")} #{row.field("Last Name")}".strip
  puts "#{full_name},#{row.field("First Name")},,#{row.field("Last Name")},,,,,,,,,,,,,,,,,,,,,,,* My Contacts,* Home,#{row.field("Home Email")},* Work,#{row.field("Work Email")},* Mobile,#{row.field("Mobile Phone")},Home,#{row.field("Home Phone")},Work,#{row.field("Work Phone")},"
end

And because I wanted to be able to sync my contacts between Google and my phone in the future, I tried to write a script to transform a Google Contacts output CSV into a CSV that BitPim likes. But, alas, Google’s export CSV is inconsistent at best, so I wrote a script to go again from human-readable but this time to BitPim CSV:

# Simple CSV to BitPim Contacts CSV
# by Ian Lotinsky (https://ianlotinsky.com/)
# Released under the MIT License (http://en.wikipedia.org/wiki/MIT_License)

# Run like
#   ruby bitpimcsv.rb my_contacts.csv > import_into_bitpim.csv

require 'rubygems'
require 'fastercsv'
if ARGV.size != 1
  puts "USAGE: #{__FILE__} "
  puts "  First Name,Last Name,Home Email,Work Email,Mobile Phone,Home Phone,Work Phone"
  exit
end

puts "names_title,names_first,names_middle,names_last,names_full,names_nickname,numbers_number,numbers_type,numbers_speeddial,numbers_number,numbers_type,numbers_speeddial,numbers_number,numbers_type,numbers_speeddial,emails_email,emails_type,emails_email,emails_type,categories_category"

FasterCSV.foreach(ARGV[0], :headers => :first_row) do |row|
  full_name = "#{row.field("First Name")} #{row.field("Last Name")}".strip
  puts ",#{row.field("First Name")},,#{row.field("Last Name")},#{full_name},,#{row.field("Mobile Phone")},#{"cell" unless row.field("Mobile Phone").nil?},,#{row.field("Home Phone")},#{"home" unless row.field("Home Phone").nil?},,#{row.field("Work Phone")},#{"office" unless row.field("Work Phone").nil?},,#{row.field("Home Email")},,#{row.field("Work Email")},,"
end

And of course, after I got this all working, I remembered that there is a Google Contacts API that I should have tried playing around with.

I hope this saves people from the frustration I experienced and the time I wasted because of bad CSV importers and exporters. If you have an suggestions for improvement, please leave a comment.

The Unplugged by Ruven Meulenberg

While researching user experience design techniques, I stumbled upon some nifty whiteboard magnets for prototyping called GuiMags as well as a complementing book called The Unplugged.

GuiMags look like the nicest way to prototype something before going to HTML and CSS. Labor intensive forms of prototyping don’t seem to add much value, and paper and traditional whiteboard prototyping only works until you’ve changed your mind about something and have to throw your work in the trash or erase half the board.

Although I decided to postpone a magnet purchase until I am doing design again, I was able to get my hands on the book. Its premise: we limit ourselves by the technologies we use. Instead of thinking outside the box, we’re often thinking and functioning in it. A large part of this thinking inside the box is how we develop software.

Although, everyone interested in the topic should pick up the book, here are a few of my takeaways:

  • Every major form of art that involves technology (music, film, video games, graphic design) starts outside technology. Artists do not limit themselves by their technology but by the limits of their own minds. As a software engineer, you often limit yourself by the technology you use day-to-day.
  • Spend as much time as you can iterating on concept and design before going to implementation.
  • Design the software front-end not the back-end first.
  • Just like there are code freezes, freeze the product when it has passed the design phase.
  • It is often wise to outsource the implementation.
    • This serves as a peer review of the design before it goes to implementation. Software developers traditionally think about the back-end first.
    • Different cultures have different strengths: “England and Western Europe are great at design, Ukraine and Macedonia have amazing and prompt developers who can think for themselves, the Netherlands always emails back the same day, India is extremely polite, etc.”
    • Work can be done while you are sleeping. “This can cut the development time in half.”
    • Because you already know what you want and won’t be constantly changing the design, contractors will want to work with you even if you pay less.
    • Only be satisfied with five-star developers.
    • Pay more than you agree to pay.
    • Do one-week sprints. Longer sprints end up getting delayed, with excuses.

With the last (sub)point in mind, I think this methodology is well-suited for an agile development process.

There is a lot to gain from reading the book, so make sure to grab a copy for yourself.