2011
The joy of logs
But a better conceptual model is to treat logs as time-ordered streams: there is no beginning or end, but rather an ongoing, collated collection of events which we may wish to view in realtime as they happen (e.g. via tail -f or heroku logs --tail) or which we may wish to search in some time window (e.g. via grep or Splunk).Work on an app with a couple dozen servers, a handful of databases, and several moving parts and you start to realize that logs are one of your best friends. They're useful for troubleshooting, performance monitoring, and just knowing how your application works in reality, under real traffic.
I’ve tinkered with building deeper APIs for logging within applications and services, but I think Adam Wiggins is on the right path here (not the first time either). Logging should be as simple as possible in applications. All the smarts for aggregating, searching, and extracting interesting information should happen after the data is collected. Using standard out instead of files is a fantastic idea too.
I'm Corgi-internet famous
OCD: Obsessive Corgi Disorder, Kitty putting the moves on my man. Also on Men and their dogs. I’m corgi-internet famous! Photo by Courtney.
Noel Rappin's Advice on TDD
Testing Advice in Eleven Steps. My favorite:
At any given moment, the next test has some chance of costing you time in the short term. The problem is it’s nearly impossible to tell which tests will cost the time. Play the odds, write the test. Over the long haul, the chance that the tests are really the bottleneck are, in my experience, quite small.
All eleven are pretty handy for those like myself who still feel like they have a lot to learn about TDD, BDD, et. al.
Organizing and decoding problems
My favorite sort of problem involves the interactions between individuals, groups of people, and mechanical rules generated by individuals and groups. Speculating on how the rules were shaped by the experiences of the individuals and groups is a fun game to play when presented with a curious set of circumstances. Conversely, my least favorite problems are those generated by the institutional brain damage of certain kinds of groups. Software and systems shaped by regulations and the particulars of monetary exchange are tedious at best.
I find it quite amusing when answers aren’t “clean” and technological systems aren’t the best solution. Often, no amount of analysis and brilliant coding can make an improvement. What is needed is to understand what people do, why they do it, and persuade them to do otherwise.
This brings me to economics, specifically behavioral economics. If you take away all the math, economics is largely about how people behave in aggregate. It’s a useful tool in understanding how to work with systems that involve people. But there’s more to economics than explaining how people interact in markets.
Russ Roberts, in the process of explaining how economics is not useful as a mechanism for answering questions like “did the stimulus work?” or “when will the housing market recover?”, gets to what really interests me about economics and finance:
"Is economics a science because it is like Darwinian biology? Darwinian biology is very different from the physical sciences. Like economics it is a very useful way to organize your thinking about complex phenomena. But it is not a predictive or very precise science or whatever you want to call it."
The crux of the biscuit, for me, is right in the middle. Economics is a useful way to organize an intricate and interconnected problem and figure out how to reason about it. In casually studying economics and finance over the couple years, I’ve come to form a better mental model about how the world works.
Its possible that this mental modeling is what I do when I’m coding. I’m poking how some code works, looking at its inner workings, trying to understand how it interacts with the code around it. I sift through revision logs to see how it got to where it is today, talk to others on the team about the code and why it ended up one way and not another. I’m organizing and modeling the code in my head, building up a model that describes .
Lately, I’ve been describing my work as tinkering with lines of code until numbers appear on the screen in the right order. This is invariably greeted with a comforting-to-me response like “I could never do that”. But I really enjoy this. I’m not just debugging my code; I’m sharpening the way the program is organized in my head. Once I’ve got my head around it, I decode that organization into words, code, drawings, etc.
With programs, there is some system of rules, forces, and interactions which describe how the code works or doesn’t. Economics, too, describes a system of rules, forces, and interactions that predicts how a puzzle of human beings operate. Organizing and decoding these technical and social puzzles is great fun.
Driven to drawing monsters
From my notebook:

