Closet Coder

I work in my closet. I code. Yep.

Git Bisect for Great Justice

| Comments

About a week ago, we had an elusive error that appeared when we deployed our latest app to staging. Suddenly, any submission resulted in a “Stack trace too deep” error that gave no meaningful way to determine where the issue was coming from. We were stuck for a couple of days, but then I was reminded of git bisect.

git bisect is a great way to trace down problems to a specific commit for purposes of isolation or blame (though I’d suggest against the latter). Like you’d expect from a programmer, it even searches efficiently, using a binary search, hence bisect.

Fundamentally, what bisect does is split the commits from the latest good commit to the earliest bad commit in half over and over again until one commit has been isolated which transition occurred.

Let’s say that you were a terrible developer and didn’t run your tests before checking in. After several days of doing this, you run your spec suite and get an unhelpful error which prevents the spec suite from even being run. Since you don’t know when that was introduced, you use git bisect

1
2
3
4
$ git bisect start
$ git bisect bad # marks the current commit as bad
$ git bisect good production #marks the commit pointed to by 'production' (branch or tag) as good
Bisecting: 62 revisions left to test after this (roughly 6 steps)

Now you are in the middle of bisecting. You can then attempt to run specs (or manually test for an error) and mark the commit accordingly

1
2
3
4
5
6
7
8
9
10
[3939bac050b2779d5d13a3757054511eb0f8961a] Update Rakefile to point to sensible server.
$ rake spec
ERROR! ...
$ git bisect bad
Bisecting: 31 revisions left to test after this (roughly 5 steps)
[f2230b2e2ccf636266891ce6be3750994f414fe4] Fixing Issue #2294
$ rake spec
.......  ^C
$ git bisect good
...

You continue until you’ve isolated the commit…

1
2
3
4
5
6
$ git bisect good
1c675b26e5b8472d28d3fb44a23119ba41e7002c is the first bad commit
commit 1c675b26e5b8472d28d3fb44a23119ba41e7002c
Date:   Wed Apr 4 16:11:40 2012 -0500

    Adding support for Guard

Then you can look at that commit and address it specifically. This is a huge argument for small commits, especially when you’re looking for small, difficult to find bugs related to subtle business logic.

When you’re done, just git bisect reset and you’ll be back on your HEAD.

You may be asking if you could do this manually – and then answer is an absolute YES, but bisect provides a very simple and easy way to step through the process without a lot of extra thought or effort.

CanCan and Devise With Nil Current_user on POST

| Comments

I had a Rails 2.3.X app that I migrated to Rails 3. When I did, I upgraded CanCan and Devise. Suddenly, my delete links weren’t working. I remembered that unobtrusive JS was the default so I hopped into the application.html.erb template and added the relevant javascript tags.

application.html.erb
1
2
3
4
5
6
7
  ...
  <head>
    ...
    <%= javascript_include_tag 'prototype', 'rails', 'application' %>
    ...
  </head>
...

Great! Now my delete links weren’t just links to the show action, but when I did click them I noticed that a CanCan error appeared. After some debug statements, it became clear that current_user wasn’t set, but only on the POST/DELETE methods. Hmmm. What could be causing this?

Yes! The csrf tags!

If you’re upgrading to Rails 3 and you see odd behavior on POSTs with the session (anything that tries to protect_from_forgery), make sure you have this line in the head section of your application layout.

1
  <%= csrf_meta_tag %>

Crisis, averted.

Best Way to Bundle

| Comments

Thanks to the RubyRogues Episode on Bundler, I learned the best way to use bundler.

You want to always use the “pessemistic” version numbers for a handful of reasons.

1
2
gem 'rails', '~> 3.0.3'
gem 'rspec', '~> 2.7.0'

This allows the most efficient resolution of gem dependencies (in this case, any version of rails from 3.0.3 up to and not including 3.1, and any version of rspec from 2.7.0 up to and not including 2.8) and the added benefit of allowing you to easily patch everything safely using only bundle update.

