I just recently passed my 1 year mark as a “real” software engineer (whatever that means), and I wanted to take time to reflect on my journey and come up with some learnings. I feel this is beneficial both for my personal growth and also as advice for anyone in a similar situation.
How it started: the terrible internship
I could still recall my internship almost exactly 4 years ago at one of Singapore’s largest law firms, absolutely hating everything about the experience — dressing up in stuffy, uncomfortable attire, working rigid hours even when I was done with my tasks, working on dull work, and feeling a complete lack of job satisfaction. There was no specific Eureka! moment, but I knew then with crystal-clear certainty that I definitely, definitely did not want to practice law.
That internship was a significant milestone in my SWE journey in more than one way, however. Apart from providing clarity on what career I would not enjoy, it also gave me an inkling of what I would in fact like. For some reason (and I can’t recall why exactly), during that internship when I had nothing to do (and didn’t feel like asking for more soul-numbing work), I ended up reading git documentation (lol no kidding). I spent my days burrowing down the rabbit hole of source control — and I remember being fascinated by its simplicity and ingenuity. I am absolutely not kidding when I say that this single incident was what sparked my interest in software engineering as a career choice. I was like, “this is really cool!”
A semester abroad
After my internship ended, I spent my next semester on overseas exchange at the University of British Columbia in Vancouver, Canada. I didn’t really think too much of software engineering at the time because I was way too excited about the opportunity to live overseas (in Canada too!).
Because I was on exchange, I was graded on a pass/fail basis, and so I had a lot of slack in studying (which translates to a ton of free time). Meanwhile, what I read about source control was lying dormant in my subconscious, waiting to spring up. And on one fateful day, I decided to apply what I had learned about source control — by building my first ever app, a Reddit bot.
Now, I had absolutely no experience with software engineering at that time (although I had some programming experience). Check out my first bunch of commits before I realized that you shouldn’t include the date in your commit message. Hell, I was actually using git commits as “savepoints” before that to save incomplete implementation, but thankfully I realized that mistake before pushing to GitHub (not embarrassed to admit I was a complete noob). I worked with Python (because I knew it was extremely beginner-friendly), which happened to have a great Reddit library. I chucked everything into one huge file because I didn’t know any better. Along the way, I learned about web requests and scraping. I didn’t know about PAAS providers like Heroku, so I reserved the free AWS EC2 instance to run my Reddit bot (I SSH-ed into my instance and ran it with
nohup so it doesn’t die). It would frequently crash and I had to manually restart it. To find out why it was crashing, I implemented “logging” by printing to text files.
It was a piece of shit software, and it worked only half the time, but I was hooked. It felt like magic (it still does) to create something and see it work. Even today, this is probably the aspect of software engineering I like the most — making, building, creating.
I was so addicted to building my bot that I was writing code during my law classes (I remember writing code during my seminar when the lecturer was droning on about intellectual property.)
It was probably at this moment I knew I wanted to be a software engineer.
A path filled with obstacles
It wasn’t straightforward though, and I had several concerns about my newfound career choice.
First, there were some obvious obstacles in the way. I would be graduating with a law degree — why would any company hire me to write code? Even if they would, I didn’t think I was anywhere good enough — a crappy Reddit bot that crashes every few days isn’t that impressive. I felt I lacked the CS fundamentals to be a “real software engineer”.
Second, I had no mentorship or guidance available to me. Unlike the CS majors, I didn’t have seniors working in a bunch of different tech companies to offer career advice or provide referrals. It was a huge step and there were too many unknown unknowns, and I had no idea where to begin.
Third, it was terrifying to step away from the well-trodden path into the unknown. I was literally the first person (that I knew of at that time) to make this move, and I had nobody’s footsteps to follow. There was no “right way” or “wrong way”, because I didn’t see any tracks at all.
What I did
From early on, I decided against completing switching majors to computer science. If I did that, I would probably have to extend my candidature (and postpone my graduation) by at least a couple of years, since most of my law courses were not transferable. Based on my available options at the time, I decided to apply for a minor in computer science.
In all, I applied to minor in computer science 3 times. I only succeeded on the third try. I was probably rejected the first two times because I had nothing to show for it except a tenuous write-up in my application. For my third application, however, I had taken the introductory programming class by then and scored well — that probably tipped me into the accepted zone.
I did not feel disadvantaged in my programming classes, likely because I had built a bunch of side projects by then and am comfortable with writing code (in addition to my programming experience). In all honestly, I probably also have a natural aptitude for computational thinking, because expressing ideas in code felt natural and intuitive to me, and I did not experience common struggles that I hear about.
What I did struggle massively with, however, was data structures and algorithms. I was both fascinated with the ingenuity of what I was learning as well as horrified at how hard it was to be comfortable with them. For practice, I was solving LeetCode, HackerEarth, and HackerRank questions in my free time (I actually wrote a post about that). I ended up with a grade I was pretty proud of, considering my 0 →1 journey in the course of a semester.
Some time at the end of my third year, I learned of a couple of software/product engineering modules (CS 3217/3216) that were said to be extremely tough but rewarding. I decided I wanted in. I reached out to Prof B — who formally or informally runs these modules — to “find out more information” (my diplomatic way of trying to wiggle my way in). I remember reaching out over Facebook Messenger, and almost immediately getting rejected. I was told that these classes were extremely competitive, rigorous, and reserved for the top computing students only. But at that time, I was defiant and wanted to prove myself, and I refused to take no for an answer without a fair consideration.
Eventually, Prof B agreed to a meetup (probably to suss me out). I can’t recall what we chatted about exactly, but the TL;DR is that my grade in the introductory programming module convinced him that I might actually be half-decent after all. We ended the meeting with the understanding that my acceptance into those modules was conditional on my grades that semester for the (more) advanced programming class as well as data structures and algorithms.
Fast-forward to the start of my fourth (and supposedly final) year of university. I scored well enough in those two classes to be accepted into CS3217 (CS3217 and CS3216 are conducted in alternate semesters).
Honestly, I loved CS3217. It was challenging enough to be exhilarating, which is not a word I’d commonly use to describe classes. We were literally being thrown into the deep end of the pool; lectures were on abstract programming concepts that were only tangentially related to assignments. The assignments came in fast and furious, and we were expected to turn to Google for pretty much all the help we needed. Fun fact: CS3217 technically lists another (introductory) software engineering module as a prerequisite, but I took both classes concurrently, and my CS3217 classmate ended up being my tutor for the introductory software engineering module. By the end of the first half of the semester, we had designed a physics engine and a game engine from scratch, and used them to build a full-fledged game! For the second half of the semester, my team ended up building a budget-tracking application. Nothing revolutionary, but it was fun putting together an application from scratch and thinking through its design and architecture. I absolutely loved this class, I learned so much from it, and more importantly, it affirmed my interest in software engineering. I’d always been a self-sufficient and independent learner, so I was extremely comfortable with the teaching style of the class.
I read CS3216 during my final semester of university. It was a hella crazy semester — I was juggling an almost full-time internship (4 days a week), a law module, CS3216, and LeetCoding furiously in preparation for job applications. I spent virtually every waking minute living and breathing code — including during my law class, and I could definitely sense that I was pissing my law class instructors off. (I was too busy to even read their feedback for my assignments, and ended up repeating the same mistakes for multiple assignments.) CS3216 was, in some ways, “messier”— instead of focusing purely on the technical aspects of writing high-quality code, we focused on developing a great product instead. We worked in cross-disciplinary teams involving product marketing, UI/UX design, user research, and of course software engineering. On hindsight, I think I prefer CS3217 which has a clear emphasis on code quality and software design. And, again, on hindsight, I think my preference for CS3217 carried over to my career path as well (more on this another time).
Finally, in my last semester, I applied to take a “tech interview prep” class as well, run by Prof B (again). Just like before, I was initially rejected because the class was reserved for School of Computing Year 3 students, which I was not. I knew I needed every bit of advantage I can get, and I wanted to be there to soak in all the knowledge and tips, as well as network with other students, so out of desperation (and because I was feeling lucky), I asked if I could just informally sit in to observe. Eventually, Prof B allowed me to take the class as a full participant, which entailed mock technical interviews, assignments, presentations, etc.
This turned out to be one of those lucky breaks in life that make or break. I got my Facebook referral from the class’s TA, and eventually my first job out of university. I can’t imagine how different my life would be right now if I had just given up on that class.
I knew I had a lot of catch-up to do to be competitive with CS majors when applying for full-time positions, and that internships are extremely valuable experiences, which was why I made them my top priority.
I ended up doing 3 internships at a tiny start-up, a medium-sized start-up, and a large tech company, to get a sense of the type of company I want to work at.
My first internship was unremarkable. I interned during my winter break in my third year of university. I remembered that I PM-ed a random user on Reddit who posted about an internship opportunity, and he connected me with the hiring manager. It was complete luck that I even found out about this. I made it clear to the hiring manager that I did not have prior experience, but I was willing to learn. I probably fit the bill, because it was a tiny startup based in one of Singapore’s universities that was working to build a MVP to explore the market potential of an idea. I did not have a tech lead/mentor, and had exceptional autonomy over the project (I was essentially the only engineer working on my part of the project). In hindsight, I didn’t learn as much as would be ideal, but it gave me a taste of the industry, and I did make use of it to learn as much as I could (I picked up Redux to pair with my React knowledge to build stateful web applications).
My second internship was at a medium-sized startup with one mature profit-generating product and a newer, yet-unprofitable product in the market-capture stage. This was a longer internship over summer break between my third and fourth year in university. I remember being really nervous about the interview because it was my first technical interview ever, and I didn’t know how tough the questions were going to be. In the end, it was a lot easier than expected (as most things in life are) — some stack-based question, if I recall correctly. Because I was working in a startup, roles were not as clearly defined as in a large company, which meant I did a bit of software engineering and a bit of devops. We had daily stand-ups, and biweekly sprints. It was an awesome work environment, my co-workers were great, and I learned a ton.
My final internship was at an established Singapore-headquartered tech company. The technical interview was definitely way more challenging— my most memorable question from all my interview questions was to build a parser-interpreter for a simplified programming language which involved generating an abstract syntax tree from an expression and then evaluating it. I remember being so stoked that I could conceptualize a working solution in my head, and write functional code that seems like it could work… and yep, it works! At this internship, I worked on an iOS gaming-companion application, and it was definitely more technical than my second internship.
And as I was hustling in my final semester, juggling my law and CS classes, my internship, as well as LeetCoding like my life (career) depended on it, I was also sending out job applications. I knew for sure I wanted to work in Silicon Valley if I could, because it just sounded a lot cooler and I’ve always wanted to experience working and living overseas, so most of my applications were for SV-based companies. Otherwise, I also applied to local companies.
I pretty much got rejected or ghosted by every company except for Asana, Facebook, and Google where I passed through to the final round of interviews.
Let’s start with Google. My Google interview was for the Singapore office. I tried my best and flunked it. That’s the end of it.
My Facebook interview was originally for the Singapore office as well, but I worked with my recruiter to eventually switch my application over to the Menlo Park (“MPK”) location. That was a big risk — I imagine that competition for MPK is a lot higher than for the Singapore office, and I remember consulting my friends and family on whether I should take that risk. Eventually, I decided to take the chance and go for it.
My Asana application was supposed to be for the San Francisco office, but headcount zeroed out during my application process, and so I switched my application for the Vancouver office, although I’d still be interviewing in San Francisco.
Eventually, after a nerve-wracking week of coordinating with my Asana and Facebook recruiters, I lined up both interviews for the same (free!) trip to the Bay Area.
Tl;dr: I failed Asana (though I’m not sure why, I thought I did really well!) but received a Facebook offer! And that’s how I went from a law student to becoming a software engineer.
I just passed my 1-year mark at Facebook (happy Faceversary!) in May 2021, and in all honesty, I think I’m doing pretty okay. I started out as a product engineer, but I’m considering switching to an infra team.
Looking back, it has been a hell of a journey, with ups and downs (mostly ups though) and a bunch of pure luck.
I think here are some of the lessons I distilled.
Live life greedily. I like to think of my approach to life as a greedy one, where I make locally optimal decisions at every stage. I can’t guarantee that I will arrive at a globally optimal outcome, but it gives me the greatest expected value. Make the best decision at every point in time, and unless you are extraordinarily unlucky, you should come close to the global optimum.
Make your own luck. I don’t believe that some people are naturally luckier than others. I think luck is a manifestation of both random variation and one’s own actions. Make your own luck by putting yourself in the best position possible to “get lucky”. For instance, I was “lucky” to receive a referral, but I enabled that “luck” by fighting for the chance to be in the class.
Be gritty. Don’t take no for an answer —understand no to mean “not now” (obviously, this advice is not meant to apply to romantic contexts, in which case this is no longer grit but sexual harassment). Looking back, so many lucky breaks were a direct result of my persistence and not giving up.
Tl;dr: persistence (grit) makes for a greedy approach to life that makes luck.
I’m still eager to learn as much as I can by following my interests. For instance, during the Covid-19 lockdown in 2020, I completed an online operating systems textbook. Right now, I’m learning to design and implement my own programming language.
I think it’s important to never stop learning, both as a source of personal growth and professional advancement.
I’m also actively seeking out mentorship so I can learn from other people who have been through similar journeys.