How I learned to code in nine years
I first began learning to code around December of 2010. I had quit my job to start a company that summer with my roommate. We raised a little money from friends and family, but things weren't going so well. We needed to drastically reduce our burn-rate or we would have to shut down.
Neither one of us were technical so we were paying my co-founders two former colleagues to develop the product. Nearly out of cash, it was clear we would no longer afford to to pay them. If we wanted to keep iterating on our idea, one of us needed to pick up writing code. Needless to say (as the title of this essay suggests), I decided to do it. The company ultimately failed, but as luck would have it, learning to code turned out to be far more influential to my life.
The following is a guide to how I learned to code over the next nine years. I don't know that mine is best or all that novel, but hopefully it helps others understand their options in changing their career. I've been extremely fortunate and despite being one of the most difficult things I've learned, it's been a privilege.
The title of this essay is a hat-tip to Peter Norvig's Teach Yourself Programming in Ten Years which I recommend reading!
A quick preface
One aspect of learning and mastering any difficult new thing—especially as a beginner—is pushing through the moments that challenge your resolve. For me those were feelings of inadequacy (I suck at this), impatience (I need this now), and fear (what if this was a big mistake). As someone with no formal CS background, no technical training, I felt like the deck was stacked against me.
What got me through the failures, false starts, and hard parts, was a relentless focus on what I wanted to build. It wasn't about learning to code, it was about keeping my startup going. Each thing I learned along the way were just the next problem to solve, to build that new feature, deploy that new site, fix that bug. I was obsessed with making things and coding was a means to an end. As a musician, this also seemed to make sense—I don't want to be a guitarist, I want to create music!
I think this helped to shift my focus to what I was making. Each failure wasn't about me, it was learning and making the product better. It wasn't until later that I realized how powerful and important this motivation was to me in all my creative pursuits. There is no stronger demand than creating an honest expression of your imagination.
My point here is that you're probably after something bigger than writing code. Heck, learning to code isn't even an actual destination—you'll always be learning. Introspecting on why can help you find a deeper motivation which I found to be critical to get through the hardest parts. This is the 'inner game' of learning how to code.
How I learned
Looking back, I found the following things to be extremely useful in accelerating my progress to becoming a competent software engineer. People are often surprised to hear that I didn't read textbooks, watch videos, or go to a bootcamp to learn. Personally, I learn best by doing (although early on I did read maybe half of Learn Python the Hard Way which is pretty great!).
Work on small, self-contained features to something that already exists
For me this was my startup, which I was highly motivated to improve and had an endless list of small, but useful improvements I could make. This eventually got me into web design, UI. I started taking on more ambitious features and snowballed from there going from python to frontend js/css.
I attended almost any hackathon I could. The culture hackathons is almost the ideal environment for someone like me: focused on a result, surrounded by other engineers who are generally nice and helpful, forced to deliver something in front of people. Some of my favorite hacks are totally unpolished, whimsical things with no clear purpose. My goal was very—simple—have something to demo to the audience by the end of the event no matter what.
Another bonus was meeting other engineers and creative people. Over time, I started to see the same faces. Meeting and working with different people on projects helped me build relationships—some of whom I've since worked with professionally! This was probably the first time I realized that coding was a social endeavor.
Hackathons definitely hold a special place in my heart. After getting over the crippling imposter syndrome (I still remember vividly to this day), they truly helped accelerate my progress in learning to code.
I've gone back and forth on how tactical mentorship should be. I think it's tempting to block your own progress because you have no one to help you. However, if you can only make progress because of someone else, you will not succeed in becoming a software engineer. Good mentors are more like guides than instructors. I do think my friends Jordan, Justin, and Jon had an outsized impact on my ability to get productive, but more through inspiration, friendly conversations about tech, and seeing what it could look like if I could get my skills to a certain level of proficiency.
When I'm learning something new I find that I enjoy immersing myself deeply into the community and forums that aggregate people who share a common purpose. Technology and startups were what I was interested in, but I realized that I needed to find more focused niches. Mainstream media doesn't cover tech and engineering well at all and you pick up on ideas and trends too late.
It sounds weird typing this out right now, but finding HackerNews was huge for me. It felt like this was where the builders hung out and you get the sense of being plugged into the community. Reading articles that were posted, looking through comments helped me build up the vocabulary and understanding of what's going on.
The Meetup scene was also vibrant in NYC for engineering and startups. Early on I attended many startup-related meetups, but they ended up feeling a bit like everyone was pitching each other and name dropping venture capitalists which got old. Thankfully there were more engineering meetups for specific languages, frameworks, and other interests where the folks building the startups where hanging out. It felt welcoming and fun, so much so that I would eventually start helping out organizing them.
Get paid to learn
After my co-founder and I closed up shop on our first startup, we continued to build quick prototypes together. While doing that I supported myself by finding freelance work with a design agency which a former colleague of mine owned. This allowed me to keep building up my skills and stay afloat financially (just barely).
At this point I was also assembling a portfolio which I could share with people for freelance gigs. By connecting with many people in the startup scene I eventually found a steady stream of work from those who needed some extra help or wanted me to build out a quick prototype that they could use to validate their ideas. It helped that I kept my rate quite low that way I could take on projects using languages/frameworks that I had little experience with.
The added pressure that someone is paying you for your code was a powerful force in pushing me to stick with it. I didn't want to let anyone down—including myself. The added motivation helped me learn even more as fast as I could while getting paid. Plus I got to work on some really interesting things!
Just keep building
During this time I just kept building new things—I launched something like 20 projects over the course of a year. All sorts of things, some that would never see the light of day, others that I launched to gather feedback and shutdown. The combination of repetition and exploring different frameworks and tools helped me rapidly build up experience.
I had a rule that I would use some new thing for every project I built. I kept a file of projects and which part of the stack was new. Sometimes that was a new framework, library, piece of infrastructure, or language. For me, exploring a wide range of ideas was very helpful to learning concepts and seeing patterns. A failure mode I wanted to avoid was tying my skills to a specific stack—I want to be an Engineer not a Django Developer!
Since I was typically building everything myself, it forced me to learn more about every part of the stack. For example, if I ever wanted to put what I made on the internet I better figure out how to host my server and deploy code changes.
Say 'yes' to more things
Finding a way to say 'yes' to more things presented many opportunities to learn and meet more people building interesting things. For example, a friend asked me if I wanted to do the StartupBus with them—a multi-day hackathon...on a bus. Saying yes to that was signing up for a grueling week, but as a result I got to meet lots of other hackers, designers, and journalists. I got to see SXSW for the first time in Austin, Texas—which, as an outsider, felt like the center of the whole startup scene.
As another example, I replied to an email from a friend (whom I met through the StartupBus) looking for volunteers for a non-profit. I applied for and received a grant to work on education tools for P2PU—helping people learn skills from peer-led classes. While I was volunteering my time to work on it, my travel and lodging was being covered so I could be in Berlin learning, meeting passionate people, and building meaningful things. It was an incredible experience and volunteering your time in exchange for getting experience was worthwhile.
Find joy in learning to master
With many projects under my belt I felt confident I could take on more and more ambitious projects. I realized the enjoyment I felt about going from an idea in my head to something that people could use on the internet was extremely satisfying. To me writing code is a creative endeavor—faithfully translating ideas into reality. I got the same feeling from writing music. My early career as a non-technical product manager and then startup founder was really about creating and now I'd stumbled upon this superpower. If only I'd realized this sooner!
I'm noting this because what might have been the initial reason for learning to code is seldom enough to sustain the journey. I did it because I wanted my startup not to die. I continued because I realized how well aligned the creativity of writing code is with my core values. Maybe you'll find something similar.
Starting up... again
Continuing to build my own projects and freelancing opened up new opportunities, including founding another company. While I was working part time at a startup, I was introduced to someone through a mutual friend (that I met through the startup scene) to build a prototype of an analytics tool. Starting as contract work, it very quickly turned into a round of funding and an offer to come on full time as part of the founding team.
Startups are an incredible place to grow and learn a wide range of skills. I was able to apply all of my experience thus far as a full stack developer, but this time I was also confronted with scale, recruiting, fundraising, management, all while delivering tools for users paying a lot of money. Certainly no hiding there!
I felt immense pressure to deliver and there were plenty of dark moments, but they were all motivation to push myself, learn more, and get it done. It was humbling, I struggled with imposter syndrome, but ultimately helped build a company, team, and product I was proud of.
I aim to keep one side project going at all times. I did this even while under a ton of stress with running a startup. Mostly because it provided another outlet for my creative energy and I could learn new things sometimes totally unrelated to my day job. I like to work with languages and tools I haven't used before and I've found there are many benefits to my day job through this exploration.
Side projects make you better at your job and, more generally, your rate of learning. Ideas picked up from these side project forays have been extremely valuable to me. It's made me a better engineer, manager, and keeps me sane when I just need a break from the day-to-day.
Learning multiple languages
The second programming language I learned is probably the language I learned the best. I think because in the early days I was just trying to get things to work and everything else was just the next problem to be solved. I didn't really take the time to learn the language well. However, the second language I learned, Clojure, I was much better prepared. Experience helps you learn how to learn and I've found this applies to programming too.
I deliberately try to learn languages that are very different from the ones I already know. As an example, I wasn't interested in learning Ruby because I knew other high-level dynamic languages like Python. Of course Ruby and Python are very different (and I did eventually learn Ruby when I joined Stripe), but I wanted to experience new ways of solving problems and different paradigms.
These days I'm learning Rust because I've never used a strongly typed language before (or one that can operate so low-level). Learning to use types and all of the concepts that come along with it has been an excellent learning experience and helps round out my knowledge of programming.
Ok now read textbooks and academic papers
Most of what I described about learning to code has been very focused on building things as the way to learn. After a certain point I found it difficult to make progress without more understanding of computer science (in the academic sense). At my last startup, I was working on some really hard problems of distributed computing, big data, and even machine learning. It was time to stop avoiding academia and learn to read papers and textbooks.
I think this helped deepen my knowledge about the work I was doing and engineering in general. I eventually learned some of the things I'm assuming people learned in their CS classes at university—algorithms, data structures, and networking. I cracked open some of the classics like Structure and Interpretation of Computer Programs (SICP) and even implemented some algorithms from academic papers.
I'm still pretty slow at parsing academic papers because of the mathematical notation. I have to call my brother sometimes to ask (he's a physicist). Maybe I'll go and learn that one day too!
Present at meetups and conferences
Presenting at a meetup was also a good way of forcing yourself to learn a topic really well and focus your energy on things people find interesting/relevant. For example I presented at the Clojure meetup and the Python meetup on topics related to work or side-projects. I find it's a great way to participate, share something valuable, and meet connect with others. Organizers are often hungry for presenters and it costs you nothing to reach out and ask to present with a good idea about what you want to talk about.
For me, the capstone to my journey was presenting at a conference. I idolized people that talked at conferences. They just seem so important and revered! If I could somehow get there I would feel like a card-carrying member of the software engineer club. I finally did achieve that goal by presenting the chocolatier game engine at Clojure West in 2016 and, well, it turns out the journey doesn't end there! However, it was a useful goal and I think it was the culmination of lots of other work to get there.
All in, what I outlined above has taken me nearly a decade. There's not really one moment that denoted 'OK I am an engineer now', but I think maybe I'm the only one that cared about that.
Was it worth it? Learning to code put me on an unexpected path that led to some amazing opportunities and people. I found my way into tech and stayed there. As much as we like to gripe about Silicon Valley-isms, it's been my dream to get here and I think we can keep making it better.
These days I get to share my experience with others, help them grow, and build really cool things like Stripe Atlas. Engineering leadership has been my latest journey—from startup CTO to engineering management at Stripe—it's been just as interesting and unexpected as learning to code!
Have a question or want to say hi? You can reach me on twitter @alexkehayias