Zee Spencer

Zee. Software Developer. Educator.

Subscribe to my Newsletter

My newsletter is a weekly-ish set of interesting links and a short essay. The essay may be about programming, design, technical leadership, or anything that strikes my fancy.

Not sure? Read the archive.

Choosing Between Web UI Tooling and Libraries

Building high quality software in a small team requires thoughtful application of both soft and sharp focus. As primarily a back end or systems engineer, I rely heavily on UI tooling to offload cognitive overhead without sacrificing design quality.

Posted on May 30, 2020. About

Drift Work, Shift Work

Over the years, I've heard many ways to frame the tradeoff in work conditions that optimize contributors' work productivity and managers' work productivity. The most popular being "Maker schedule, manager schedule." While I agree that some kinds of work are best suited to specific work conditions, I'm unconvinced a manager versus individual contributor framing is helpful when attempting to determine how to structure my workday.

Posted on January 8, 2020. About

2019 Year in Review

In 2018, I set out to establish habits that made me physically, economically, and mentally healthier. It's been tough, but worth it. And it gets easier every day.

Here's the metrics I've used to guide me, the goals I set to improve those metrics, and where I am now.

Posted on January 1, 2020. About , ,

How Kiera and I Merged (some of) our Finances

Having been with Kiera for going on 4 years now; and having lived together for 3 of those years; It seemed a bit unnecessary that we maintain separate budgets for shared resources like groceries, rent, utilities, streaming media accounts, etc. We’d cobbled together a “I‘ll pay for Blue Apron if you pay for the CSA” form of spreading of fiscal responsibilities, but that was getting more and more complicated and difficult to balance to ensure an equitable split based upon our respective incomes.

Posted on April 17, 2016. About ,

Defining My Dream Job

About a year ago I got back into freelancing and started building a small, distributed development studio. While I enjoyed the freedom and the people; I couldn't sustain the constant sales cycle and discovered management and operations is a recipe for burnout for me. My constant anxiety over payroll, bookkeeping and cash flow was debilitating.

I could write in depth about what I've learned about myself and running a business over the past year; or describe the agony of laying off good people who may struggle to find new work due to systemic bias; or tipping into depression due to a combination of burnout and the erosion of my self-confidence. But instead I'd like to look forward. It's less painful.

Posted on August 3, 2015. About ,

Effective Code Critique

Code review gets a bad rap. People worry that code reviews slow teams down, create conflict between team members, or disempower team members by taking away decision making authority.

I believe these concerns are anti-patterns that indicate a team is using code review for criticism as opposed to critique. What's the difference? Critique is focused on specific parameters, where criticism is unbound.

That said, many programmers are unclear how to perform judgement free code reviews. The following are a series of suggestions which may help move code reviews from criticism to critique:

Posted on July 26, 2015. About ,

A Pattern For Distributed Retrospectives

Well-facilitated, compassionate retrospectives (the practice of taking time to discuss how to improve the effectiveness of a team) are, in my experience, the core differentiator between a gelling, high-performing team and a team that struggles to get things done.

Now that I work primarily on distributed teams, I've found that retrospectives are a touch harder. They lack the high-bandwidth feedback of body language that can tell you early on when someone is getting upset or has something to say but isn't quite ready to say it.

Posted on February 15, 2015. About ,

The Rationale Behind Testing

Tests are use cases.

They illustrate how to use the code they're testing.

They provide examples of how the code works in a given context.

They describe the code's behavior.

They highlight pain in how to use the code.

They expose complexity in our code and the business domain.

When they notify us the code no longer behaves as specified? That's a bonus. Not the goal.

When we test, we get critical design feedback.

Posted on February 12, 2015. About ,

When To Hire Apprentices And Junior Developers

As bootcamp-esque educational programs train more people on the baseline skills to contribute to a software project, companies are learning how (and how not) to integrate these lower-cost, less experienced developers with their teams. Frequently, these companies hire these less-experienced, single-skilled individuals as "Junior Developers" and throw them at a project.

While this has some level of success, savvy companies are turning to apprenticeship.

Posted on February 2, 2015. About ,

