Starting out: A user’s guide to getting started.

Brendan Burns
13 min readJun 13, 2016

I’ve started a number of things in my life. Many of them, including that one time as an eight year old when I climbed up into a tree with a bunch of 2x4s and some of nails, were poorly planned endeavors that required a fair amount of *ahem* “iteration.” But over the years, I’ve learned a few lessons, mostly the hard way, about the process of starting something. As I set forth to yet again start something new (in this case this blog) I thought I’d write them down in case they’re useful to someone else. Standard disclaimers apply. Your mileage may vary. Past results do not predict future outcomes. The surgeon general indicates that reading this on a tiny screen in a dark room may cause eyestrain.

Getting started.

It’s hard to start. There are many names for the causes: writer’s block, fear of the blank page, analysis-paralysis, etc. The thing is, what you start with is never going to start out as awesome as the thing you have in your head. And no matter how much you love to build, building the thing is never going to be as fun as imagining the impact of the thing will have once it’s built. Even starting this post took me longer than it really should have because of exactly these reasons. But of course, if you never actually begin, you never finish and that great idea and all of its impact are vaporware.

However, once you get going, once you lay down that first file of code or the first line of text, suddenly it flows, because suddenly there is something there to build on, something to improve. And of course, one of the first things to realize is that that first thing you do is going to suck. It’s going to feel terrible, nowhere near the thing you’re aspiring to build. The path is going to feel like forever, like it’s never going to get to the destination. But once that first step is taken, you’re on your way, and each step is easier, and each interim product sucks less. Huzzah for incremental improvement.

So let’s say you’re there. You’ve got your favorite editor open, but you keep checking social media your email or the news, desperately hoping for something to draw your attention and require that you do something, anything other than start. How do you work through it?

Ask the right question.

Years ago, I was setting out to train for a marathon. But the weather in Seattle, especially in the winter, is not exactly encouraging to the idea of going for long distance runs. As I stood on the porch, staring down a twenty mile run in the rain, I would ask myself: “Do I want to go running?” and the answer was a resounding “No.”

It turns out, of course, I was asking the wrong question. The right question was: “Do you want to run a marathon next fall?” The answer to that was a resounding “Yes” and of course, it implied an affirmative answer to the earlier question as well. Remembering to ask the right question can make all the difference between starting to run and standing still.

Commitment devices

Numerous times when I’ve been on the verge of starting, but not yet started, I have deliberately promised a live demo a week in the future, with not a single line of code yet written. This demo is often promised to an executive or a team meeting. I’ve promised to give conference talks about ideas that I only have just begun to think about, with no clear thesis or concrete notion beyond the abstract.

Am I crazy? Overly confident? No. These are examples of commitment devices, and I’m using them strategically to ensure that I start a project. Asking the right question (above) is about finding the right intrinsic motivation to get started. Commitment devices are about artificially creating an extrinsic motivation to get started. It’s super powerful. Your boss may have given you a great performance review if you never did the demo, but once promised, I guarantee your review is going to suffer if you don’t deliver. Promising things that aren’t started, but really need to be started, is a fantastic way of focusing the mind on delivering.

Staying Moving

Ok great, now you’re moving, but inevitably the distraction will come. The pager will go off, the cat will need to be fed, someone will share that next viral video. If getting started is the hardest thing, staying moving is the next challenge, and staying going is necessary, especially early on, to turn initial momentum into a habitual ritual.

Find the dopamine spot

For every single thing I’ve ever developed, I’ve always had a complete program within writing the first 500 lines of code. Why? It’s not like this program did much. Often times it just printed something, or just called some library routines and ensured they didn’t crash. But the thing is, just doing something is enough to trigger my dopamine response. Poke it and it wiggles. I’m having an effect. “I’m doing something” my mind shouts, and the dopamine flows. And that’s enough to keep me going. Enough to make me make it do something more. “That something’s not enough, it needs to do something more.” I don’t know if that’s enough for everyone, but I guarantee that something is. Maybe it’s a green dashboard, the perfect test, generating documentation for a library, or counting the words in a chapter. Find your dopamine spot and orient your development around it. Make sure you get incremental rewards at the right intervals, and you’ll never stop building. Hey, the slot machine manufacturers use psychology against us, isn’t it time we used it constructively?

Take breaks

Though most projects are truly marathons (or longer) I find it’s better for me to organize the actual activities into a series of short, intensely focused sessions, rather than a long drawn out slog. Often times I’ll get into the task at hand: Writing a new section in this blog, a new piece of code, fixing a flaky test. My focus is deep, my mind is entirely devoted to this task. I’m working efficiently and effectively.