You also want to be familiar with the various levels of ‘conservatism’ in updates.

1
2
3
bundle install # once the Gemfile.lock exists... most conservative
bundle update <gem>[ <gem>] # only update specified gems
bundle update # update all gems to latest validly specified versions

This allows you to properly patch everything and keep your gems in proper sync in the most efficient manner.

You should also update to bundler 1.1 since it uses a much faster API call to download the latest index of gems and dependencies from rubygems.org. Yay, faster bundler!

Always Fight for Simpler

| Comments

If there is one thing I have said over and over again in one form or another, but never seem to learn completely, it’s “Always Fight for Simpler.”

Everything could be simpler. Sure, we think it can’t, but it can. Don’t assume you need a feature in an app, a gadget in your life, or a certain amount of money… fight first for simpler.

Ask yourself, for any given situation, what the simplest possible solution to the problem is. Maybe it’s not good enough… but maybe it is. Fight for the simplest solution and go from there.

Simple doesn’t always mean cheap, fast, easy, or perfect. Simple means it lacks complexity. Simple means it depends on few other things. Simple means less instead of more.

Complexity and Elusive Perfection

| Comments

About three or four times a year, I find myself wishing my application wasn’t so complicated. I wish I was some stud developer who always made the right architectural decisions and didn’t back myself into a corner. I read about OO ideas regarding change management and coding for change even when you don’t know what that change is and mostly, I find myself baffled.

Hindsight is 20/20. I can see easily how the decision that seemed good at the time to make a Model.seed! method that allowed you to specify all the department data in the database AND change it in the app was a bad idea. I can see that allowing users to change values of reports from within the reports, like a spreadsheet without using the adjustment-as-a-line-item pattern is now a bad idea… but we’re 3 years on and it’s just not something we’re going to be able to convince the users to change or the management to invest the money in fixing.

Then I ran across one of the best tweets ever. from @jeremyckahn - “All codebases are abominations. They are all terrible. If your codebase isn’t a disaster, it probably doesn’t do anything interesting.”

It’s so true. Remembering that you’ll always make some wrong choice when designing a complex app helps you to be able to cope with the pile of technical debt that has accumulated. Making poor choices because you’re lazy is one thing, but making poor choices because you don’t have the experience or expertise is quite another thing entirely.

If you don’t think your code is crap, you’re probably doing it wrong, or you haven’t been doing it long.

Octopress

| Comments

I am trying out Octopress as a new blogging engine. I have seen several people use it and I appreciate the lack of PHP :)

My Ideal GTD App

| Comments

I have been a long time user of Things by Cultured Code, but they have been very slow implementing a couple of features that would really enhance the way I use GTD, namely time based reminders, location based reminders, and cloud-based syncing.

So I went out looking. Producteev looked pretty good, but it is woefully underpolished. Firetask also looked promising, as did Wunderlist, but both left something to be desired. Toodledo had nearly everything except a native app.  Omnifocus looks like it has all the features, but is so complicated and ugly that I don’t like it.

So I’ve come up with my list of needs, wants, and wishes for a GTD app. I don’t think it’s comprehensive, but it doesn’t seem like too much to ask–and yet there is nothing in a reasonable price range to do what I want.

So here’s my list. Take it for what it is. And if you know of something that implements all the musts, most of the wants and some of the needs… let me know.

Needs

  • Native Mac App (as a first class part of the solution)
  • iPhone App with Sync
  • Global Hotkey for capture that goes by default to the "Inbox"
  • Recurring Tasks
  • Easy Deferring of Tasks
  • A good "Focus"/"Today"/"Now" view that makes solid sense
Wants
  • Solid Cloud Sync
  • Easy Delegation of Tasks (drag, e-mail/web app notification)
  • Contexts / Workspaces
  • Projects / tags
  • Basic integration / support for Pomodoros
  • Full screen mode in Lion that takes advantage of the screen real estate to show task details, sub tasks, etc for the *current* task.
  • Push notifications / App badges for tasks remaining