Branding Inception: $2,000 - CLOSED

Zinc is a recently incorporated business focused on technical team training, end-to-end product development, and technical management consulting. We are investing in a solid foundation for our branding. To do so, we are looking for a designer to provide logo design, typography choices, and color selection services.

The resulting brand will reflect the following values:

  • Simplicity
  • High-quality
  • Thoughtfulness
  • Feedback-driven

Posted on January 26, 2015. About ,

Effectively Onboarding Junior Team Members

It's no secret there is a growing demand for technical and creative skills and that our educational system is struggling to provide the skills to deliver useful, working, modern products and services. This is further exacerbated by our industries unwillingness to look beyond a certain archetype.

Companies are beginning to realize what science has told us for years: framing the problem effectively is the best way to encourage others to solve it and are responding by investing more heavily in employee training.

Posted on January 13, 2015. About , , ,

Running Tests Across Multiple Ruby Versions With Rbenv And Make

When writing gems, we frequently want to verify behavior across a variety of ruby versions. While this is possible with travis ci, running microtests before pushing shrinks the likelihood of breaking the build.

My objectives were to:

  • Run tests against different ruby versions in parallel. I've got all these cores, why not use them?
  • Auto-run tests on file system changes.
  • Commands must be discoverable with tab-completion.
  • Adding additional versions must be relatively painless.

Posted on January 6, 2015. About

Migitating Anxiety On Software Teams

Software development is a creative pursuit. It takes intense focus as well as time away from a problem to for subconscious work. Both of these cognitive modes are debilitated by stress and anxiety.

A major source of anxiety is uncertainty. Uncertainty is almost always deeply personal, and may be about many things:

Posted on December 7, 2014. About , ,

A Year In Review With A Walking Desk

For the past year or so, I've been doing most of my computing at a walking desk. When I tell people this, they immediately ask "But how?!" or confidently declare "I wouldn't be able to walk while working!"

While I was a bit skeptical at first, I find a walking desk fits quite nicely into my work habits. I start the day with a mile or so walk, followed by sitting and/or standing until lunch. After lunch I sit for a while, then switch to walking. On a good day, I walk about eight miles. On average, I tend to walk two to four miles a day.

Posted on November 30, 2014. About ,

Getting Past Junior

Junior developers make complex solutions for simple problems.

Average developers make simple solutions for simple problems and complex solutions for complex problems.

Senior developers make simple solutions for complex problems.


Posted on June 27, 2014. About , ,

The Chef's Tale

Once upon a time there was a Chef. This Chef was sought by all of the rulers in the land to cater their feasts. The Chef was ferried from castle to castle; delighting all for whom they cooked.

One day, a pair of scullery workers asked The Chef to tell them the secret. "My children," The Chef replied, "I have no secret. I wake up each day. I plan what I will make. I make it. I review how it went. I learn when things don't go well, and I learn when things do.

"But surely," one child contended, "surely your renowned and creative dishes must have a secret ingredient! Perhaps dust of a unicorn horn? Dragons blood? Fairy hair?"

Posted on June 25, 2014. About ,

The Vim Lovers Guide to Editing Clojure

I've recently started a Clojure gig, which has a pretty emacs-oriented language ecosystem. Emacs uses Cider and Paredit to make it super easy to:

  1. Move parenthesis around S-Expressions (aka 'slurping' and 'barfing')
  2. Access a Clojure REPL
  3. Surround lines, words, etc. with parenthesis, braces, brackets and quotes

Unfortunately I don't really know emacs and would rather focus on learning a language than an editor; so I set out to find vim equivalents.

Posted on December 5, 2013. About

Designing A Personal Learning Plan

Plans are worthless, but planning is everything. Dwight D. Eisenhower

We all have different paths along the long road, and it's often difficult to find the best path. We have different goals and different constraints. Some of us want to specialize in consumer-facing mobile apps; others want to rethink the cryptographical underpinnings of our networking protocols, and still others want to write code to provide a safe driving experience for those of us who plummet down the highway in a metal container going 80 miles an hour.

This is OK; there's tons of room for different passions in the technology field.

Posted on November 19, 2013. About ,

