A month ago, I announced a new blog series called Leveling Up: A Guide for Programmers. This series covers skills you can use to learn faster, more easily, and more strategically as a programmer (and maybe outside of programming, but I’ll stick to what I know). I recommend reading that intro and then coming back to this post, which covers our first skill: setting goals.
Do you have a goal in mind? Or are you looking for more guidance on how to set goals that will advance your skills?
The idea of goals comes with some pitfalls for a self-taught programmer.
Programming is Wide and Deep: Swim with Care!
The first pitfall for a self-taught programmer is the idea of “doneness”—when we accomplish a goal, we consider ourselves done with something. But in programming, there is no “done”—there is always further you can go. Apps need maintenance. Languages and frameworks change. There is always more to learn and more to do. So a broad goal like “learn iOS” doesn’t have an established finish line. That makes it subject to what I call mood metrics: that is, when you’re feeling energized (in a great mood) you think you’re making great progress, but when you’re feeling sad or drained (in a rough mood) you think you’re making terrible progress.
The second pitfall is the rabbit hole. On any idea in programming, there’s always deeper you can go. The iOS ARKit is built on top of the iOS Framework, written partly in Swift and partly in Objective C, both of which compile to C, convert to Assembly, then to machine code. There’s tons of research and open source development around virtual reality, augmented reality, computer vision, and machine learning. So if you start with a plan to learn about ARKit, you could keep going forever. That’s a romantic idea in theory, and plenty of ‘passionate’ programmers will say it’s a good thing. But it’s not a helpful benchmark for you to establish a skill set, and it can prevent you from moving on to other things you want or need to learn.
So how can we short-circuit these two pitfalls?
Workaround: Choose a Project.
Set goals around a project rather than a concept. For example, if you want to learn ARKit, you can build an iOS app that surfaces nutrition information when your camera is pointed at various cereal boxes.
A project offers an established finish line and a way to move forward incrementally until you arrive. And how much of something you need to know is…as much as it takes to get the app working. So if going deeper doesn’t directly contribute to getting something working, it’s not part of this goal. Skip it. You can learn more once something is working. The project gives you a scope in which to work.
We’ll discuss a technique for breaking down a project goal later in this post. But first, an aside…
Your motivation will wax and wane during the learning process.
This chart represents how you may feel over the course of learning a new programming concept:
That dip at about two months important to notice. When you learn something new, you start with a high level of confidence after a few small successes. Those small successes lead to new things: the chance to try out your new knowledge in the real world, or in the context of a project. Outside of its limited initial context, your new knowledge and skills look much smaller. That experience can be jarring, but those obstacles are an important part of the learning process.
Those obstacles—the struggles, the dips in confidence—will be easier to overcome if you see them coming. You will not always feel excited to work, and you will not always feel like you’re progressing. Luckily, the trick is not to stay motivated. It is to go ahead and put in practice time even when you are not feeling motivated.
We’re going to talk a lot more about this. In fact, the next Level Up post is devoted solely to this topic. For now, though, keep it in mind as we return to talking about goals.
Technique #1: Breaking down a project goal
When I was a student and teachers assigned me large projects with eight week deadlines, I would write down the deadline in my planner and then backtrack to figure out how many days I had until the deadline. I’d divide that number of days in half—so for a two month project, that’s 30. I would then write out a list, from 1 to 30, and come up with 30 steps that would take me from having nothing done on the project to finishing the project. I would write one of these steps in my planner on every other day between the planning date and the due date.
That’s a lot of steps for a recreational project, so for your learning projects I recommend a different approach.
Instead, let’s pick a goal for something we’d like to have finished in a few months. Here’s the one I’m doing right now: I want an app that asks people about their values (like environmental conservation, employee treatment, et cetera) and serves them a stock portfolio based on those values.”
I have broken this goal down into some parts, with the hope of accomplishing each in a month or less:
- I want to create an endpoint that accepts a portfolio id and a set of values and stores those values with that portfolio.
- I want to create an endpoint that accepts a portfolio id and serves a collection of investments in line with the values stored with that portfolio (including any calculations with values, ESG metrics, and market caps).
- I want to write a frontend with a form for questions that translate to values for my API.
- I want the frontend to display a series of investments based on the results from the API.
I get to decide what goes into each of these goals. Should the code be test-driven? (Yes—for me. But that’s me.) What’s the stack? (Rails for the API because I know it, and ReactJS for the front end because I want to learn more about it). Do I care about performance? (Sure, but I don’t want to get caught on it). I can change any of these variables to make any one of those sub-goals larger scope or smaller scope for me. That lever is important because it helps me adjust if one of these goals ends up looking like it will take too long.
Now I take the first goal only and break that one down into a weekly goal set.
- Kick off an API app with token authentication and a test framework (this is the first part of most of my API projects).
- Write and implement a database diagram with portfolios and value sets.
- Figure out a minimum viable list of values for a value set.
- Write an endpoint to update a value set with a portfolio id and a list of values.
I take the first week only and break that down into a set of smallest steps forward.
- Launch an app. This particular app will be a Rails app on top of a graph database.
- Get the app under a test framework. I’ll go with rspec for now.
- Make users and a protected resource.
- Put that resource behind token authentication.
- Pass out tokens to users.
Each day I have available to work, I’ll try to complete one of these smallest steps forward. Provided I accomplish my goal for the week by the end of the week, I spend a few minutes breaking down the next week only. I don’t break down the whole thing at once because I gain information from each week that helps me better estimate the next week: estimating a long way out at once tends to magnify my inaccuracy as an estimator.
If I don’t accomplish my weekly goal, I have the freedom to reset my weekly goals to better reflect what I can get done in a week. We’ll continue to go through the project each week, estimating just one week at a time.
As I accomplish my smallest steps forward, I’ll make a commit for each. In my example, each smallest step forward encompasses measurable progress toward a feature, but once I’m in less familiar territory than “start an app” I’ll often go with even smaller steps for each commit:
“read about this new technique and copied the example code into my repo”
“modified the code for my use case”
“changed this variable to experiment with how it works.”
We do these tiny steps to reflect each small amount of progress, which helps us progress even on days when we don’t have much time or energy to work.
You can use your notebook to set and track these goals as you make them.
Notebook Exercise #1: Breaking Down Goals
- Write down a project idea at the top of a notebook page.
- In a list underneath, divide that goal into smaller (approximately monthly) milestones
- Do a weekly breakdown of the very first milestone, but not the others. When learning is involved, time estimates tend to be way off, and we want to avoid that messing with your confidence.
- For each work session, record which milestone you’re working on at the start of each work session in your notebook. Our goal is to identify and take the smallest forward step every day.
- Note changes in the goals or milestones in this list as you go along.
A Word on Skills and Techniques
For now, I plan on organizing these blog posts around skills: things you want to be good at to help you succeed as a self-taught programmer. For each skill we will talk about one or more techniques: stuff you can do to improve at the skill. For example, in this post, we have focused on the skill of goal setting, and we have covered a technique for breaking down goals into actionable steps.
The techniques I am planning to discuss in this series lend themselves to a set of metrics: how much time it takes to do this technique, how engaged you have to be to do this technique, et cetera. I am thinking about offering a little label at the top of each technique discussion with a list of these metrics to give you an idea of what each technique will feel like. For example, I would say that breaking down a goal takes a medium amount of time (not 2 minutes, not 2 days) and a medium amount of engagement (you cannot do it on autopilot, but if someone were to interrupt you in the middle you wouldn’t have to start all over again). There may be more metrics, and those metrics might become more specific as we move through the series. Stay tuned!