But the longer I spend on that task, the more my mind drifts, the less efficient I become and the slower I work. It really depends on the task and my mental state how long this is. Sometimes it’s twenty minutes, sometimes it’s two hours, but in any case, I’ve trained myself to recognize when my distraction index is getting too high. And when it does, it doesn’t mean it’s time to re-focus, it means it’s time to take a break. Time to go for a walk, to get a cup of coffee, to watch that cat video my co-worker has been laughing about for an hour. Whatever it is, embrace the distraction. Be as focused on the break as you were on the task, and you will be rewarded with renewed focus on your real task when you return to it.

What to do

Ok, now you know how to start and how to keep going. But wait, what should you actually be doing? The first, and most important thing, is to actually understand what it is you are trying to do. There are two important things to realize:

  • There will never be an easier time to adjust your trajectory. Simple geometry tells us that the farther you get from the origin, the longer the translational motion caused by angular differences.
  • You’re probably going to choose the wrong direction, but you can try to get it mostly right.

Put together these two points may seem fairly contradictory, but the truth is that they’re complimentary. The first says: This is a good time to try to get the things you known you need in place, and generally understand where you want to go. The second says: Don’t sweat it too much (see analysis-paralysis above).

So what are you trying to do?

What is it?

What kind of thing are you trying to build. Is it a useful library? A new application? Is it web or mobile? Is it a service? Infrastructure to help others build services? It seems like an obvious thing that you’d need to know to start something, but often times we start with a vague idea: “Networking in containers seems like it has a bunch of open problems” and we don’t even necessarily know what we’re trying to build. Figuring that out is a good place to start since it shapes a number of the decisions about what to do.

Lifespan

How long do you expect this project to last? Class work that lasts a week and you never touch again has a very different profile of priorities and requirements versus a project that you expect to live with for many years. In the case of a 1-week project, focusing on speed, at the expense of documentation and testing, probably makes sense, since it’s less likely you’ll forget much over the course of a week. In the case of a many-year project, the cost of spending a week or two setting up testing infrastructure at the beginning is a trivial investment against the much longer lifespan.

Audience

Who is the audience for this project? Is just a hobby for yourself? A web application for your household? A library you expect (hope?) lots of other developers will use? Understanding your audience allows you to focus on the pieces that are necessary. If it’s just you, comments in the code are likely sufficient documentation. You don’t need to think about SEO or a web site, if you wrote the code. If you think (or hope) that lots of other developers will start using this library, then documentation (and SEO/discoverability of that documentation) are of critical importance since that is how developers will find out about you and how to use your code. LIkewise, applications built for others need to understand their lifecycle and have much richer end-to-end and integration tests, to ensure against regressions that impact end-users. Understanding the audience for your project is another guide to identify the places you should focus on when setting your initial trajectory.

Product

Wait, didn’t you already ask about this in “What is it?” above? No. I asked what you think this is. Now I’m asking what your users think it is. To often, we develop technology for the sake of technology without asking ourselves “why would anyone ever want to use this?” “how are they using it to improve their day-to-day lives” “what is the value-prop of the thing I’m building?” You can have crystal clear clarity about what you’re building, what its lifespan is and who its audience is, but if you aren’t building a compelling product for the intended customer (even if that’s only you) then you may as well not even start. You’re not starting something useful, you’re just passing time.

Ok, how should you do it?

All right, you’ve figured out how to start, how to keep going, and what it is you’re actually building, what about the nuts and bolts of how to actually build it?

Version Control

(well duh) but the number of times that I’ve hacked something up without running ‘git init’ first is stunning. And even when I run git init, the number of times I’ve wanted to revert a recent change and realized I’d never been committing is equally stunning. Always be committing, for everything. Oh and back it up somewhere too. Git is great like that, you can tar the repo up and copy it into persistent storage somewhere and recover from it later. Or if you’re planning on open sourcing (and why wouldn’t you for most things) just throw it up on github. It doesn’t matter if it’s barely started, I guarantee the users of github won’t judge and maybe you’ll even get a pull request to fix some bugs.

Unit Tests

There’s this thing about unit tests. I 100% believe in them and their importance, but I hate writing them until it’s time for me to refactor my code. When I’m refactoring they’re the thing that keeps me sane and confident. Especially important if you are writing libraries where compatibility is import. Or applications where you ship software and it needs to work. Or services where people expect reliability, or infrastructure where people need confidence in your infrastructure. (So, everything.)

Also, what you don’t realize today is that unit tests make it easier for others to come collaborate. They often provide the only example code for calling a library. They give other users the confidence to make changes, send PRs and not be responsible for breaking the software.