Fear Not Your Ignorance

Ignorance is a blessing. An opportunity.
Ignorance is where possibilities are boundless.
Don't fear it. Embrace it.
Explore the unknown.

Posted on November 12, 2013. About

Structure and Space

First we shape our buildings, thereafter they shape us.

I first heard this phrase from my friend and colleague Davin Granroth. While the phrase may originally have been meant literally; I prefer a more allegorical interpretation.

Posted on November 9, 2013. About ,

Agency, Society, and Invention

I've become convinced a life well lived requires a high level of personal agency.

I believe this not from rational introspection or a position of moral highground; but from noticing the things which make me happy or sad, bring me joy or rage, or drive me to engage or withdraw.

Posted on October 29, 2013. About ,

Back to Codin'

The last 9 months have been some of the most amazing, fullfilling, enjoyable months I've ever had.

I've been lucky enough to teach nearly 150 hard working, passionate people the basics of development and help launch their career in a field I love.

This has consumed every ounce of my energy, so I'm looking forward to taking time to recharge, relax, and build some software.

Posted on October 25, 2013. About ,

Splitting codebases

As programmers, we split our code along what job those bits of code do for us. We pontificate about whether MVVM or MVC or another pattern is the appropriate way to build an app for the given language, environment, or problem domain.

This is valuable! Adaptable code knows little about other parts of the system, and good application design patterns guide us to writing adaptable code with little effort.

I am curious: how does slicing code along the job code does for users impact how we build software?

Posted on June 2, 2013. About

The Learn Startup

A long time ago, in an industry far far away, there were two competing production models: the assembly line and the master craftsmen.

The master craftsmen hand built each and every machine. Painstakingly ensuring it was beautiful and functional. Each machine was resplendent and tuned to perfection, but it took days to build one.

Posted on May 13, 2013. About , , ,

Begin Again

Professions are complex. From outside it looks solid.

Entrepreneur. Lawyer. Designer. Accountant. Developer.

Once we dig in we discover its diversity. Subtle differences become stark contrasts.

We discover, explore, and absorb skills and ideas one after another.

The parts coalesce. Patterns direct our actions. We recompose our thoughts and behaviors.

Posted on May 5, 2013. About ,

The Windsurfer

She chrouches, alert and ready.
Waves crash across the bow.
She clenches the mast tightly
She furrows up her brow.
Winds roar with fury
Waves whip to foam
All other beach-goers
Turn their faces home.

Posted on April 13, 2013. About , ,

Introducing jekyll-cdn

I extracted my jekyll plugin for cache-busting from my blog into a gem, jekyll-cdn! The main feature is a set of Liquid filters for getting the right asset_path, stylesheet_path, and javascript_path for the environment you're building.

It's super light weight, provider agnostic, and doesn't require an asset pipeline. Have fun fellow jekyll-lovers!

Posted on March 23, 2013. About

Choosing Kindness over Condemnation

It's easy when hurt to lash out.
To crush those who caused me pain.

It's hard when hurt to reach out.
To comfort those who caused me pain.

When I choose to be kind, I am forgotten.

When I choose to condemn, I am remembered.

I broker my humanity for a moment of hate.

I trade my dignity for a flash of pride.

Posted on March 21, 2013. About ,

Gertrude the Giraffe

I have a small menagerie I take wherever I go. One who has accompanied me since I was a child is Gertrude. Gertrude is a giraffe with a long, beautiful neck with spots which spell four words: Guess, Google, Grab, Go.

When I get stuck Gertrude reaches up with her long neck and plucks a leaf out of a Guessandtrythis tree. She drops it in front of me and prods me until I pick it up. With each guess I gather information to help us make another, better guess.

Posted on March 12, 2013. About , ,

A Caveat When Hosting a Static Site on CloudFront

I recently experimented with hosting my blog on CloudFront. While this was great for performance it caused a few issues.

Cloudflare does not translate /foo to /foo/index.html, which makes perfect sense for performance; but causes problems if you depend on the server to follow that lookup pattern.

To fix this I use S3 for zeespencer.com and CloudFront for assets.zeespencer.com and the jekyll-cdn gem to provide Liquid filters so switching between local testing and hosted is a snap.

