Designing a Scalable Deployment Pipeline

Anyone who’s led a product engineering team knows that a growing team requires investments in process, communication approaches, and documentation. These investments help new people get up to speed, become productive quickly, stay informed about what the rest of the team is doing, and codify tribal knowledge so it doesn’t leave with people.

One thing that receives less investment when a team scales is its deployment pipeline–the tools and infrastructure for deploying, testing, and running in production. Why are these investments lacking even when the team can identify the pain points? My theory is that it nearly always feels too expensive in terms of both money and lost progress on building features.
Read more on Designing a Scalable Deployment Pipeline…

Why Estimate Bugs and Chores in Your Backlog?

When we’re running a client’s project using our Atomic Process, our team will assign an estimate of points to each item in the product backlog.

In general, we classify backlog items into three buckets:

  • Features (new or enhancements)
  • Chores (dev work not resulting in tangible product changes)
  • Bugs (fixing unexpected behavior or regressions)

Read more on Why Estimate Bugs and Chores in Your Backlog?…

On Writing Technical Content

During the past few months, I’ve taken on the daunting task of collecting some of the important software development lessons we’ve learned at Atomic over the past decade into a body of writing about the size of a handbook. The goal is to capture the ideas in a way they could be easily shared with a new Atomic developer, so as to build a common framework for having conversations about our dev practices here. We’re excited about this resource, and we plan on sharing it broadly when it’s completed.

While working on this project, I learned a few things about managing time and energy by breaking down tasks, categorizing them, and understanding the environmental and time constraints of each type.

Organizing My Work

Once I had an initial outline and a couple of rough chapters, I created a Trello board to track tasks and filled it with everything I could think of that needed doing. Each task was something that would take somewhere between 30 minutes and 1/2 a day to complete. To avoid distraction, if I was working on one task and realized something else that needed to get done, I’d add it to a backlog list in the Trello board.

Read more on On Writing Technical Content…

Prioritizing Refinements – Choose Wisely

As software craftspeople, we constantly reach for sublime elegance in our work. Just beyond every module rewrite or subsystem refactoring is the paradise of ultimate modularity, configurability, and simplicity — somewhere we never quite arrive.

However, we shouldn’t fall prey to actually believing that given the necessary time to implement every abstraction, refactoring, and re-organization is doing the world any favors. Useful software needs to be used. To be used, software needs to be in the hands of users. To get into their hands, it needs to be shipped.

Most vectors for improvement are only visible once a piece of software is being used by people who didn’t create it. This is the most important point to reach in a software product’s lifecycle, as quickly as possible.

Read more on Prioritizing Refinements – Choose Wisely…

Winter Bike Commuting

I’ve been commuting to work on a bicycle year-round in Grand Rapids, Michigan since 2005. I’m lucky to work at a place that’s so supportive of bike commuting, enabling me to ride in year-round for the past 8 years.

Winter riding, in particular, is what I find most enjoyable. No one should feel that snow, ice, or sub-freezing temps are insurmountable barriers for winter riding. Every morning I check the temp and see a sub-32F reading I think, “YES! No rain!”

The following are a few tips I’ve learned which will hopefully help and encourage you if you’re curious about trying a winter commute.

Read more on Winter Bike Commuting…

Simple Passive Code Generation

TL;DR – Here’s a rake task you can use to easily generate classes:
desc 'generate a class in lib/ and a spec in spec/lib/ for name=underscored_class_name'
task :genclass do
  require 'erb'

  filename = ENV['name']
  raise 'must specify name=underscored_class_name' unless filename
  classname = filename.camelize

  class_file_template = < <-EOF
class <%= classname %>

  def something

  spec_file_template = < <-EOF
require 'spec_helper'

describe <%= classname %> do

  before do
    @target = < %= classname %>.new

  describe '#something' do
    it "should do something"

    ["lib/#{filename}.rb",           class_file_template],
    ["spec/lib/#{filename}_spec.rb", spec_file_template]
  ].each do |(fname, template)|
    if File.exists?(fname)
      puts "skipping generation of existing file - #{fname}"
      puts "generating #{fname}", 'w+') do |f|
        f.write template.result(binding)
Read more on Simple Passive Code Generation…