get
class method and something about memcached was causing enough trouble to drive me to draw a little monster.
A conversation between fictional engineers in a fictional world
A hypothetical conversation that may have occurred between two non-existent engineers working on the second Death Star in the completely fictional Star Wars universe.
Engineer #1: Hey Bob, I was perusing the blueprints for this “Second Deathstar” this morning. Pretty impressive stuff.
Engineer #2: Thanks Hank. I’m pretty proud of it.
Engineer #1: And you should be! Had one question though. There was something in the request-for-proposals that mentioned some flaw in the previous one where a snub fighter could drop a torpedo through a vent and blow the whole thing up, yeah?
Engineer #2: Yep! Don’t you feel bad for the poor schmuck who made that decision?
Engineer #1: Haha, that’s a good one Bob. So you fixed that right?
Engineer #2: Oh, definitely. All the exhaust ports are small enough the only thing falling in there is a grain of sand.
Engineer #1: Nice thinking! So, my real question is, what’s this giant opening you can fly a large freighter through? And why does it lead right to the station’s giant fusion reactor that sits in a room big enough to fly in circles in said large freighter?
Engineer #2: Oh, that? Well, the passage from that room to the surface is where I’m going to run all the pipes and wiring that I forget about until the last second. I figure once I’m done patching everything together, no pilot would be able to fly through there, even in a snub fighter.
Engineer #1: And the giant room?
Engineer #2: Oh, you know clients. Always deciding they want something really impressive at the last minute. I figured I’d just leave a little extra room in case they come up with something at the last minute.
Engineer #1: Haha, right again Bob. Clients are such idiots.
Simple Ruby pleasures
I think I first discovered the joy of take
and drop
in my journeys through Haskell. But it appears that, since 2008 at least, we have had the pleasure of using them in Ruby too.
Need the first or last N
elements from an Enumerable
. Easy!
[sourcecode language=“ruby” light=“true”] ary = (1..100).to_a ary.take(5) # => [1, 2, 3, 4, 5] ary.drop(95) # => [96, 97, 98, 99, 100]
range = (1..100) range.take(5) # => [1, 2, 3, 4, 5] range.drop(95) # => [96, 97, 98, 99, 100]
hsh = {:foo => 1, :bar => 2, :baz => 3} hsh.take(1) # => [[:bar, 2]] hsh.drop(2) # => [[:foo, 1]] [/sourcecode]
The real magic is when you use take
along with other Enumerable
goodies like select
and map
. Here’s one of my personal favorites amongst the code I wrote in 2010:
[sourcecode language=“ruby” light=“true” highlight=“12,13,14”] class QueryTracer < ActiveSupport::LogSubscriber
ACCEPT = %r{^(app|config|lib)}.freeze FRAMES = 5 THRESHOLD = 300 # In ms
def sql(event) return unless event.duration > THRESHOLD callers = Rails. backtrace_cleaner. clean(caller). select { |f| f =~ ACCEPT }. take(FRAMES). map { |f| f.split(":").take(2).join(":") }. join(" | ")
# Shamelessly stolen from ActiveRecord::LogSubscriber
warning = color("SLOW QUERY", RED, true)
name = '%s (%.1fms)' % [event.payload[:name], event.duration]
sql = event.payload[:sql].squeeze(' ')
warn " #{warning}"
warn " #{name} #{sql}"
warn " Trace: #{callers}"
end
end
QueryTracer.attach_to :active_record [/sourcecode]
This little ditty is awesome because:
- It's super-practical. Drop this in your Rails 3 app, tail your production log, see the slow queries, go to the method in your app calling it, and fix it. Easy.
- It only activates itself when it's needed. Queries that execute quickly return immediately.
- No framework spelunking required. Rails 3's notification system handles all of it. Rails' backtace cleaner gizmo even makes the backtraces much nicer to read.
- It chains methods to make something that reads like a nice, concise functional program.
Enumerable
joy, read up on each_cons
.