Posted on March 3, 2013. About


Last year was fantastic. I started my own business, helped three startups get off the ground, learned a ton about working with distributed teams, and fell in love.

This year is even more exciting! I signed on with DevBootCamp where I'll help hundreds of people begin their programming journey! Talk about fun!

While I was initially leary of boot-camp style developer training DevBootCamp won me over. Not only do they teach practical programming skills they also teach:

Posted on February 19, 2013. About , ,

Grind Young

I hear your heart beat from all that caffeine
Oh, what a shame there's not more in your bloodstream
So while you're here in my cafe
Let's make the most of the beans that we're gonna grind young

We're gonna grind young
We're gonna grind young

Let's make the most of the beans like we're gonna grind young
Let's make the most of the beans like we're gonna grind young

Posted on February 17, 2013. About

Using Nil Effectively

We seem to use nils in place of a default return value in a function. Say you wanted to write a function that splits a string on its commas:

def nil_split_on_comma(string)
  return nil unless string.include? ","

While this seems reasonable it can have some unfortunate side effects:

p nil_split_on_comma("asdfqwer").map(&:length)

Woops! Undefined method map for nil class! Let's try again!

Posted on February 17, 2013. About

Now I Know That Love Is Blind

Now I know that love is blind
In the dark your smile shines.
My heart is stolen and I feel fine!
Why is organ harvesting a crime?

Posted on February 14, 2013. About

Two Lumps of Clay

Two lumps of clay were bought by a potter and set on her windowsill to soften in the sun. The first was terrified of being prodded, poked, and shaped. "I don't want any part of this!" He said, "I'm a good piece of clay! I don't want to be a pot!" and he hardened himself in the noon day sun.

Posted on February 10, 2013. About ,

Point Victor

There was a young lad named Rictor
Who gloated he was the Point Victor
But the cards he'd "completed"
Had bugs left untreated
And rejection befell poor young Rictor

Posted on February 10, 2013. About ,

Ambiguity In Code Is an Opportunity to Refactor

There's a common design principle that states "Design the system to prevent errors from occuring." Lean manufacturing calls this Poka-yoke. Interaction design calls these [forcing functions](http://www.interaction-design.org/encyclopedia/forcingfunctions.html)_.

Since a much of the time building software is spent reading code, it's important to decrease the amount of errors in understanding while we read.

Posted on February 1, 2013. About

What Mom and Dad Need to Know About the Rails Security Exploit

Dear Mom, Dad, Gramma, Brothers, Aunts and Uncles

I've got some bad news. You may have some work to do to keep your private information safe and prevent people from being able to impersonate you on the Internet.

As you know, I'm a computer programmer. Or a nerd. Or whatever. Essentially people give me money to sit on my butt and get fatter. Yes Mom, I know I haven't called in a few weeks. I'm sorry. Anyway, my people have really let you all down right now.

Posted on January 31, 2013. About

I sense a pattern

From curiosities, interest.

From interest, desire.

From desire, passion.

From passion, thoughts,

From thoughts, actions.

From actions, habits.

From habits, self.

From self, curiosities.

Posted on January 31, 2013. About ,

The Ruby & Symbol

& is a powerful ruby operator, when you use it as a unary operator it has two main use cases:

The most common is to pass an object as a block to a method, like this:

[1,2,nil, 3].reject(&:nil?)

This calls #to_proc on the symbol :nil?, converts the result into a block, and passes it to the reject method. A line by line breakdown looks something like this:

[1,2,nil, 3].reject(&:nil?)
[1,2,nil,3].reject(&(proc = :nil?.to_proc))
[1,2,nil,3].reject { |e| e.nil? }

Posted on January 30, 2013. About

Build a Command Line Remote Pairing Setup

Over the past couple years I've done a bit of remote pairing. When I need a GUI everything is pretty straightforward: Join.me for screen/keyboard sharing and iPad with Skype or Google Hangout for video calls. This is pretty bandwidth intensive and can be slow, so I'd rather keep as much as I can in a terminal.

Posted on January 29, 2013. About