Wishes
  • Defer to Location (best - switch contexts based on location automatically, some tasks context free)
  • Defer to Time: maybe not as important if location based worked, but being able to defer something until 9:00 pm gets it off my focus list until after my kids are in bed.
  • Defer until Focus section is 'empty': Implemented as "dependent" tasks or "next" tasks or "next tasks" for within a project.  Hard to get this right.
  • Full on support for Pomodoro
    • Start a pomodoro for a given task, tag, or context
    • If started for a task, automatically mark the # of pomodoros taken
    • If started for a tag or context, still record the pomo and the tasks checked off during it
    • If the "interrupt" key is pressed, prompt for recording a new task in the inbox
    • If not resumed, mark the pomo as failed
  • Review Support
    • Reports of Pomodoros for the day/week/month
    • Reports of tasks completed for the day/week/context
    • Graph of "productivity" based on pomos completed per day
  • Calendar View, integrated with iCal calendars

Now, I know my list looks long to those in the GTD world, but if you look at the features, they seem simple to implement.  Very simple.  Omnifocus is the closest to this, but has no Pomodoro support and bad “Today” support.  Producteev is actually really close, but lacks enough polish.  Things is still the best task manager I’ve found for managing tasks AND getting out of the way.  Has someone made this task manager I seek?  If not, I assume I’m naive for thinking it is simple to do.  I’m considering whipping together a webapp prototype that does what I want.

What’s your ideal GTD app?  What features would you say are imperative?

 

Don't Use DateTime in Rails 3

| Comments

Rails 3 has good TimeZone support built in, but you have to use the right Date and Time classes to get full support.

If you have this set in your application.rb config.active_record.default_timezone = :local, then you really need to use Time so that it properly identifies itself as being in the local timezone and not in UTC when passing to the database insert.

1
2
3
4
5
6
7
8
ree-1.8.7-2011.03 :001 > DateTime.parse('2011-11-27 12:00:00 +0000')
=> Sun, 27 Nov 2011 12:00:00 +0000
ree-1.8.7-2011.03 :002 > DateTime.parse('2011-11-27 12:00:00')
=> Sun, 27 Nov 2011 12:00:00 +0000
ree-1.8.7-2011.03 :003 > Time.parse('2011-11-27 12:00:00 +0000')
=> Sun Nov 27 06:00:00 -0600 2011
ree-1.8.7-2011.03 :004 > Time.parse('2011-11-27 12:00:00')
=> Sun Nov 27 12:00:00 -0600 2011

So basically, Time.parse always returns the value in the local timezone, DateTime.parse always returns the value in UTC. To get complete compatibility, always use Time.parse. Trust me, I learned the hard way :)

Code Kata #1 - Supermarket Pricing

| Comments

Taken from Code Kata’s by Dave Thomas

The basic premise of this Kata is asking how you would model super market pricing.  What is the price of an item?  What is the cost?  How do you handle price-per-pound?  Buy 2 get one free?  What’s the value of stock? It’s interesting, and I thought I’d take the time to blog through my thought process.

I’d like to iterate over the design and see where it takes me. First task is to represent a product.

1
2
3
4
5
6
7
8
9
10
11
class Product
  attr_accessor :name
  attr_accessor :price
  attr_accessor :quantity

  def initialize(name, quantity, price)
    @name = name
    @quantity = quantity
    @price = price
  end
end

Basic enough… But the :price element can’t simply be a float… no it’s it’s own object… let’s look at that closer

1
2
3
4
5
6
7
8
9
10
11
class Price
  attr_accessor :amount
  attr_accessor :unit # nil, :pound, :oz, :box, etc
  attr_accessor :multiple # defaults to 1, enables '3 {units} per {amount}'
  attr_accessor :num_free # defaults to 0, enables 'buy {special} get 10 free!'
  attr_accessor :special # defaults to nil, enables 'buy 3 get {num_free}'

  def initialize(params={})
    params.each {|p,v| send("#{p}=", v)}
  end
