So you’re still in school and Google has always been your dream company? Or maybe you’re in a non-tech related field but have had a recent change of heart? Heck you might be already working for one of the software giants but you’re still feeling like an imposter? If that’s you then read on.
My software engineering career commenced with a Google summer internship in 2011. At the time, I was a junior at the University of Michigan-Dearborn where I was pursuing a bachelors in Computer Engineering. After enjoying a great summer, I interviewed again and was able to secure a full-time position upon graduation in 2012.
I went on to spend 5 years working for 3 different teams (AdSense Front End, Android Systems and Assistant Infrastructure) in the Mountain View and Los Angeles areas before finally ending my journey there as a senior software engineer in mid 2017 to dedicate my time and energy on building Mindcrumb a startup that addresses the main pain points in the continued education realm which is a field that I’m very excited to improve!
I’m not claiming to be an expert on this subject, but I will simply share my journey that got me there and the lessons learned along the way. This isn’t merely a guide for quickly cracking the interview questions, but rather my personal blueprint for building a stellar software engineering career at a top silicon valley company the smart way.
Disclaimer: The first publication of this article was on the first of August 2017 which was also my last day working for Google. The opinions discussed in this article represent solely myself and are not affiliated with Google.
How Top Engineers Operate
Before delving through specific tips to get noticed by recruiters and ace those notoriously hard interview questions, I’d like to talk a bit about the common traits and mindsets that I’ve witnessed firsthand through working with some of the smartest bunch of silicon valley software engineers:
- Clearly define problems from first principles: First and foremast they do not expect to be spoon fed what to do. On the contrary, they are aware of their team’s general direction and strategy and are able to define and scope both short and long-term problems that need to be solved. They are proactive in reaching out to experts inside and outside the company to gather as much data as possible in order to explore all their options until they settle on one clear solution. Most times the difficult part is defining the problem and not implementing the solution.
- Speedy implementation: As soon as the solution is identified they are able to quickly implement it because they have already spent time optimizing their development environment in terms of mastering their programming language, source control tools, editor, testing tools…etc. In addition to that, they never forget to do that last 1% of the work in terms of cleaning their solutions and making them more readable to their fellow teammates.
- Great communicators: A problem is far from over when the last line of code is implemented, as documenting and marketing the solution should never be taken lightly. There’s no point in creating an amazing platform or a testing benchmark if no one knows how to use it or no one even knows it exists.
- Do not develop an ego around their ideas and projects: This one is huge and can be controversial as a lot of great engineers tend to have huge egos. Nonetheless the few who are viewed as team players and mentors in their teams are the ones who welcome conflicting ideas and potentially retiring projects that they’ve worked hard to deliver. They simply don’t form an identity to themselves from their own projects. They are not afraid to admit that they were wrong about something and those around them will respect them and trust them even more as a result.
- Maintain high standards: Great engineers don’t produce sloppy code or skip testing just to finish the project faster. They realize that it’s a bad investment of their time since it’ll potentially create unforeseen bugs for end customers and will create unnecessary overhead to several teams. High standards also makes them more trustworthy from their teammates which automatically makes them an authority. Everything they create is well polished.
- Constantly stretch their comfort zones: They aren’t afraid to move on and be beginners all over again.
Master Computer Science Fundamentals
To learn the piano some people choose to simply memorize and replicate a few known musical pieces over and over. It certainly is a great way to feel that you’re progressing quickly and perhaps fall in love with the piano not to mention bragging rights from your friends, but it’s far from becoming a piano master. That requires some level of understanding of the fundamentals of music theory, ear training and writing your own music which is a whole new level.
Similarly with computer science, the fact that you can design a cool website for an online garage sale does not make you an engineer who’s able to efficiently solve computational problems. Hack reactors and coding boot camps that teach such ‘vocational’ skills are a great start, but they’re not enough to become a software engineer that top companies are looking to hire. A computer science (CS) degree is one way to go but I’ve worked with countless competent engineers with college backgrounds in Math, Physics, Economics, Philosophy and others.
Whether you are a CS major or not, I’ve compiled a list of fundamental topics that you should at least have some practical understanding of. There are a lot of ways to acquire the knowledge in those topics ranging from taking a class or reading a book. My personal preference is to start with a related fun hands on project (that you would enjoy) and then dig through a reference book to bring all the key points together. Without further ado, here are the fundamentals and my personal recommended recipes to acquire them:
Object Oriented Programming and Design Patterns
My language of choice is C++ which is still a popular language for writing servers at big companies like Google. If you have no prior programing knowledge or if you’re a curious 14-year-old who’s intrigued by C++ like I was back in the day, then I would recommend Deitel’s C++ How To Program Book.
The Deitel book tends to over explain concepts which is great for a beginner, however; it doesn’t have a lot of fun applications so my recommendation is to think about software categories that you’ve always wanted to create. For example, if you enjoy video games, then you can supplement your studies by simultaneously going over a C++ game development course. One easy to follow resource would be gamecodeschool.com (they even have a C++ beginner course if you’re too impatient to jump right into the fun stuff!).
Object oriented programming (OOP) is a programming concept that breaks down systems into a set of manageable objects that interact amongst each other. This paradigm simplifies huge projects and makes collaboration so much more tolerable which is why it’s a must learn skill when working in a big tech company.
There are countless ways to structure your code when solving the same problem in the OOP realm. Some are palatable but some are plain ugly, which is why I highly recommend you go over the book Design Patterns for timeless and elegant solutions to common problems in software design.
Algorithms and Data Structures
Algorithms and data structures form the foundational framework when solving any computational problem. As a result, they constitute the biggest chunk of tech interviews. Knowledge in this area is what separates coders from engineers, so if you had to pick one area to focus on in this foundational section then it should be this one.
At its core fundamentals, for any given computational problem and a list of constraints, you need to come up with the most efficient algorithm that solves that problem. Moreover, you’ll need to analyze the growth cost of the algorithm in order to properly allocate the least amount of resources required.
General purpose programming books like the Deitel book will cover the basics; however, you’ll require a more in-depth knowledge in this area to challenge yourself and deepen your knowledge. For that, I would recommend going through Skiena’s Algorithm Design Manual. The book has a thorough treatment of the subject with lots of examples and exercises.
Moreover, to make it more fun and put that knowledge into practice, I would advise going through online algorithm competitions like Topcoder’s Single Round Matches which consists of several problems with varying difficulties.
You can choose to compete against others in real-time or at least attempt to solve one of the older matches’ problems on a regular basis. You can tweak the difficulty based on your level but my biggest advice would be to code the problem completely and make sure it passes the system tests even if you gave up on the answer and had to peek through the match’s editorial to get some hints.
If you have any sticking points in one area (e.g. Dynamic Programming), then go through the related topcoder tutorials to aid your progression.
NOTE: Delving through the next 4 sections is optional if you’re aiming for a general entry-level software engineering position (e.g. new college graduate); however, it’s recommended to go through them eventually if you aspire to deepen your software engineering understanding and have a more well-rounded skill set.
Basic Computer Hardware
Often times an algorithm will require a complete redesign in order to cope with its execution environment’s constraints, so having a good understanding in those deeper layers will help you make better decisions.
We’re living in the era of “Internet Of Things” (IoT) where computing capabilities are embedded in small and large devices, so a basic understanding of their various subcomponents is crucial to properly design algorithms that cope with the host device’s capabilities.
One way to acquire those hardware skills as well as create fun and meaningful projects is to go through a hands-on Arduino course. You’ll also get a chance to practice your C++ programming skills in a restricted computing environment. There are plenty of Arduino courses out there, but the one that I went over is The Arduino Starter Kit.
If you’re extra curious about this section and have the time and energy to go deeper on this topic then The Elements of Computing Systems book will certainly become a new favorite of yours.
OS Fundamentals and Systems Programming
After getting compiled, a computer program will need to be executed by the hosting operating system (OS). The OS’s job is to execute the code and allocate the resources that the program requires. The OS will present several interfaces that abstract the details of the hardware calls (e.g. through system calls and device driver filesystem interfaces) which means that the compiled code is operating system and processor specific.
Compiled languages such as C++ allow you to write portable code that can be compiled to various different CPU architectures and operating systems due to its standardized libraries and various different processor-specific compilers. As a result, the programmer won’t have to worry too much about the various different hosting environments unless they’re dealing with system-level code (e.g. creating a software interface for a new plug and play device).
Despite its limited use outside of low-level coding, learning system programming will help you get generally better at improving and measuring the performance of your code as well as allocating the minimal resources for scaling your projects. It will also improve your awareness of systems’ security and will help you get better at debugging tricky flaws in your applications.
A good approach to acquire knowledge in this area is by writing some system-level code in Linux. Pick one example application to implement from scratch while going over a good systems programming book such as Robert Love’s Linux System Programming. A good example to implement is a system daemon that logs file access for a specific application (process), and a separate program that communicates with the daemon and provides the user with an interface for selecting which process they wish to log.
Last but not least, now that you have some experience with interacting with the operating system, it’s time to learn more about its inner workings. If you’re not planning to deep dive too much in this area, then the MINIX book would be a great resource. It provides self-contained knowledge of the fundamentals as well as actual code snippets from a real OS.
Minix is a relatively small but fully functional OS with limited use outside of academia, so if you’re looking for a more real-world system to learn about then I would suggest heading to my systems engineering article for a detailed study plan.
Learning how a computer program gets compiled into the language of the CPU helps you get a deeper understanding of programming language fundamentals. You’ll gain a firmer grasp on language parsing and how high-level instructions are converted into a group of simple arithmetic/logic and memory access counterparts.
Compiler design knowledge will also come in handy when using a debugger for real-time tracing of program execution; whether for troubleshooting tough bugs or reverse engineering third-party software.
To quickly gain knowledge in this area I would recommend implementing a compiler for a simplified programming knowledge. Luckily, Niklaus Wirth’s Compiler Book is a free resource that does just that in 100 pages! It walks you through implementing a compiler for the Oberon programming language while simultaneously introducing the needed algorithms and grammar concepts along the way.
Another resource is the Dragon Book which is regarded as the go-to book in mastering this area; however, I find it too abstract and difficult to grasp so I would advice on optionally using it as a supplemental resource or a second book to go through should you decide to delve deeper.
Compiler construction is a challenging but rewarding topic to study. It will take your algorithmic skills to the next level and will introduce a lot of concepts that will be helpful if you decide to deep dive into an NLU (natural language understanding) related field so I recommend not ignoring it.
Networking and Distributed Systems
As networking technologies have exponentially evolved we are no longer limited to performing computations on a single machine. Problems dealing with massive data structures (e.g. map reduces) can be distributed amongst a cluster of locally interconnected computers, thus forming a supercomputer (e.g. data centers).
Distributed parallel processing significantly speeds up algorithms while loosening up the hardware limitations of an individual computer.
On the other hand, problems that require relaying information to millions of users worldwide (e.g. navigating to a website, executing an RPC call) require replicating the same program (e.g. web server) on a cluster of globally connected computers. This global replication known as cloud computing reduces response latency and improves service reliability.
It’s recommended to get a good theoretical and practical knowledge in this area especially if you’re going to work for a giant company such as Google. A great resource to help you get started is Van Steen’s Distributed Systems.
Finally, if you’re curious about how the internet is connected and what happens behind the scenes when you make a single request to view a webpage, then consult Section Two of Unix and Linux System Administration. The book will help clarify a lot of those topics as well as introduce numerous helpful utilities to investigate on your own (e.g. tracking the itinerary of a network packet using ‘traceroute’).
Optimize Your Environment and Sharpen Your Toolset
Most programmers budget the majority of their time and energy on designing the solution to a problem while underestimating any major hiccups during implementation. This would certainly be a very reasonable assumption for someone who optimized their programming environment and sharpened their tool set.
In reality though, the majority end up struggling with using the correct language patterns or end up manually copy/pasting repetitive code that could easily be automated or even worse when they hunt and peck for the keys on the keyboard.
To make matters worse, the same toolset problems will happen again in different projects which will further maximize the overall wasted time and energy. Consequently, spending some time on mastering your programming toolkit will pay dividends on the long run.
Here are my recommended tips on conquering this area:
Become a Touch Typist
If you feel that typing is significantly slowing down your train of thoughts, then it makes sense to put some focus on this area. Out of a sheer bad habit, there was a time when I used to hunt and peck on the keyboard especially when typing symbols.
To fix that issue I used typing.io which is an online typing instructor tailored specifically for improving programming typing speed. It took a few weeks of daily 15 minute practice to become a touch typist (I even purchased a Das Keyboard with blank keys to force myself into breaking my tedious hunting and pecking habit).
Master your Code Editor or IDE
Regardless to what project you work on or what programming language you use chances are you will end up using the same editor, so it makes sense to become more proficient with it. Vim is my personal favorite due to its high customizability and smooth handling once you’re past the very steep learning curve.
There are several other editors like Eclipse or Sublime that are more user-friendly and less intimidating for a beginner. However, if you’re as masochistic as I am with your tools and vim sounds appealing, then I would suggest you master its fundamentals first before attempting to extend its functionality with a good set of plugins (see my fully customized vim on my github). An easy to follow book to go over would be Practical Vim.
There are countless editors and plugins out there so make sure you stick with the one that makes you the most productive.
Fluently Speak your Programming Language
If you’re new to coding in a specific language then I would first recommend delving through a language cookbook rather than a reference book. Save the reference book until you’re comfortable with the language fundamentals.
Understanding the language very well will make it easier to review other people’s code without constantly deciphering their snippets on stackoverflow.
Learn How to Debug
It’s frustrating when your code doesn’t work properly and you have no clue where to start. Reading through the code to figure out the problem can sometimes be tedious (especially if you’re not reviewing your own code) so learning how to use an appropriate debugging tool to quickly pin-point the malfunctioning pieces is valuable.
There’s a variety of tools depending on the project. For example, if it’s a malfunctioning webpage then Chrome Web Inspector can help. If it’s a C++ program then the gdb debugger can provide clues. If it’s a sluggishly performing Android app then a tool like systrace would be a godsend.
I would recommend you research the right tools for your project early on in development so you don’t have to stress about it later on.
Learn About Version Control Systems
If you’re collaborating on a project then you’re most likely using a version control system (VCS). To save yourself some tears and frustrations when checking in code or resolving conflicts, I would suggest you allocate an afternoon to study the VCS’s inner workings and practice using it on a dummy project.
You should avoid stressing over the same recurring problems over and over again by using process automation. Many processes can be fully automated with a script while others rely on simply capturing a bunch of notes and storing them in an accessible location.
Examples of common tools to automate coding related problems are bash scripts, python scripts, vim code refactoring commands, writing a C++ utility…etc. On the other hand, for most of my ‘life-related’ automation needs, I tend to use the Google App Scripts since I already use gmail, calendar and google drive to stay organized.
I also like to keep one large “Notes” document where I jot down pointers to my scripts and when to use them, as well as any useful recipes for familiar problems to avoid redoing the same research all over again. The Notes file is in the md format so it displays nicely in both a command line or a GUI environment. It’s also searchable, easily accessible from the command line with a short alias and it’s synced to my google drive.
Have Something To Show
Now that you’ve got the fundamentals handled and feeling good about navigating your coding environment, it’s time to showcase some skills. Pick a challenging but exciting project in an area that you’re curious to explore. For example, if you’re interested in creating chatbots derived from websites’ help pages then you should deep dive in NLP (natural language processing).
This isn’t about bragging to the world about what projects you’ve created, but it’s more about developing some depth to your technical skills and getting better at starting and finishing projects.
It’s very important to develop mastery in at least one area if you aspire to take on a lead role in bigger projects. This is also the fastest way to get promoted to senior positions at the company.
Discussing previous projects is a common warm-up interview question that allows you to confidently talk about a subject while leaving a good impression. An interviewer can easily see through candidates who talk about a project that they’ve simply brainstormed as opposed to those who implemented it from the ground up due to the depth of details provided.
Having a meaningful side project will make your resume stand out especially if you’re not from a top-tier university or if you haven’t had a previous prestigious internship.
It’s important to keep side projects even after you get hired to stay inspired and not get sucked in too much into the company’s culture that you become too detached from the outside world.
Sell Yourself: Your Resume and How to Structure it
Even though a LinkedIn profile has become a de facto unofficial resume, recruiters still require a traditional resume to review your application. More importantly, your interviewers will also have access to your resume and will likely tailor their assessment based on it.
The key rule regarding the length of the resume is that less is more. Assume that recruiters and interviewers will take the same amount of time to skim through it whether it’s 300 words or 3000 words. By writing less you make every word count, so try to cap it at 1 page but don’t abuse that rule by cramming too much tiny text everywhere.
Keep your resume appetizing to read. Use a pleasing font (i.e. no cursive or comic sans!), avoid colors, don’t trim the page margins and leave some white space in between sections. Present it to friends and teachers and ask for honest feedback. You can even hand it over to strangers for 30 seconds and ask them what they’ve learned about you during that brief time; this is a pretty good measure of how lean and readable it is.
Your resume is likely to be split into 4 major chunks: education, work, projects and skills. In order to quickly captivate the attention, I advise you to arrange the first 3 chunks in the order of importance and impact.
This will likely be your first section if you’re a recent college graduate. Make sure to include your school, major, graduation year and your GPA (you can include the major GPA if there is so much contrast with the overall GPA).
Don’t forget to mention any awards, scholarships and extracurriculars; but make sure not to dilute your impressive achievements (e.g. valedictorian, or president of an honor society) by including a few mediocre ones (e.g. general member of a club that anyone can pay money to join).
Recent Work History
Start with listing your most recent positions first coupled with a quick one line explaining your duties. If it’s a recent job that is relevant to the position you’re applying to, then you should also follow-up with a more detailed explanation of your contributions and accomplishments.
Same key rule applies, avoid wasting ink on older or less relevant positions. Stay concise and avoid using less known acronyms.
This should include your top relevant side projects. If you’re a recent engineering college graduate then this would be the place to talk about your final year project. Keep the following points in mind:
- Mention the motivation behind the project (e.g. school assignment or personal curiosity)
- State the problem that you’re trying to solve
- Describe your contribution if it’s a team effort
- Highlight the most challenging and unique aspects of the solution
- Include links to its website, design and code when relevant (e.g. github links)
- Talk about the impact of the project and any awards claimed
This section is optional. Ideally your skills should already shine through your work history or side projects. If that was not the case then you can include them in this section, but I would advise you keep the following in mind:
- Only include skills relevant to the job you’re applying to.
- Avoid including under-developed skills and be extra careful with adjectives like “expert”. From my experience interviewing, I have adjusted my questions numerous times to target that “expert” area, not to be evil, but in order to see how the candidate operates in their self-proclaimed comfort zone.
- Don’t include basic or less impressive achievements as they will give the impression of a rookie (no need to include that you’re an expert at Microsoft Word or Paint…etc.).
Prepare For The Interview
Interviews assess your skills in 3 main areas: algorithm/data structures, programming languages, and system design. They also gauge your communication skills as well as your thought process when approaching new problems.
Interviews are generally heavy on solving algorithmic problems so it’s imperative to have this area tightly handled (revisit the corresponding fundamentals section for pointers).
In the weeks leading up to your interview, make sure you are solving at least one problem every single day within a reasonable time and even better if you can code it on a whiteboard. Practice speaking up your thought process as you write the answer. Stretch your comfort zone by picking new problems in new areas of focus and keep challenging yourself by yanking up the difficulty level as you progress.
Here are the most important algorithm categories that you must have a good practical understanding of (i.e. solve practice problems related to those from topcoder or other similar resources):
- Sorting and Searching Algorithms
- Tree and Graph Traversal Algorithms
- Algorithms using Hashtables
- Dynamic Programming
- String Searching and Manipulation
- Basic Geometry Concepts and Algorithms
The Structure Of The Interview
Interviews usually start with a quick ice-breaker chit-chat about your previous work experience or projects. My advice to you is to avoid bragging or talking on and on thinking that it would impress your interviewer because it won’t. All will it do is rob away precious minutes from the upcoming problem solving section.
The next and most important part of the interview, is the problem solving section. Here is when the interviewer presents you with one or more problems (usually of increasing difficulty) in order to assess your skills. Many of the questions will involve writing code. For those, I would suggest you avoid jumping straight to coding until you have verbalized a clear design to your interviewer.
Don’t be shy about asking clarifying questions if you’re unclear about any parts of the problem. If you feel stuck for too long, I would suggest you ask the interviewer for a hint; you will likely lose a few points but it’s still better than not finishing the problem.
Finally the interview ends with a five-minute Q&A so here’s your chance to end on a high note. Even if you think you did horribly, try to stay cheerful and actually ask a question that shows you are excited to work for the company. The most common one is usually “What team do you work on” which is perfectly OK, but you can ask anything as long as you’re friendly and inquisitive.
What Interviewers Are Looking For
Interviewers usually come equipped with a handful of pet questions of varying difficulties and focus areas. They decide on what questions to ask based on whatever experience is on your resume and the position you’re interviewing for (e.g. college graduates will have general software engineering interviews while experienced kernel programmers will have mostly system engineering interviews).
Generally speaking, interviewers are looking to see if they would enjoy being your teammate and working on a project with you. So first and foremost, stay humble and never show signs of arrogance or dismissiveness towards your interviewer because no one wants to work with a cocky bastard. They want to put you at ease in order to see how you operate at your best.
Contrary to some common myths, they’re not interested in asking brain teasers or trick questions and have no intentions to stress you out on purpose just to see how much you can handle. More specifically they’re assessing the following:
- Whether you’ve used the suitable data structures and algorithms
- How you optimized the solution as you went on
- How well you knew your programming language of choice (you only need one for all of your interviews so make sure you’re very competent with it)
- How fast did you code
- Whether you missed any corner cases
- Whether you made any syntactic errors (personally I’m lax in this area but I’ve seen interviewers being extra OCD on this so tread lightly)
- How you analyzed the time and space efficiency of your code
- Whether you communicated your thought process clearly and in a sound and logical way (Avoid fluff talk, bluffing or veering on too many tangents. Just get straight to the point!)
- How well did you respond to their hints
- Whether you were pleasant and friendly to talk to
Would you like me to provide you with regular feedback and advice on your journey to get hired at Google?
Then head to my page on Mindcrumb to start a new career journey and add me as a reviewer. You’ll be able to share your progress with me (and your friends) and I will provide you with more detailed personal advice and feedback as you progress (FREE).