Building Communities of Empowerment

Recently I sat in on a conversation between two people I respect. One declared empowerment is an individuals choice. We choose how to respond to situations and we can choose to remove ourselves from unacceptable situations.

The other stated empowerment requires us to have support from our community. It needs structures in place so that negative situations are reduced and positive situations are increased.

Posted on January 13, 2013. About

We Are Better Than This

Let me start this off by saying I'm furious. I'm furious at my gender, and my 'professional' community.

Maybe you haven't seen Iris Classon's recent blog post about her stalker, but here's the gist: she's been programming for a year and a half and she is already experiencing the worst of us. Our sexism. Our selfishness. Our lack of decency.

Posted on December 20, 2012. About

Keeping Space

While at Devbootcamp last week I was introduced to a new phrase by an instructor. I asked how intensely draining his job must be, and he remarked that his wife is amazingly good at "keeping space" for him. I didn't grasp what he meant, so I asked him to clarify.

"Keeping space," he said, "is when my wife gives me a safe haven to release the pent up emotions from spending all day investing myself in the students here."

Posted on December 12, 2012. About ,

In Pursuit of Excellence

Excellence is not only about the task at hand.

  • It's about treating others well
  • It's about accepting criticism
  • It's about knowing yourself

Excellence takes commitment.

Posted on December 2, 2012. About

Simplicity Wins

Occam's Razor applies to your business plan.

Occam's Razor applies to your design.

Occam's Razor applies to your code.

Stop adding blades; dammit.

Posted on November 29, 2012. About ,

The Proud Ants

Once upon a time there was an ant colony. It wasn't a very big colony, but it had the best hunters, builders, and nurses for miles around. For many seasons, the colony prospered.

Posted on November 23, 2012. About ,

Why I Don't Use Aliases

The difference between an amateur and a professional is their capability to execute consistently in a variety of situations.

How dependent are you on your tools, environment, and configuration?

Posted on June 20, 2012. About

When to Reject and Accept Work

No matter how well you define what should be done you will always wind up with work that isn't quite right. In these situations you have three courses of action:

  1. Reject the work and provide feedback.
  2. Accept the work and add new work items.
  3. Accept the work and ignore its imperfections.

Posted on April 15, 2012. About ,

Coding the Distance

Reluctantly crouched at the command line
Keyboards clicking and clacking in time
The green bar flashes, the vim pops up
Churning, and burning, they push changes up
They deftly maneuver and regex to rename
Fingers flying fast keyboards in flame
Reckless and wild, they commit and they push

Posted on February 26, 2012. About

Breaking Up With Backbone

Dear Backbone,

It's been fun. We've had some incredible times together. But I just don't see us working out.

Don't get me wrong, you have some nice features, your code base is relatively clean, you have good test coverage, and features don't change drastically between releases.

Posted on February 14, 2012. About

Finding Flow in Practice

I spent 5 hours practicing visual design.

I never picked up a pen.

I used a more familiar, less efficient tool.

It kept me focused.

Had I tried to a pen I would not have lasted 10 minutes.

I need to become more comfortable with pens.

Posted on January 14, 2012. About

Talking is Hard

I am an external thinker.

When I write, I feel the words.

I touch them.

Once I see them, I know they are not the words I want

So I reshape them.

When I talk, whatever comes out is out.

No editing. No revising.

Never the words I want.

Posted on December 30, 2011. About ,

Confessions of a Shitty Pianist

Once I practiced daily, studied theory, explored composers and genres, and wrote my own music.

I became a badass pianist.

Then I stopped practicing, experimenting, exploring, and creating.

Now I'm a shitty pianist.

If we rarely practice, study, explore, or create we are not exceptional.

Posted on December 29, 2011. About ,

Judging Code Simplicity Fit It Through The Tube

We coders have all kinds of definitions of simple code. To some, simple code is code they understand and read easily. Others believe simple code follows the coolest, most appropriate design pattern. Some say simple code has the fewest characters.

Extreme Programming tries to settle that debate by offering four qualities of simple code: testability, browsability, understandability, and explainability.

Posted on April 25, 2010. About