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.”

Rails path and url helpers

Sometimes I forget the simple differences between Rail’s helpers. This mini post is so I don’t forget.

*_path
Generates relative URLs: /users
Used in views by link_to, form_for, etc. (per DHH)
The browser maps relative URLs to absolute URLs based on the current page’s protocol and host (/users on the page http://domain.com/new translates to http://domain.com/users)

*_url
Generates absolute URLs: http://domain.com/users
Used in controllers by redirect_to (per DHH) because RFC 2616 states that redirects must be absolute URLS. This is true, however, modern browsers can handle relative URL redirects now too

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.

assert_raise in Rails Integration Tests

Today I wanted to assert that a POST from an integration test resulted in an exception being raised under certain conditions. I had done this bunch of times in unit and controller tests, so I just ported that methodology to my integration test. Here is a contrived example of how my original test read:

  def test_that_exception_is_raised
    exception = assert_raise(RuntimeError) {
      post '/comments', {:comment => {:message => 'I hate you!'}}
    }
    assert_equal 'Say something nicer please. Thank you.', exception.message
  end

The problem was that the assertions were failing because <RuntimeError> exception expected but none was thrown. But I clearly saw in my test.log that the exception was thrown:

  RuntimeError (Say something nicer please. Thank you.):
    app/controllers/comments_controller.rb:789:in `create'
    test/integration/comments_test.rb:456:in `__bind_1278520981_664592'
    /ruby/lib/ruby/8.8/test/unit/assertions.rb:123:in `assert_raise'

I thought about about the differences between functional and integration tests in Rails, and then realized that although the exception was thrown, that’s not what is returned to the browser. Instead, the browser is sent an error page. Then it became glaringly-obvious, how to write my assertion:

  def test_that_exception_is_raised
    post '/comments', {:comment => {:message => 'I hate you!'}}
    assert_response :error, 'Say something nicer please. Thank you.'
  end

I still feel like a newbie sometimes.

Ruby include and extend

My employer, Razoo, treated its developers to RailsConf 2010 this year. Very late the second night of the conference (the first night I was there–we skipped the tutorials), I saw Yehuda Katz give an impromptu Birds of a Feather talk about upcoming changes in Rails. It was good, but the thing I remember most clearly was his explanation of include and extend in Ruby. He let code do the explaining:

# a module with a method
module Says
  def hello
    puts 'hello'
  end
end

# a class we want to have the method (not an instance; the class)
class Person
end

# (our end goal)
class Person
  def self.hello
    puts 'hello'
  end
end

# there are two ways to achieve this
# using extend
class Person
  extend Says
end

# or using include
class Person
  class << self
    include Says
  end
end

So, in short, include just includes the module’s methods as instance methods and extend includes the module’s methods as class methods. I always do better with examples than reading technical documentation!