But you need to make them real. This means wire up CI/CD, and not just CI/CD for the trunk, but CI/CD for every pull request. This helps build community too, because you don’t have to worry about some external contributors pull request breaking your code. While you’re at it, you probably want to set up a submit queue. Having humans merge code is bad news. Automate yourself out of that job. Require unit tests for every PR. Measure and report coverage. You should probably be outputting JUnit XML. (yes, even if you’re coding in Go, Python or Node). Like it or not, JUnit XML is the lingua franca of test visualization in Jenkins. Get to know Jenkins. There are a million different plugins, but once you install them it can work magical automation for you. Yes, this is painful. Yes, building things is more fun. But remember what I said about trajectory? You’ll have even less fun later when you have to retrofit these things.

Integration tests

Don’t scrimp here. This is the place where the real testing gets done, and yet it’s light enough to run on a single box. Running things on a single box reduces the barriers to contributors (who are in many cases your users as well). It also means that you are more likely to be able to run them for every PR which in turn improves your speed and reliability. When you’re gluing things together to build out the integration test suite, it’s tempting to slam things together into a giant binary and just get it to work end-to-end. This is a mistake I’ve made far too many times. The trouble is, initially with just a handful of tests, this approach seems reasonable and its output is debuggable. But twenty tests in, and it’s just nothing but log spew. Use a real testing harness just like for your unit tests. Yes, it can be harder, but the time you save in making your tests easy to debug will more than make up for it. (oh, and see earlier points about junit XML).

End-to-end (e2e) testing

End-to-end testing differs from integration testing in the sense that it is an even more accurate representation of production conditions. While an integration test runs on a single machine, end-to-end testing is likely to turn up a full stack of machines or containers (though perhaps with fewer replicas and fewer resources).

End-to-end tests are also the thing least likely to be added initially, and correspondingly most likely to add-on at the end. This addition is nearly always ugly and painful, and as a result, end-to-end tests are almost always added into some catastrophic event (e.g. pushing a major breaking change into production) which subsequently triggers a “code yellow” style intervention to add end-to-end tests. This kind of emergency room medicine is both highly disruptive (since it requires a team to stop all other existing work) and also has an effect on culture, since if end-to-end tests are seen as an “add-on” by your development team they are far less likely to be comprehensive (or even added) for every feature.

So instead, set these up at the beginning. I know if barely makes sense, since the product in its initial stages is so simple that they are nearly if not totally redundant with the integration tests, but the longer you wait, the harder it is to retrofit them in.

Document everything

Yeah, I know it’s just you and you know all of your code. Just like you’re sure that it doesn’t have any bugs, right. But what about Bob over there? Bob just joined your team and he doesn’t have a clue. Worse yet, he’s going to bug you while you really just want to be coding. So do Bob and yourself a favor: document your code while it’s fresh in your mind. As mentioned earlier, depending on your expected lifespan, this may not be necessary. On the other hand, code is like a cockroach — hard to kill.

Oh, and use documentation generated from your code. Use godoc, javadoc, doxygen or whatever else you have to generate HTML documentation and ship it with your code. Better yet, host it on your website or github repo. The more people can get into your code more easily, the more users, collaborators and success you will have. In most cases, building a community will quickly pay back the cost in adoption, feedback and contributions.

And while you’re at it, write design documents. Often times the initial use of such sketches is more to clarify your ideas in your own mind, than educate others, but as your product and community grows, they leave a historical record to help bootstrap newcomers to the project. On the other hand, don’t only write design documents (see analysis-paralysis above). I have yet to see a markdown compiler that generates working applications.

Find avenues for people to find you

We tend to think of building software as a technical endeavor, one of design documents, source code and code reviews. But if your project or product is to be successful, you’re going to have to grow. Maybe this is growing users, growing customers, growing an open source community or hiring developers, or maybe all of the above. Regardless of why you are growing, growing requires meeting people and enabling people to find you. If you’re not on social media, get on social media (and while you’re at it, add some standing searches via TweetDeck so that you can monitor what is going on in your ecosystem). Create a Slack or IRC for realtime discussions and feedback. You wouldn’t believe how useful it is to have a standing communication channel and how impressed your users will be when you fix bugs for them in minutes. While you’re at it, go to some meetups, show demos of what you’re working on (see commitment devices above) Above all, be actively engaged, respectful and responsive, it works wonders. Which leads us to…

A final note on culture

This is maybe the most important. The culture and tone you set here will have long term impact on your project. In the first one month, you will effectively have set the tone for your project for the rest of its life. (Worried yet?) In the first few interactions, in the first few people you work with, in every conversation, code review and help session, you are setting the trajectory for how you will be viewed out in the larger world. This is probably the most under-appreciated and yet massively critical points to get right in a project. Idiosyncratic quirks in the first month become pathologic failure points in the first few years.

--

--

Brendan Burns

Brendan Burns is a co-founder of the Kubernetes open source project. He received a PhD from UMass Amherst and BA from Williams College both in Computer Science.