---
type: post
date: 2015-04-21
slug: done-vs-finished
title: Done vs. Finished - On Code Reviews and Learning Languages
---

As part of my yearly goals at work, I've been doing more and more work in Go.
It's a pretty fantastic language, I've found, and fairly easy to pick up, minus
a few little caveats (goroutines took me a bit to wrap my head around).  A lot
of this has been taking place in a little project,
[jujusvg](https://github.com/juju/jujusvg), which takes a Juju bundle and
outputs an SVG representation of that bundle for displaying in webpages such as
[jujucharms.com](https://jujucharms.com).  This was a project I started on a
sprint and have been shepherding through its growth over the last several months
with the help of several members of our team who are more well-versed in Go than
I am.

In particular, a recent branch of mine has brought up a lot of interesting stuff
to think about, especially when it comes to learning a new language and what it
means to be finished.

The goal with [#23](https://github.com/juju/jujusvg/pull/23) was to allow
embedding of charm icons in the bundle SVG so that the diagram was totally self
contained, not requiring any requests to outside assets such as the icon SVGs
through SVG's `<image>` tag.  The main benefit to this is that anyone can build
a bundle diagram and embed it anywhere - a slideshow, a webpage, whatever -
where it will work without network access.  In addition to this, we can now do
some checking on whether or not an icon exists, is really an SVG, and so on.  In
the case of the charm store, we can also embed icons by fetching them directly
from GridFS, rather than over HTTP, which will be a significant speed boost.

Within our projects on the Juju UI Engineering team (and, I suspect, elsewhere
in the company), we utilize a system of reviews required to land code.  In
particular, we require at least one QA, and at least two positive reviews in
order to land any branch.  If there are any negative reviews, they must be
addressed and received positively before the branch can land.

In the case of #23, the process of reviewing stretched out over 21 days and 124
comments, which is exceptionally long for a branch to live in review (we
generally aim to have a branch completed - from start to reviewed to landed -
within one day), but in this case, I think that the reviews helped me to learn
how to be a better Go programmer, and a better programmer after all.

This, I'm sorry to say, felt slightly unusual for me.  I think that the industry
of software development is strongly imbued with "guess culture".  In this
dichotomy, social interaction between actors is divided into either "guess
culture" or "ask culture", which describes the ways in which the actor will act
when confronted with a problem they do not know how to solve.  In software,
you're expected to either a) know how to solve the problem, or b) know how to
figure it out yourself.

This was shown to me early on in an interview question:

> Given a private jet in a hanger, find out how much it weighs.

Answers ranged from "cut it in half again and again into smaller parts until you
can place one on a scale" as a sort of Zeno's Paradox of plane-weighing, to
"fill it with a known amount of jet fuel and fly it until it crashes."

The answer that the interviewer was looking for, however, was "Google it".

I think this is an interesting question when it comes to the idea of ask versus
guess culture.  On the one hand, it points to the obvious solution of "sure,
it's good to be able to solve a problem given limited resources, but don't be
afraid to just ask," but it also highlights, in a simple-minded sort of way,
that you should be able to sort the problem out by yourself without opening
yourself up to criticism by asking what might be a stupid question.

Counter to guess culture, though, is the concept of ask culture, wherein it's
acceptable to ask for help, clarification, or instruction.  There's a lot bound
up with this, though, and the ideas of machismo so prevalent in software
culture, as well as the idea that we should leave university with 100% of what
we need to know in order to be successful, both of which are ludicrous when
investigated with the least amount of scrutiny.

While I scoffed at it early on, I think that Agile methodologies (we follow a
Lean Kanban style) do a good job of subtly encouraging a shift from guess to ask
culture within a team at the very least, and sometimes within a whole company.
The idea behind Agile isn't specifically to provide upper management with
burn-down charts and instant results, but to create an environment where
knowledge-sharing, rather than knowledge-hoarding, is the norm.  A lot of the
other aspects of Agile fall out from that: cross-training, quick turn-around,
daily stand-ups, and so on.

In the case of reviews, the requirement to get two thumbs up and address any
concerns means that a conversation is automatically required between developers.
I think that worked really well for us on this branch, not just because I got to
be a better Go developer, but also because others on the team know exactly how
to implement my proposed API changes, and get to understand just how the library
itself works on a lower level than they might if they just looked at the
example.go file.

The only place we found ourselves stumbling happened to be purely mechanical:
GitHub, while it's great in a lot of respects, did not lend itself well to this
review turn-around.  Other tools, such as Rietveld, allow both inline comments
as well as inline responses, and unified messages back and forth.  With GitHub,
I found myself having to reply to each comment left on my branch with "done" in
order to track which I had responded to in code, which meant that all of my
coworkers got a list of emails containing simply "done" and a link to the pull
request.  Better, I think, to have a single email sent with my replies
addressing each comment once I pushed my subsequent branch.  Again, it's simply
a mechanical thing, and not that tough to deal with, but I feel as though there
are other code review tools out there that work better than GitHub's.

What it really came down to, after all of the reviews, was that I needed to be
more than just productive in Go, I needed to be fluent.  There's a lot that can
be said either way when it comes to coding styles, but there are some objective
benefits to language fluency.  In particular, my approach to fetching icons took
the following path

1. Fetch synchronously, one icon at a time, over HTTP in all cases.
2. Implement `IconFetcher`s for retrieving icons how the user specifies,
defaulting to HTTP
3. Allow fetching icons concurrently using goroutines, using one set of channels
for synchronization and another for errors.
4. Allow fetching icons concurrently using goroutines and
[WaitGroups](http://golang.org/pkg/sync/#WaitGroup) to simplify synchronization.
5. Since concurrency was either on or off, threads could get out of hand, so
allow fetching icons concurrently up to a limit using
[github.com/juju/utils/parallel](https://godoc.org/github.com/juju/utils/parallel),
which vastly simplifies the code overall path of the code, abstracting out a lot
of (but not all of - we're not trying to be magical) the asynchronous patterns.

Each of these iterations was shepherded along through suggestions and code
snippets from my reviewers.  The point being was that I was writing Go code in
order to be productive while not yet being fluent.  Through the help of others,
I was able to step all the closer to Go fluency so that I could make a branch
that did more than just get the job done by any means necessary, but also do
what I needed to in a clean, easy to read, and efficient manner, a perfect
example of utilizing an ask instead of a guess method.  Which brings me to my
last point: done versus finished.

When I first proposed the branch, even though I proposed it as a WIP branch,
knowing that there would be comments, it was technically done.  It fetched all
of the icons needed for a bundle, embedded them in the SVG diagram, and produced
a valid output.  However, it wasn't *finished*.

If we had wanted or needed to iterate on this branch faster than we eventually
did, then I'm sure we could've landed it as-is on each go-around with a
follow-up card created to represent future work.  My activity graph on my
profile might've looked a little more full, but I think that having something
finished was much more important, for a library such as this.  We didn't want to
leave things hanging too long and risk releasing something which wasn't
complete, even if it did what it said on the tin.

The responses that I got on my code review were basically all about that.  It
was a little painful to have a branch lingering for 21 days, but on the other
hand, it's much more satisfying to land something that I'm proud of than
something I feel more like sweeping under the rug.  Through the help of Roger
and Martin, I was able to do that.  Not only was the branch more finished than
it was simply done, I became a better developer in the process, learning more
about what is the Go-ish thing to do specifically as well as what is a good
CS-ish thing to do generally.