end

At first, this looks overly complicated, but it allows us to store the exact input and calculate off of that. We never want to store $0.3333333 / orange when the user enters 3 for $1–that would make our rounding happens at the EARLIEST possible moment, rather than the latest. We also want to enable flexible definitions of what costs the amount specified, thus you could say 0.99/pound, etc. There should be some units that are known, and others that are simply treated the same a nil (or /each). I’m not thrilled with the num_free or special yet… maybe those will factor themselves differently as we go forward.

So what can we represent here… let’s set up some examples:

1
2
3
4
apple = Product.new "apples", 200, Price.new(:amount => 1.99, :unit => :pound)
soup  = Product.new "soup", 100, Price.new(:amount => 1.00, :multiple => 3)
oreos = Product.new "oreos", 50, Price.new(:special => 4, :num_free => 1, :amount => 2.98)
bread = Product.new "bread", 25, Price.new(:amount => 1.69)

There’s a couple things about these that I want to refactor as I’m going… I want the price to be a bit more readable… like:

1
2
3
4
apple = Product.new 200, "apple", :at => 1.99, :per => :pound
soup  = Product.new 100, "chicken noodle soup", :at => 1.00, :for => 3
oreos = Product.new 50,  "oreos", :at => 2.98, :buy => 4, :get => 1
bread = Product.new 25,  "bread", :at => 1.69, :per => :loaf

That’s what I’d like. It reads straight across. You can represent most things here… so we’ll refactor “Price” and “Product” to look like that:

1
2
3
4
5
6
7
8
9
10
11
class Product
  attr_accessor :name
  attr_accessor :price
  attr_accessor :quantity

  def initialize(quantity, name, price)
    @name = name
    @quantity = quantity
    @price = price.is_a?(Hash) ? Price.new(price) : price
  end
end
1
2
3
4
5
6
7
8
9
10
11
class Price
  attr_accessor :at
  attr_accessor :per # nil, :pound, :oz, :box, etc
  attr_accessor :for # defaults to 1, enables '{for} {per} per {at}'
  attr_accessor :get # defaults to 0, enables 'buy {buy} get {get} free!'
  attr_accessor :buy # defaults to nil, enables 'buy {buy} get {get}'

  def initialize(params={})
    params.each {|p,v| send("#{p}=", v)}
  end
end

There! Much better! Now how about being able to call “cost” for a specific quantity of something. Should it be on the “product” or the “price”? They are closely related, but the product is what needs the call, most likely delegating some of the calculation to the price. Let’s set up “Price.of(n)” and “Product.buy!(n)” Product.buy!(n) will actually decrease the quantity we have in stock.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Price
  # ...
  def of(quantity, unit=:each)
    quantity = convert(quantity, unit)
    (quantity / for) * @at
  end
end

class Product
  def buy!(n)
    @quantity -= n
    price.of(n)
  end
end

This continues to be tougher and tougher, but I’m getting the idea. This would be great for a TDD driven exercise. I’d like to do the timed Kata like Corey Heines does – to music even :)

Enough for this Kata. Time to move on to Kata #2.

Scary Complicated or Richly Awesome?

| Comments

When you look at a new piece of data, most of our initial reaction is in relation to the complexity of that data. Usually this scares me, but after you get to know the data, the more the merrier! What was scary becomes rich and awesome.

How do we move from scary complicated to richly awesome? Comprehension, comprehension, comprehension. And what is the best way to grok something like that? Dive deep into the guts of the code or the task and find out why the data is there and what it does. Why was it modeled that way? In what way could it have been modeled different? Do I have the power to change it? Is it a good thing to change it? Do I understand the system fully enough to see the richness of the data and of the model itself?

In the spirit of “Practice, Practice, Practice” – pick an open source project, look at the model, figure out what all of it does and how you would do it differently, more simply, more robustly, with better error handling, with fewer models.  Grok and regrok.  Get used to the FEELING of comprehension.