Table of Contents

0. Introduction

1. Why take-home coding challenges are better than the alternatives, and you should love them

2. The drawbacks of take-home coding challenges

3. The basic types of take-home coding challenges

4. Mistakes to avoid making when given a take-home coding challenge

5. Get organized: how to plan before you write a line of code

6. Writing tests: just do it!

7. How to unlock your debugging superpower

8. Make it work, then make it pretty, then make it fast

9. How to make your code shine

10. How to take your challenge to the next level

11. How to write a kick ass README

12. Final steps before you hit send

13. After you hit send: prepare to discuss your code

14. Frequently Asked Questions

15. Conclusion

0. Introduction

Hi, I’m Jane. I’m a software engineer, but I do not have a CS degree. I actually studied fine art in college. So, how did I end up here?

In 2015, I attended General Assembly’s Web Development Immersive Bootcamp. A friend told me about General Assembly and I happened to be trying to teach myself to code. I wasn’t satisfied with my progress from reading books and working through online tutorials - I wanted to build things! After all, as an artist, I found code to be just another medium of expression, with the browser as my canvas.

I was accepted to General Assembly, and enrolled in their 12 week in-person bootcamp in San Francisco in the spring of 2015. Three months later, I had built 3 apps, with 3 different tech stacks. Then, after 3 months as a Developer in Residence at GA, I landed my first full-time job as a software engineer, more than doubling my salary from my previous career in the apparel industry. Over two years later, I’m on my third job since bootcamp and have learned a ton, not only about programming, but also about the technical interview process.

I wrote this guide because I want to help others with non-traditional backgrounds succeed on take-home challenges. Please read it, take notes, apply the material, and let me know about your results. You can reach me via email at jane@fullstackinterviewing.com.

Back to top

Share this post on →





1. Why take-home coding challenges are better than the alternatives, and you should love them

Let me start with a story:

The last time I was interviewing for a job, I had this one on-site interview…

The interview itself was scheduled for 4 and a half hours, but before I was even invited to that interview I had already had coffee with the VP of Engineering and a 1 hour technical phone interview with one of the engineering managers.

The company asked me to bring my computer to the interview, because I would be doing some live coding. I knew the interview was going to be long and grueling, so I was already nervous. I had little idea what to expect or how many people I would be meeting with.

After being grilled for an hour on my resume and work history, it was time for the live coding portion of the interview.

I took my computer out of its case, and I was ready to go.

The next interviewer came in, asked me some questions, then said, “Now I’d like you to build the homepage of our site”.

I knew that we only had a total time of about 45 minutes, with the last 5 minutes reserved for questions.

Nervously, I opened my computer, opened a new file and started typing. The interviewer was LITERALLY staring over my shoulder watching me code.

At this point, I was just thinking I needed to get through the rest of this 45 minute session. I was trying to think as fast as possible, but with the person staring over my shoulder giving me no guidance, I just froze.

After several minutes where I searched for documentation and CSS rules on Stack Overflow, the interviewer either finally sensed that I was feeling uncomfortable or determined I wasn’t working quickly enough, so decided to switch up the task. We continued with live coding, but moved on to some Javascript questions. Finally, after what felt like an eternity, our time came to an end and I was SO relieved. I could not wait for that portion of the interview to be over.

I made it through the rest of the interview sessions and left the building exactly four and a half hours later feeling mentally drained and completely exhausted.

A day or two later, I heard back from the company. They said that they hadn’t gotten enough of a sense of my coding ability during my on-site interview, so they wanted me to complete a take-home challenge.

Now, of course I was thinking, couldn’t we just have avoided all of the time spent in the on-site interview if they had simply given me a coding challenge first?

Without the pressure of anyone watching over my shoulder as I worked, I went ahead and completed the coding challenge over the following weekend. I was interviewing with a few other companies, so was on a bit of an accelerated timeline. I put a TON of effort into the challenge, really going above and beyond in every way that I could.

I sent the completed challenge to the company, and even though it was over a weekend, they reviewed it and got back to me right away. They were incredibly impressed and were eager to chat with me about next steps!

When it comes to technical interviews, I will always prefer a take-home coding challenge over a whiteboarding session. Even now, with over 2 years of professional experience as a software engineer, I still feel that a take-home challenge is a better way for me to showcase my skills and for an interviewer to assess them. Why? Because a take-home challenge is a much closer approximation to my actual day to day work as an engineer than any kind of whiteboarding session.

Though not all companies offer take-home challenges, many more are starting to in order to open up their candidate pools to engineers from all backgrounds, not just those with traditional CS degrees. My goal in writing this guide is to get you excited about completing a take-home challenge if a company gives you one. I want you to be completely set up for success when you receive a take-home challenge, and know exactly what to do and how to crush it when you get one.

I LOVE take-home challenges! They are very similar to projects you would complete in a coding bootcamp or in an online course. In the 3 times I’ve gone through the interview process over the last 2 years, I’ve completed quite a few.

Here are the 7 reasons I love them:

1. You can work at your own pace in your own development environment

2. You can showcase your practical skills

3. You have an opportunity to learn and improve your coding skills

4. You are building your portfolio and a resource for the future

5. You can get a feel for the kind of work you’d be doing and the problems you might be trying to solve at a company

6. You don’t have to miss work to complete a take-home coding challenge

7. You can easily differentiate yourself from other applicants by going above and beyond

1. You can work at your own pace in your own development environment

Unlike a whiteboarding interview or a timed coding test, you get to decide when you want to work on a take-home coding challenge. This means you can set your own schedule and work at your own pace. You don’t have someone staring over your shoulder watching you code on your laptop or on a whiteboard.

Instead, the only pressure you have is the pressure you put on yourself to finish. Also, you don’t have to stress out about remembering language specific syntax as in whiteboarding interviews, because you can always look up anything you need. Because you are setting your own schedule and working at your own pace, you can also choose when it’s time to move from one requirement to the next or when something is done. You’re also able to work in your own development environment that you are most comfortable in. Finally, with take-home challenges, when you plan properly, you have time to edit and review your code before you send it to be reviewed. Through this editing process, you can catch mistakes and even improve your code, for example by DRYing it up.

2. You can showcase your practical skills

Take-home coding challenges are an excellent way to showcase your skills and focus on what you love doing. Instead of spending time memorizing data structures and algorithms, you get to build a widget, component or small app, which is so much fun. The best part is, if you’re particularly drawn to a certain part of the stack, a certain language, or a specific technology, you can put a lot of focus on that in your challenge.

Because take-home challenges are a closer approximation to your day to day work as a developer, they are also a more realistic indicator of how you will perform in a specific role. With whiteboard interviewing, a candidate may be very good at solving algorithm problems, but not resourceful when it comes to building features or debugging. In this case, a candidate can pass an interview because they are good at interviewing, rather than because they are proficient in a certain language, for example.

On the flip side, if you’re great at building things, but have trouble interviewing, it will take much more time and energy to excel at whiteboarding interviews because you’ll need a lot more practice. Ultimately, I think take-home challenges are a win-win because both the candidate and the company are able to assess if the position is a good fit much more easily.

3. You have an opportunity to learn and improve your coding skills

Ok, this is one of my favorite reasons to do take-home challenges! Not only can you showcase your existing skills, but you can also improve them and learn new ones. Every time you build a new app, you’re getting more and more practice programming, becoming self-sufficient searching and debugging, practicing getting organized before a project, understanding how to scope tasks, and knowing when to stop working.

Also, you can use a take-home challenge as an opportunity to learn a new technology. In some cases, you will have to complete your assignment using a specific framework, language, technology or stack. If you’re not familiar with it, that’s ok! You’ll likely spend time reading and referencing docs as well as completing tutorials in order to get your project off the ground. In the cases where the technology is open-ended, but you’ve been wanting to try something new, these challenges are a great opportunity to do so.

For example, I was given a front-end challenge and had previously been using Angular as my go-to front-end framework. I was in the process of learning React, so I choose to use React for this challenge, and, having done that, I now have a much better understanding of React than when I started.

4. You are building your portfolio and a resource for the future

In my experience, many companies are ok with candidates having their take-home challenges public on Github. But, you should ALWAYS ask before making your challenge public. Also, if you do make a challenge public, it’s a good idea to exclude the company name. Many companies continuously use the same coding challenge, and they would rather not have multiple solutions available on GitHub with their name attached. This means that yes, in many cases, your challenge can live publicly on GitHub and all of your commits will count toward your beautiful green streak!

I occasionally go back and reference my own challenges when I’m looking for small examples. Once I was implementing a feature in a production app that was similar to something I had built for a take-home assignment. It was really helpful to be able to look back at my old challenge as a point of reference.

5. You can get a feel for the kind of work you’d be doing and the problems you might be trying to solve at a company

Take-home challenges are also more like the work you’ll actually be doing as a full-time developer, so doing them is great practice for your future job. A company may give you a take-home challenge that is a small-scale version of a big problem they are wrestling with or involves a key component at the crux of their application.

Here are some examples:

If authentication and permissioning are critical to a company’s product, they may ask you to build an app with specific requirements around authentication.

If the company ingests and parses data from a lot of different external APIs, they may ask you to build a small version of this type of infrastructure.

If data visualization is a key component for a company, you may be asked to visualize data in specific ways or come up with your own solutions to problems they are facing.

Also, some companies have language or framework specific coding challenges. For example, I’ve received two challenges where companies have requested that I use Ruby on Rails because they wanted to evaluate how I would work within their specific tech stack.

6. You don’t have to miss work to complete a take-home coding challenge

This is one of the best reasons to opt for a take-home coding challenge. Unlike a traditional several hour long whiteboarding interview, a take-home coding challenge can be completed outside of work hours.

I have always dreaded having to take a day off to attend an interview. In-person interviews are already stressful enough because they usually require advance preparation, and dealing with the logistics during work hours simply adds more stress. That said, you will have to build in several hours of time in your likely already busy schedule to complete a take-home challenge, but at least it will be on your own time. If you are really excited about a specific company, it should be easy to make the time to complete a challenge for them.

7. You can easily differentiate yourself from other applicants by going above and beyond

This is my favorite benefit of take-home challenges! Unlike timed coding tests or in-person interviews, the flexibility you have with take-home coding challenges allows you to easily go above and beyond. In a whiteboarding interview, you are put on the spot, so it can be hard to perform well and stand out as a candidate unless you’ve spent tons of time up front preparing. You might miss an edge case or forget about testing entirely if you’re nervous.

With a take-home challenge, you can spend more time planning ahead to ensure that what you submit will really stand out. You have time to make sure your code is properly tested, is easy to read, and flows logically. Because you can take time away from your challenge, you can work on it, then come back to it later with more clarity. It’s similar to when you’re working on a tough problem: you take a break, and you come back to the problem in many cases only to find out that it was a simple mistake causing your error.

So, how can you differentiate yourself? The possibilities are endless. For example, if you love CSS, instead of using a library like Bootstrap to style your app, you can write your own custom styles, add animations, use a preprocessor like SASS or LESS, or showcase anything else that you specifically love about the language. If, like me, you love Javascript, you can focus on the interactions on the client side, or build out your app’s server side using Node.js. If you love writing tests, you can focus heavily on testing best practices and ensure that your app has full test coverage. If you’re a fan of APIs, you may be able to build one as part of your app or pull and transform a bunch of data from an external API.

These are just a few examples, but the list goes on and on, and it’s really up to you to decide what to focus on and how to showcase your strengths. But having the ability to decide in the first place is one of the huge advantages of take-home challenges.

Back to top

Share this post on →





2. The drawbacks of take-home coding challenges

Full disclosure, there are two main drawbacks, both related to time management. However, I firmly believe that the positives outweigh the negatives.

1. It’s very difficult to juggle multiple challenges at once

2. Take-home challenges can be very time consuming

1. It’s very difficult to juggle multiple challenges at once

First, it’s very difficult to juggle multiple challenges at once, especially if you are balancing job hunting with a career or other responsibility.

If you’re working full-time and simultaneously interviewing for a new position, you may have experienced this before. Here’s the scenario: company A sends you a take-home challenge and you start working on it, only to be sent another challenge from company B, who you are also interviewing with.

If you’re in the position of juggling multiple challenges, though, remember that this is a GOOD thing! It means that companies like you and are excited about you as a candidate.

Some companies will include suggested completion times with their challenges, while others will simply ask you to get back to them by a certain date, often within a week. To be honest, I often ignore suggested completion times because they are usually very unrealistic for me. But, in reality, we’re all busy. If you find yourself in the position of juggling multiple challenges OR you simply have other obligations and know you will not be able to complete a challenge by the deadline, you will need to ask for more time.

Learning how to push back on timelines is an important skill to develop as an engineer, so if a company’s timeline seems unrealistic, you are more than welcome to spend more time on a challenge. However, if there is a hard deadline and you are unable to finish the challenge by that deadline, you MUST email your contact to let them know that you will be turning in your challenge late. For many companies, asking for more time is not a problem, but you need to correctly manage expectations as well.

You can also check out the FAQ section, where I address this scenario and other questions.

2. Take-home challenges can be very time consuming

Second, take-home challenges can be very time consuming, especially if you want to impress your interviewers (TIP: you do). Like I said before, some companies will give you a suggested time. For smaller projects, this is usually fine, but for larger projects that require an entire app to be built, I usually ignore those time parameters. Why? Three reasons:

I almost always find the time suggestion to be unrealistic

Because I like to spend the time to get organized before I write a line of code, write a README (which you’ll see more on later), and take care to review my code before submitting it, this adds to the total amount of time that I usually spend on the challenge as a whole. Sometimes, actually writing the code won’t take that long, but that is only if I’ve had experience with the type of task and framework or language required.

For example, I once got a coding challenge that had a time suggestion of 4 hours. The challenge required building a single page app with a server that pulled data from an external API. As someone who is more familiar with front-end development and less familiar with building APIs, I spent extra time getting the API endpoints to work the way I wanted. I also chose to build this app in the framework the company used, which I was less familiar with, which meant I needed to spend some time reading documentation and working through tutorials. This was a great learning experience, but took me more than 4 hours.

In my day-to-day as an engineer, I’m rarely building new apps from scratch

Most coding challenges require you to start from scratch, but this is not a practice that a typical developer does everyday. So, there is often some time needed to reacquaint yourself with installation and set-up steps. Sometimes these steps can cause headaches when they are unfamiliar or hard to debug.

In order to impress the interviewer, I will go above and beyond the requirements

If I want to differentiate myself from other applicants with a coding challenge, I am likely going to spend longer than the time that is suggested. Why spend the extra effort, you ask? Well, if you are really interested in a company, one of the best ways to show your interest and excitement is to go above and beyond on a coding challenge. Especially if you are newer to programming, companies like to see that you’re willing to take on a challenge and learn something new!

3. The basic types of take-home coding challenges

There are several different types of coding challenges that companies assign based on the types of roles they are hiring for. For example, a company may assign a different challenge depending on whether they are hiring a front-end engineer, a full-stack engineer, or a back-end engineer. Here are some examples of the different types of coding challenges you can expect, depending on the role:

Front-end challenges:

Build a user interface for a specific type of interaction Box-to-Box Drag and Drop Create two large squares on the screen and fill one of them with smaller squares. The design, color, and layout is completely up to you, but make sure that each small square is uniquely identifiable using text, color, etc. Requirements: - Any small box dragged and dropped over another small box should swap positions with the other small box - Any small box dragged and dropped on the other large square should be moved to that square and swapped with any small box already there - There should be a button that allows the user to reset the small box positions - There should be a button that allows the user to randomize the layout and positioning of the small boxes within both large squares The final project needs to work in the latest stable versions of Chrome and Safari. Once completed, compress all files into a zip archive and send it back. Example 1: Drag and Drop



Display data from an external API in a client-side app Create a web page that shows a photo in a lightbox view, with the ability to move to the next/previous photos and display the photo title. You can use any public API that returns photos (i.e. Flickr, Instagram, Google Image Search, Yahoo Image Search) It should run without errors in the latest versions of Chrome, Safari, Firefox and IE. Please send the code (Github repos are fine) and a URL where the working lightbox can be seen. Example 2: Photo Lightbox App



Build a game Tic Tac Toe App Requirements: * Build a two player tic tac toe app where a game is played by alternating clicks until the game is won by X, O or is a tie. * Include a reset button so that when a game ends, the board can be cleared and a new game can begin. Bonuses: * Make the board fully responsive * Allow for more than 1 game to be played simultaneously Example 3: Tic Tac Toe Example 4: Connect Four





Full-stack challenges:

Build an entire app with persistent data Example 5: Email Preferences App

Pull data from an API and visualize it



Back-end challenges:

Build an API Example 6: Movie App



For the rest of this guide, I’m going to use the Tic Tac Toe challenge above as an example of implementing the process I outline. You can view the source code here.

Back to top

Share this post on →





4. Mistakes to avoid making when given a take-home coding challenge

There are several mistakes you can make with take-home challenges. Some of these are small mistakes that are easily correctable, while others will leave you frustrated and unable to finish your assignment. I want to address these mistakes first, so when you’re given a take-home challenge, you know exactly what not to do. If you’ve completed a take-home challenge before, you might have even made one of these mistakes in the past. But, don’t worry - mistakes are a part of the process and everyone makes them. Knowing these ahead of time will simply allow you to evaluate whether a given challenge is right for you and give you more confidence when you do move forward with one!

Here are the 8 mistakes you can make:

1. Taking on an assignment when you aren’t quite prepared or don’t quite have the skillset for it

2. Time management and scope creep

3. Trying to learn too many new things at once

4. Making too many assumptions

5. Blindly copying code without understanding how it works

6. Submitting sloppy code

7. Leaving too many comments in your code

8. Starting to code right away

1. Taking on an assignment when you aren’t quite prepared or don’t quite have the skillset for it

This is possibly the biggest mistake you can make. As an engineer, it is very important to know your own limitations - you should know what your strengths and weakness are. Everyone, even the most experienced engineers, still have room to learn and grow because there are always new technologies popping up or new languages and paradigms to learn. An experienced engineer will also not be afraid to admit when they don’t know something, and this is a very important skill to develop and demonstrate.

A take-home coding challenge can end up being a frustrating waste of time if you don’t have the right skill set for it. For example, I was interviewing with a very small start-up, and they were looking for an engineer who could do everything. When they sent me their coding challenge, it was a pure back-end challenge - it required database administration and building APIs. I had mostly been working on front-end stacks, so when I read through their challenge, I realized that it would be a stretch for me to complete it at all, let alone in a reasonable amount of time. Getting a coding challenge that didn’t fit my skill set helped me realize that this role wasn’t the best fit for me, so instead of telling myself to “power through”, I emailed them to let them know that I didn’t think the position was a good fit. I felt good about this decision, because ultimately it actually saved everyone time.

Would I have learned something from working on their challenge? Yes, absolutely. Would I have spent hours reading documentation and searching to understand best practices? Also, YES. In this case, the total time it would have taken me to complete the challenge outweighed the positive benefits. I would have learned a lot, but I also would have spent forever trying to figure out the best way to organize my app and been banging my head against the wall debugging (or just figuring out how to debug) weird errors that I had never seen before.

2. Time management and scope creep

Time estimation is one of the hardest problems in programming, and even experienced engineers struggle with it. I had a boss who explained a simple formula for estimating how long a task will take: take however long you think it will take and double it. So, if you think something will take you a day, give yourself two days. If you estimate a project will take you two weeks, it may actually take four weeks. I like this philosophy because in programming, as in life, there are always unpredictable factors.

This plays into take-home challenges in a couple of ways. First, some challenges come with “estimated time”. Like I said earlier, I usually ignore these, as they are rarely based in reality. Another thing you can do is follow my old boss’s principle and actually double the estimated time. Then, keep track of how long you actually spend and compare the two at the end.

Second, some challenges are open-ended. For example, they might ask you to build a client app using an external API, but not provide any specific requirements beyond that. Many people, especially newer developers, will want to add tons of features because they think it will be impressive. Actually, it’s more impressive if you keep the scope relatively narrow, but finish everything you set out to do. In this situation, it’s better to do one thing really well than to do a million things half-assed. You could spend a lot of time building a really beautiful and clean user interface that has full test coverage, rather than adding a bunch of small features that don’t really work well or work together.

A good question would be: what counts as “going above and beyond” versus what counts as “scope creep”? My rule of thumb would be if your idea accomplishes or improves on the requirements of the assignment, that is likely a good idea, but if it seems tangentially related or “just cool”, it’s probably scope creep. But, as I describe later, always make it work first.

3. Trying to learn too many new things at once

While a take-home coding challenge can be an excellent opportunity for learning, it is possible to take on too much learning. What does that mean? Well, if you’re given a challenge where you must use a specific language or framework, but you’re not familiar with it, don’t add additional complexity by setting out to learn something new on top of that. For example, if you are using a new backend framework for a full stack app, stick to a frontend framework that you’re already comfortable with.

If your challenge is language/framework agnostic, but you’ve been itching to try out some new technology, pick JUST ONE to experiment with. Between reading the docs, getting your challenge properly set up and getting used to any new syntax, you will have your hands full. Even learning one thing will eat up a lot of your time, so I would highly suggest limiting yourself to one new piece of technology per challenge.

4. Making too many assumptions

Do you remember the phrase “Never ASSUME, because when you ASSUME, you make an ASS of U and ME”? Well, it’s true. As a developer, if you make too many assumptions, you are bound to build an application where the requirements are off, or the user experience is bad. When given a set of requirements for a take-home challenge, ALWAYS take the time to review the requirements and make sure you fully understand them. And, if you have any questions at all, always ask.

First, this shows that you are willing to ask for help when you don’t quite understand something, an important trait for a developer to demonstrate. Second, many companies will intentionally give you product requirements that are vague or not fully fleshed out in order to see how you react in these situations. They are actually testing your ability to make sense of requirements that may have gaps in them. So, when in doubt, ask questions. Asking questions is also a signal that you are engaged and interested in the challenge.

5. Blindly copying code without understanding how it works

There will probably be at least a few cases where you need to search for a solution to a bug or problem in your code. Using references you find is a great idea as long as you don’t engage in cargo cult programming.

I know, it’s hard to resist copying and pasting code when you’ve found the perfect solution to your obscure problem on a StackOverflow post you came across on your 5th Google search. However, when you copy code, you not only need to understand how it works, but you will likely also need to explain it later, so blindly copying something is NEVER a good idea. NEVER. SERIOUSLY PLEASE JUST DON’T DO IT. Also, when you just copy and paste random code, it can look out of place, mess up the flow of your code, and make your submission look less impressive.

Instead, you should first make sure you understand what the code is doing by playing around with it in a repl or console. Then, rewrite it to fit within what you’ve written. Finally, test it out within the code you already have and make sure it works. People make mistakes, and you never know when you’ll encounter a typo or edge case that was not considered, so testing is super important here.

6. Submitting sloppy code

Another mistake you can make with a take-home challenge is submitting sloppy code. If your code is disorganized or hard to read, you will definitely not move on to the next interview round. Take pride in your code and make it beautiful.

What exactly makes your code sloppy? A few things:

Improper indentation

Really long lines

Log or debugger statements

Using improper casing

Commented out code

Indentation and long lines of code are especially important to keep in mind, because these contribute to readability quite a bit. If your code is hard to read simply because of formatting, it will take more time for the engineer reviewing it to read through it. Also, if you aren’t already in the habit of writing clean code, a company might assume that on top of mentoring you technically, they will have to help you get organized as well.

Log statements and improper casing are less important, but you should treat your coding challenge in the same way that you would treat production code, so try to keep things consistent and avoid useless code.

The same applies for commented out code. Commenting out code in your app in order to test things as you work can be a useful strategy, however, you’ll want to make sure you remove any commented out code before submission. Commented out code in production codebases is like cobwebs in a dusty attic - no one wants to weed through them to get to what they are looking for.

Speaking of comments, they can be incredibly useful, but your code shouldn’t be so complicated to read that it requires comments everywhere. Don’t make the same mistake I did when one time I submitted a coding challenge with 27 lines of comments for 67 lines of Javascript. That’s 40% comments! I literally wrote comments before every variable and function definition. If you get naming right (explained below in How to make your code shine), you won’t need nearly as many comments, and you can move on with your life.

Also, please don’t ever leave TODO comments in a coding challenge. If there’s something you couldn’t finish or get to, a TODO comment is not the way to handle it.

You can read more on comments in How to use comments effectively in your code below.

8. Starting to code right away

One last mistake you can make, is to jump in and start coding right away. I guarantee if you do this, you will regret it. Why? Two reasons:

Without proper planning, your code will suffer

Without first getting organized and making sure you fully understand ALL of the technical requirements, you may find yourself missing edge cases or rewriting parts of the functionality. I know it seems counter-intuitive, but you will actually SAVE yourself time if you plan ahead.

You will spin your wheels trying to get your app set up properly

Especially for newer developers, initial app setup can be one of the hardest parts of a take-home coding challenge. It’s not something you do every day, so it often takes some research and reading documentation to get reacquainted with the process and ensure you’re going about it in the best way.

So, there you have it - a summary of mistakes to avoid making. You’ll find that a lot of these are also applicable to your day to day work as a developer. In the next section, we’ll dive into further detail on how to get organized before you write a single line of code.

Back to top

Share this post on →





5. Get organized: how to plan before you write a line of code

So, you may be thinking, ok, I’ve gotten my coding challenge, I’ve gone through your list of mistakes and haven’t made one yet, so now it must be time to write some code! Well, you’ve almost got it. Yes, it is time to get to work! But, it’s NOT time to write any code YET.

Why?

Because, as you’ll see, a lot of the work actually happens before you write a single line of code. This may seem counterintuitive, but the more time you spend up front planning, the less time you will spend writing code. This is called front-loading the work, a technique I learned from Ramit Sethi.

So, now you have your coding challenge in hand and you are ready to get started with the planning process. Here are my 6 suggested steps:

1. Understand the requirements and ask any questions

2. Identify technical decisions you need to make

3. Technical design & whiteboarding

4. Test plan

5. App setup plan

6. Organize your tasks

1. Understand the requirements and ask any questions

First, you need to make sure you completely, absolutely, 100% understand the requirements of the project. Do the product requirements actually make sense? Do you know all of the views or components you will have to create for the UI? Do you know the API endpoints you will need to create or pull from?

This is the step where you’ll need to think about all of the big picture questions about the requirements you’ve been given. If any part of the requirements are unclear, it is up to you to reach out to your contact and ask questions. Even if you have a question about the technical requirements, that is fair game. For example, I once received a coding challenge where I was told to use vanilla Javascript. I was surprised because most coding challenges I had done allowed libraries or frameworks so I emailed to double check. I’m glad I checked because it made their focus on pure Javascript skills crystal clear.

Also, sometimes companies will purposefully make their requirements vague, in order to see how you approach the problem. In these cases, it is always best to ask questions as it shows you are thinking about the problem and not just making assumptions and building an app to a vague spec. Companies want to see that you will speak up and even participate in building the requirements. In some cases, companies do not have product managers, so making sure the engineer is able and willing to ask questions and think through challenges from another perspective is very important.

Here are the requirements for the example Tic Tac Toe app:

Tic Tac Toe App Requirements: * Build a two player tic tac toe app where a game is played by alternating clicks until the game is won by X, O or is a tie. * Include a reset button so that when a game ends, the board can be cleared and a new game can begin. Bonuses: * Make the board fully responsive * Allow for more than 1 game to be played simultaneously

2. Identify technical decisions you need to make

Once you’ve gone over the requirements in detail and made sure everything makes sense, your next step will be to identify the technical decisions that you need to make. Making a list of all of your technical decisions up front and thinking about them before you’re in the middle of building your app will help you immensely. Not only will it cut down on time figuring things out later, but it will allow you to make big picture decisions up front, as opposed to trying to focus on both the big picture and the small details at the same time.

All coding challenges are different, and in some cases, you may be required to use a specific technology, while others will allow you to use any tools you want. For challenges where you have a blank slate, it is best to choose technologies that you are already comfortable with. This will speed up the process because you won’t be struggling to learn as you go. If you do want to use a coding challenge as a learning opportunity, I would recommend only choosing one new technology to learn and implement. For more on this, re-read mistakes to avoid making when given a take-home coding challenge.

For coding challenges where you are required to use a specific technology, and it’s one that you either aren’t familiar with at all, or haven’t touched in awhile, you should expect to spend some time going through tutorials and reading documentation. The last time I was interviewing, I received a challenge that required Ruby on Rails, which I hadn’t worked with in 2 years. Before I jumped into building the app, I reviewed the documentation and re-learned how to setup a Rails app, which allowed me to rediscover some built in scaffolding I could use to save time setting up my app.

Here are the technical decisions I made for my Tic Tac Toe App:

- Decided on technology (React) - Decided to use a generator (create-react-app) - Decided on React components (square, row, board, and app) - Decided on testing framework and language (Jest and Enzyme, comes pre-built with create-react-app)

3. Technical design & whiteboarding

After you identify the technical decisions you need to make, it’s time to plan out the rest of your app. Are you building a front-end app that requires wireframes? Or, are you working on a back-end app where you need to plan out your data models and their relationships? Or, are you building an API and need to figure out the endpoints? Do you need to write an algorithm or AI for a game?

For anything that you need to draw out, now is the perfect time to do that. Thinking through these decisions at the start serves two purposes:

You’ll be able to reference these drawings and your original plan while you’re building your app, so if you get stuck at any point, you can always come back to your notes

Later, when you are having a discussion with an engineer about your coding challenge, you can use these notes as a reference when they ask you why you made certain design or architecture decisions

Newer developers often get caught up in building the app, but later, have a hard time explaining the WHY behind their decisions. Planning in advance will not only help you iron out those decisions sooner, but it will also better prepare you for being able to articulate your decisions later on in the interview process.

Here is the technical design & whiteboarding I did for my Tic Tac Toe app:

Once you’ve thought through and answered some of the bigger design and architecture questions for your challenge, the next step is research. If you’re planning to use a new technology or something you’re a bit rusty with, use this time to search for documentation and other resources. Are you worried that your chosen front-end framework will make app setup hard? Maybe there is scaffolding that you can use. Does your challenge require something that you might need a Ruby gem or an NPM package for like authentication or security? Find it now! Do you need to get an API key so you can access data or play around with an API? Get it!

Again, by working through these technical todos and kinks now, you’ll save yourself from having to stop working on your app to go down a rabbit hole later just to find a specific tool that you need. Now, that may inevitably happen anyway, but minimizing this will save you time in the long run.

4. Test plan

Another very important step to take before writing a line of code is developing a test plan. I learned this while working at Eventbrite, where we created spreadsheets with test plans that other team members reviewed before we began work on a new feature. Although you won’t get peer feedback on this test plan, it will help you look at the challenge from a different angle, making sure you’re meeting all of the requirements. By thinking through and writing out a test plan before you start coding, you are able to brainstorm possible edge cases that you should account for in your code and you will use this as a basis for testing your app later.

More on how to do this in the next section, Writing Tests: Just Do It!.

5. App setup plan

If you’re starting an app from scratch, figure out if there are any generators you can use to make your app setup easier and faster. Application setup is one of the hardest parts of take-home coding challenges because it’s something that developers do rather infrequently and best practices are always changing, so it’s easy to forget how to do.

Also, when setting up an app with a specific combination of technologies for the first time, it can be challenging to get everything configured and working together properly. The absolute worst thing to get stuck on is configuring something related to app setup like a bundler or linter, so if there is a tool available to you with specific things you want already built in, feel free to use it!

Some of you might be thinking, but isn’t using a generator cheating? Unless your coding challenge explicitly says you must do everything yourself from scratch, absolutely not. Using a generator not only shows that you did your research, but also that you are resourceful. The key is understanding what the generator is doing for you and being able to explain it. Also, if you do use a generator and it creates extra files or directories that you don’t end up using, you should delete them to make your overall app architecture cleaner and easier to understand. Just go file by file to ensure you are not deleting anything that is required to run the app!

If you are not using a generator, reading documentation and finding working examples are the two most important steps you can take. Being able to play with a working example and compare it to your own app will help you if you get stuck.

6. Organize your tasks

The last step before you start coding is to breakdown and organize your tasks. Breaking down your tasks is essential because it will help you stay on track as you’re working on your challenge and it will give you a game plan for execution. Note that you shouldn’t be a perfectionist here because there will always be unexpected bumps in the road.

Here is how I broke down the main tasks for my Tic Tac Toe app:

- Understand requirements - Choose technologies - Brainstorm test plan - Hello World app setup - Build board with HTML/CSS - Implement Tic Tac Toe gameplay with Javascript - Add reset button - Make board responsive - Add ability to add additional boards - Error handling & tests - Code cleanup - README

Some of these tasks can be broken down even further into smaller steps. For example, in order to implement the Tic Tac Toe gameplay with Javascript, I will need to:

- Add a click handler to each square that logs a message - Get click handler to add an X to the square that is clicked - Get clicks to alternate between X and O - Don’t allow a square to be clicked more than once - Implement a function to find the winner and end the game - Handle a tie game

Once you’ve broken down your tasks, you should choose a tool to keep track of your workflow. This can be as simple as pen and paper or you use an app. I personally really like Trello. I start by creating 4 buckets within a board: To-Do, In Progress, Blocked, and Done. I then list all of the main tasks in the To-Do section. As I work, I move tasks across the board like so:

This process serves two main purposes:

Having your tasks listed out helps you feel productive as you complete them because you can essentially check them off by moving them across the board

Organizing all of your tasks in one place gives you a clear roadmap, so if you get stuck on a task and need to come back to it later, you know exactly to work on next

Phew, you’ve made it through this long section! As you’ll see, all of this planning will become more important both as you’re coding your challenge and also later when you’re preparing to discuss your challenge with your interviewer. If you follow these steps, you’re guaranteed to feel organized and set up for success.

Back to top

Share this post on →





6. Writing tests: just do it!

I remember when I first learned about testing at General Assembly. The idea seemed useful, but at the time, I was in bootcamp mode, so I concluded that testing just wasn’t something I had to prioritize for my projects. Testing can be overwhelming because there are so many different types of tests: acceptance tests, integration tests, and unit tests, not to mention test driven development vs. ad hoc testing.

I can’t tell you how many times in my engineering career that I’ve been saved by automated tests. One time, I was working on removing a dependency from a very large codebase. I thought I had removed all of the uses of the library, but when I pushed my final changes to production, I broke 30 acceptance tests! Yeah, so despite being detail oriented and thinking I had updated every use of the library, I actually had missed 30 cases. So, tests saved me from pushing many bugs to production.

Tests are also great because they allow you to be a more confident engineer. You can actually move faster when you have a test suite in place because you can always run the tests to check if your changes broke anything, and if they did, fix them. When you don’t have any tests, it can be very scary making any changes to your code at all, especially business critical code.

So, now that I’ve made a case for writing tests as a professional engineer, why should you include them in your take-home coding challenge? In addition to all of the benefits I already listed, your tests will make your submission shine.

First, adding tests shows that you know or are willing to learn another technology/framework. It also demonstrates that you take ownership of what you’re building, because you are taking responsibility to make sure it works. Testing also shows that you’ve considered edge cases, which many newer engineers often overlook. Finally, though many companies, especially larger ones, have separate QA teams that handle testing, many startups do not, so being able to write and test your own code (or even write tests for other people’s code) is a very valuable skill.

Many companies take tests very seriously, and some will not tell you that they expect tests for your coding challenge, but will automatically reject you if you leave them out. Therefore, my recommendation is to write tests no matter what when given a take-home challenge. Not only will it make you a better developer, but for companies that were not expecting tests, you will stand out even more!

So, you’ve planned out your app on a high level and thought through architectural and design details and now you are ready to start working. How do you go about writing a test plan? Here’s my 80/20 suggestion for how to come up with the right test cases:

1. Test the happy path

For my Tic Tac Toe app, the happy path is starting with an empty board and playing a game until X wins.

2. Think about variations on the happy path

A variation on the happy path would be if O wins or if there is a tie game.

3. Think of edge cases

An edge case would be if a player tries to play a move in the same square more than once.

4. Test anything that is complex

The algorithm to find the winner is the most complex part of this app.

Here’s my sample test plan:

- Test that the initial state of the board is correct (i.e. board is visible and empty) - Test that a move can be played - Test that moves alternate between X and O - Test that a move can be played to a square only once - Test that a winner can be found in a row - Test that a winner can be found in a column - Test that a winner can be found in a diagonal - Test that a draw can be found

Tests are also great because once you’ve written one, you can often use that as the base for your next one. In the code below, I first test that a move can be played in my Tic Tac Toe game, then I check that a move can be played in the same square only once. To write the second test, I simply started with the code for the first test and added to it to test for that specific case. This makes writing tests super fast, as once you’ve figured out the first test you can use that as a base for your remaining tests.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 it ( 'plays a move' , () => { const board = mount ( < Board /> ); expect ( board . find ( '.square' )). toHaveLength ( 9 ); expect ( board . state (). turns ). toEqual ( 1 ); const squares = board . find ( '.square' ); squares . at ( 0 ). simulate ( 'click' ); expect ( board . state (). turns ). toEqual ( 2 ); expect ( squares . at ( 0 ). text ()). toEqual ( 'X' ); }); it ( 'plays a move to the same square only once' , () => { const board = mount ( < Board /> ); expect ( board . find ( '.square' )). toHaveLength ( 9 ); expect ( board . state (). turns ). toEqual ( 1 ); const squares = board . find ( '.square' ); squares . at ( 0 ). simulate ( 'click' ); expect ( board . state (). turns ). toEqual ( 2 ); expect ( squares . at ( 0 ). text ()). toEqual ( 'X' ); squares . at ( 0 ). simulate ( 'click' ); expect ( board . state (). turns ). toEqual ( 2 ); expect ( squares . at ( 0 ). text ()). toEqual ( 'X' ); });

You’ll notice that this strategy produces duplicate code. I specifically chose not to DRY up the code here for the sake of readability, but tests can also present a great opportunity for refactoring. So, now it’s your turn. Think about your app and, as a baseline, think of 5-10 tests that you can write.

Back to top

Share this post on →





7. How to unlock your debugging superpower

One of the most important skills as a developer is looking up documentation and finding solutions to tricky problems. Like any skill, this is something that you can improve with practice. In this section, I’ll walk you through 5 tips for taking advantage of the wealth of information online while working on your challenge.

Here are my 5 tips:

1. Read the docs

2. Follow best practices

3. Search with keywords

4. Pay attention to the details

5. Speed up your trial and error feedback loop

1. Read the docs

This may seem obvious, but reading the docs is so important! Documentation is the first place you should look when trying to answer any question. I like to say that programming is mostly reading with a little bit of writing mixed in.

And when I say read them, I mean it! Don’t just skim them. As developers, we are often in a hurry to build things and solve problems, but this usually results in misunderstandings and miscommunications. If you spend the time to thoroughly read documentation up front, you’ll better understand and internalize how the technology works. This doesn’t mean you have to read the entire documentation cover to cover before you start programming, but find and read the sections that are relevant to what you’re working on.

Because I used create-react-app to setup my Tic Tac Toe app, the create-react-app docs were the first place I looked when I started setting up tests. I searched for “testing” within the first page of the docs using cmd + F and found a link to more specific testing docs.

2. Follow best practices

When you read the docs, pay attention to the best practices. Best practices are called “best” for a reason - they are usually created and put in place by the people who’ve built and know the most about the technology, and are suitable for most use cases. Also, following best practices ensures that troubleshooting problems you encounter will be easier because other developers have likely run into those same problems already.

For my Tic Tac Toe app, I used create-react-app’s suggested testing setup: Jest, Enzyme and jsdom. I managed to get Jest and Enzyme set up fairly easily, but when it came time to write and debug tests, jsdom was new to me. Most of my front-end testing experience has involved running tests through selenium, which opens a browser and allows you to watch the tests running.

Jsdom is a headless browser implemented completely in Javascript, so it functions slightly differently. I found that putting a debugger in a test would not just stop the test as I was used to, and I needed to do some searching to figure out how to do that. It was a fairly painless process, due to the fact that many other developers had encountered a similar question.

3. Search with keywords

This brings me to the importance of searching well. Using the right keywords and getting specific can make or break your ability to find the information you need when working to solve a problem.

For example, these three searches yield very different results using Google:

How to use the debugger

How to use the javascript debugger

How to use the javascript debugger with jsdom

As expected, the results start more broadly and then narrow down as I add more detailed keywords. For the first search, the first result is a post from drjava.org, which is far from what I’m looking for. For the second search, the first result is specifically about javascript debugging - I’m getting warmer. For the third search, the first result is actually the jsdom docs, which hammers home the point that you can find almost everything you need in the docs! Feel free to try those searches yourself to see the difference in results.

Overall, remember to be specific in your searches. Is it possible to be too specific? Actually, yes! Sometimes when you get application errors, there will be pieces of those errors related to your app, like a variable name or a stack trace. In those cases, you’ll get the best results by removing the specifics and searching for the more general error message.

4. Pay attention to the details

In the same way that getting specific helps you in searching, paying attention to the smallest details will take you far as you’re working to solve problems. Sometimes the tiniest change will make the biggest impact!

For example, as I was trying to get a debugger working with jsdom, I found this Github issue with Jest. When I find a GitHub issue that might be useful, I usually scroll down to the bottom to see the most recent comments, since those are often the most relevant. Reading through starting from the bottom, I found that someone else was using create-react-app, and had added a couple of flags to their test script. I tried adding these to my app, and voila, my tests ran with a note that the debugger was listening.

5. Speed up your trial and error feedback loop

When you’re debugging something, it’s important to pinpoint exactly what you are trying to solve in order to search most effectively. It can be easy to get caught in an infinite loop of StackOverflow posts or go down rabbit holes that end up having nothing to do with what you’re debugging. Reading error messages carefully comes into play here.

For example, as I was writing my first test for my Tic Tac Toe app, I tried to write an expect statement, and got the following error:

FAIL src/App.test.js ● plays a move TypeError: expect(...).length is not a function at Object.<anonymous>.it (src/App.test.js:35:33) at new Promise (<anonymous>)

Reading the error message, I could see that .length was not the correct function for my expect statement. The first line in the stack trace also points to exactly what line and character are causing the error. So, armed with this info and a working debugger with jsdom, I was able to stop my test just before this expect statement and play around in the console until I found the correct syntax.

First, I was able to see that my board had mounted, and the squares were there. When I typed board.find('.square').length , the result was 9 . So, now it seemed like my expect statement was just written incorrectly.

I then searched for enzyme length , which took me back to the enzyme docs where I found an example expect statement with length:

expect(wrapper.find(Foo)).to.have.length(3);

I tried this in the console, but got another error:

Uncaught TypeError: Cannot read property 'have' of undefined

This confirmed that it didn’t like the .to .

Remembering that I was not only using Enzyme, but also using Jest, I googled jest-enzyme length . I then found this hackernoon articlewith an example expect statement that looked like this:

expect(wrapper.find('.ReactCodeMirror')).toHaveLength(0);

When I tried this syntax in my console, there was no error, so I updated my code and re-ran the test. AND IT PASSED!

Stopping your code right before an error is occurring and being able to test different ideas at that exact point in the code will allow you to debug more seamlessly and prevent you from going down one of those rabbit holes.

Though I often use a combination of documentation, GitHub issues, and StackOverflow to answer questions, there are tons of other great resources available like blog posts and tutorials. Figure out your learning style and find what works best for you. If you find a resource that isn’t approachable because it assumes too much knowledge, keep searching until you find one that makes sense to you. The beauty of the internet is the sheer number of resources available.

Now that you’re armed with the tools to solve any problem you run into, it’s time to focus on making your coding challenge work!

Back to top

Share this post on →





8. Make it work, then make it pretty, then make it fast

The title of this section sums it up pretty well, but when you’re working on building out your challenge, you should follow these 3 steps IN THIS ORDER:

1. Make it work

2. Make it pretty

3. Make it fast

1. Make it work

Of all of the sections in this guide, this is one of the most important ones, so pay close attention. When you’re given a take-home coding challenge, no matter what you do, the most crucial part of the challenge is to make it work. If you submit an app that has a nice UI, that will not matter if your app does not work or meet all of the requirements. Because building features to spec is a key aspect of your future job as a developer, you first and foremost need to focus on the functionality of your app and prioritize that above all else.

This is also key if you are low on or run out of time. Coding challenges can be a lot of work, especially if you want to go above and beyond to ensure that you make it to the next interview round. But, I can guarantee that you will not make it to the next round if your app doesn’t function properly or is missing some key components. So, if you’re building a front-end app, this means focusing on making it work first, and styling/UI last. If you are building a back-end or full-stack app, focus on making it work before trying to refactor your code into the most elegant solution, and only then worry about optimization.

Even if you end up without any time to go back and refactor your code or style your UI, having a working app to present is more important. You can always talk to the interviewer about how you would improve your app and refactoring some of your code might even be part of the next round of interviewing.

2. Make it pretty

Make it pretty has two interpretations here. One is making the code pretty and the other is making the UI pretty. Making the code pretty can be done in several ways. First, ensure indentation is consistent and your code is readable. Second, if you got something to work in a quick, hacky way, think about how you can refactor it to be a more elegant solution without overcomplicating it. For example, are you using a for loop when you could be using map ?

If you’re doing a front-end or full-stack challenge, you can also make the UI pretty as part of this step. Whether you use a library or write your own custom styles for your app, making the UI look good will show your interviewer that you’re taking the user experience into consideration when building a feature. For some more front-end focused challenges, you’ll be given a specific mockup to match. In these cases, making sure you’re detail oriented down to the last pixel is incredibly important. Part of your role may involve translating mockups from designers into user interfaces, so companies want to get a sense of how you approach those types of tasks.

3. Make it fast

Once you’ve made your app work, made it pretty (in the code, UI or both), it may be time to make it fast! This is where understanding performance and BigO notation comes in handy. You should take a look at your code and see if there are any areas where increasing the scale might be an issue. For example, are you using a double for loop somewhere? What if the arrays you’re looping over become super long? If you think about these kinds of edge cases, you can then come up with plan to improve your code. Taking something that would have been running O(n) and making it O(1) or O(logn) will show that you’re thinking about performance when you’re building things.

If you do run out of time, and you aren’t able to complete all of the requirements, or you generally have some ideas for how to improve your app, see the FAQ section at the end of the guide for how to handle those cases.

Back to top

Share this post on →





9. How to make your code shine

When given a take-home coding challenge, many people think about how to build an app that works, but stop there. In this section, I’ll go over things an interviewer/engineer reviewing your code will look for, so you can take your challenge to the next level and make your code shine.

When an engineer is reviewing your code, they will look for several different things. They will likely try to run the app to play around with it and see it working. If you’ve deployed it (using something like Heroku), that’s great, otherwise they will try to run it locally. After that, they will delve into the actual code, looking to see how you organized your app architecture and reading code in individual files.

There are several things you can do to make your code stand out. You want your code to be:

Readable

Easy to follow

Well organized

Clean (properly indented, free of syntax errors and unnecessary whitespace)

If you pay attention to these key details as you work, you:

Will be able to better understand your own code later

Will show that you are an engineer who takes pride in the craft of code, and people will want to work with you

Will become a better engineer

Won’t have to spend a ton of time at the end “cleaning things up”

These are the basics that don’t take much effort outside of mindfulness to get right. Now let’s talk about 3 of the more evolved code style considerations:

1. How to name things (the second hardest problem in programming)

2. How to use comments effectively

3. How to format your code as you write it

1. How to name things (the second hardest problem in programming)

Naming is one of the hardest problems in programming. When I first started in my front-end development role after leaving General Assembly’s bootcamp, I often struggled to name variables, functions and CSS classes. Over time, I learned how to avoid spending too much mental energy coming up with names. Here’s what I’ve learned:

One of the keys to naming things is to make sure you’re naming them in a way that another developer who is unfamiliar with the code can easily jump in and understand. Many people have heard stories about weird naming conventions from original source code. Sometimes people even name things they build after themselves. (This is the worst, and everyone who encounters your code in the future will hate you, so please don’t do this!)

One way you can think about naming is very literally. For example, in my Tic Tac Toe app, I simply named my CSS classes after the components: board, row, and square. For more advanced techniques for class names, check out BEM.

For functions, the same rule applies. Think about what exactly the function is doing (and, while you’re at it, do your best to make sure your functions are only doing one thing, as this helps with naming and general readability). Is the function checking whether there is a winner on a row of a Tic Tac Toe board? Then a great name would be checkRow . Is your function handling a click on a square of the Tic Tac Toe board? Then a great name would be handleClick .

Now you can start to see a pattern forming! Thinking about your code this way will not only make it easier for you to understand later (when you have to explain it to another developer), but it will also make it easier for the person reviewing your code to understand it and even enjoy reading it.

Naming Examples

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 _checkWinner ( board ) { let diagWinner = this . _checkLeftDiagonal ( board ) || this . _checkRightDiagonal ( board ); return this . _checkRows ( board ) || this . _checkColumns ( board ) || diagWinner ; } _resetBoard () { this . setState ( this . _getInitialState ()); } _getCurrentPlayer ( state ) { return state . turns % 2 === 0 ? 'O' : 'X' ; } _getInitialState () { return { board : [[ '' , '' , '' ], [ '' , '' , '' ], [ '' , '' , '' ]], turns : 1 , winner : '' } }

One quick tip: if you find yourself losing your flow because you keep stopping to think of the perfect name, split your process into two steps. First, write working code with any names (yes, even foo , bar , and baz are ok). Then take a second pass through to improve them.

Adding comments can be a great way to capture what you were thinking at the time you wrote a specific piece of code. This can be incredibly useful to you, or anyone else who comes across your code in the future and needs to understand it, tweak it, or rewrite it.

Think of comments as adding clarity to your code. For larger scale projects and production apps, there are even frameworks that give you the ability to compile the comments in your code into documentation - this is extremely useful because when your documentation and your code live in the same place they are much less likely to get out of sync as when they are two completely separate resources to update.

But, pay attention, because there is such a thing as too many comments. I remember on one of the very first coding challenges I got, I wrote so many comments…there were almost as many lines of comments as there were code! If you’re using one of the documentation tools I described above, that can be ok, but otherwise, you’ll want to adhere to the less is more strategy.

Here is where you most likely do not need comments:

When you declare a variable

When you declare a function

Don’t do this:

1 2 3 4 5 6 7 8 9 10 11 12 // Initialize campaigns $scope . campaigns = []; // Reset function to clear search form after submit var clearSearchForm = function () { $scope . campaignUrl = "" ; }; // Define addCampaign function $scope . addCampaign = function () { ... }

The variable or function name should be enough to explain exactly what it does. If you need a comment to explain it, then you need to give it a better name!

Here are some examples of where comments can be useful:

HTML

CSS

Technically tricky lines of code

References to documentation/StackOverflow

First, let’s talk about HTML. Markup seems pretty self-explanatory, right? So, why would you need comments? Let’s say you have a really long HTML file with A LOT of <div> s. Comments can be a good way to signal which </div> tags close which sections.

1 2 3 4 5 6 7 8 9 10 <div class= "container" > <div class= "row" > <div> <div> <p> Look at all of these nested divs... </p> <p> There are so many that I can't keep track! </p> </div> <!-- close 4th div --> </div> <!-- close 3rd div --> </div> <!-- close 2nd div --> </div> <!-- close 1st div -->

In CSS, comments are a good way to divide up your styles if you have a lot of styles in one file. This way, when you come back to the code later and want to make a change, it’s easier to find the styles for that one section you need to update.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 /* ROW STYLES */ .row { display : block ; } .row :not ( first-child ) { margin-top : -4px ; /* display: inline-block fix */ } .row :nth-child ( 1 ) .square { border-top : none ; } .row :nth-child ( 3 ) .square { border-bottom : none ; } /* SQUARE STYLES */ .square { display : inline-block ; width : 20vmin ; height : 20vmin ; border : 1vmin solid black ; overflow : hidden ; } .square :nth-child ( 1 ) { border-left : none ; } .square :nth-child ( 3 ) { border-right : none ; }

Comments in CSS are also very useful whenever you are hard-coding any math or adding an arbitrary number of pixels as margin, padding etc. For example, you might know that your site header is exactly 104px tall, but someone newer to your codebase might wonder why you have 104px of margin-top on an element. Comments can be useful to explain things like this that are specific to your application.

Also, comments can really come in handy when using z-index to adjust placement of elements below or on top of each other. For example, if you have a modal that you need to show and hide by adjusting the z-index, it can be good to include comments.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 /* LIGHTBOX STYLES */ .overlay { display : none ; top : 8px ; left : 8px ; width : 100% ; height : 100% ; z-index : 1001 ; /* overlay covers the entire browser window */ -moz-opacity : 0.5 ; opacity : .50 ; filter : alpha ( opacity = 50 ); } .white_content { display : none ; position : fixed ; top : 20% ; left : 34% ; width : 30% ; height : 60% ; padding : 16px ; border : 5px solid grey ; background-color : white ; z-index : 1002 ; /* white content sits on top of overlay */ overflow : auto ; text-align : center ; }

One of the best uses for comments is when you’ve written code that is technically difficult or just not intuitive. You should always strive for simple, understandable code as much as possible. However, sometimes you will have confusing code - maybe you’ve chained a bunch of methods together or are using a complex regular expression - and it would help to explain what is happening in a comment. For example, I don’t hesitate to include comments when writing Javascript to show or hide an element based on page scroll location because doing math with element heights never reads very clearly.

1 2 3 4 5 6 7 8 /* This function takes an integer and returns a * string representation with commas for every group of 3 digits. * See this StackOverflow post for an explanation: * https://goo.gl/gfe1H7 */ var addCommas = function ( number ) { return number . toString (). replace ( / \B(?=(?:\d{3}) + (?!\d)) /g , "," ); }

One more case where comments can be useful is when a link to an online reference improves code understanding. As I’ve already mentioned, avoid copying code directly from StackOverflow or similar sources - instead these resources as a starting point for writing your own code, and link back to the original source in a comment. Here’s an example of where I did this for the vanilla Javascript challenge I described earlier:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 /* Execute JSONP API call with hashtag * Inspired by this stack overflow post: * http://stackoverflow.com/a/13045312/4765678 */ var jsonp = function ( src , options ) { var callbackName = options . callbackName , onSuccess = options . onSuccess , onTimeout = options . onTimeout , timeout = options . timeout ; // Create timeout trigger that handles API not returning data var timeoutTrigger = window . setTimeout ( function () { window [ callbackName ] = function () {}; onTimeout (); }, timeout * 1000 ); // If API returns data, process data but do not run timeout // trigger window [ callbackName ] = function ( data ) { window . clearTimeout ( timeoutTrigger ); onSuccess ( data ); } // Create script element on page to run API call var script = document . createElement ( "script" ); script . type = "text/javascript" ; script . async = true ; script . src = src ; // Append script to head document . getElementsByTagName ( "head" )[ 0 ]. appendChild ( script ); };

You are almost done learning how to make your code shine! Just one more step.

3. How to format your code as you write it

I’m a STICKLER about formatting when it comes to code. I liken properly indented and well formatted code to having a clean room. Though I was never good about actually keeping my room clean as a kid (seriously, just ask my mom), now I prefer things to be tidy and in order, especially with code.

And, it’s not just me. You’ll find that the best engineers also care about well-formatted, clean code. Why? First, it’s much easier to read! Coding can be really challenging, so when code is easier to read, it makes our jobs as developers that much easier. Also, writing clean code sends a message to your interviewers that you take pride in the craft of writing code, and for many teams, this is a big deal.

So, how do you make sure the code style sticklers will approve of your code? There are a few simple tricks you can use as you’re working through your coding challenge to ensure the end result comes out clean and you don’t have to spend time at the end reformatting everything.

Choose tabs or spaces and be consistent across your entire application (i.e. no 2 spaces in some files, 4 spaces in others)

Indent your code properly as you go so that it stays readable and isn’t all over the place

Get rid of trailing whitespace! Whitespace can sometimes wreck havoc, so it’s best to just get rid of it as you write your code. There is a plugin for Sublime Text, my editor of choice, that makes this easy, and there are plugins for most other text editors.

Keep your syntax consistent throughout your entire app. If you’re using a linter, this will be easier, but requires setting one up. If you don’t have time to set one up, pay attention. Don’t use ES5 in some places in your app and ES6 in others. Pick one and stick with it!

Remove unnecessary logging and debug statements when you’re done using them! Unless logging is part of your application, you’ll want to remove any temporary statements you were using while building your app.

Always leave a newline at the end of every file.

That’s it! It’s pretty simple, and once you’re in the habit of doing this, not only will your code be easier for you to read, but it will also be easier for others to read and maintain. Many new developers haven’t been exposed to very much code maintenance, but trust me, when you have to clean up code someone else has written, you will be more thankful if it was neatly organized to start. Pay it forward!

Here’s an example of badly formatted code:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 render () { let rows = this . state . board . map (( rowContent , id ) => ( < Row id = { id } rowContent = { rowContent } onClick = { this . _handleClick . bind ( this )} / > )); let message = this . _getMessage ( this . state ); return ( < div > < button onClick = { this . _resetBoard . bind ( this )} className = "reset" > RESET < /button > < div className = "message" > { message } < /div > < div className = "board" > { rows } < /div > < /div> ) ; }

Here’s an example of the same code, but cleanly formatted and MUCH more readable:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 render () { let rows = this . state . board . map (( rowContent , id ) => ( < Row id = { id } rowContent = { rowContent } onClick = { this . _handleClick . bind ( this )} / > )); let message = this . _getMessage ( this . state ); return ( < div > < button onClick = { this . _resetBoard . bind ( this )} className = "reset" > RESET < /button > < div className = "message" > { message } < /div > < div className = "board" > { rows } < /div > < /div > ); }

Back to top

Share this post on →





10. How to take your challenge to the next level

If you’ve made it to this section of the guide, congratulations! You’ve come up with an overall plan for your app, you’ve written a test plan and actual tests, and you’ve met all of the basic requirements of your challenge while also ensuring that your code is shiny and clean. So what’s next?

Since this is The Ultimate Guide to Kicking Ass on a Take-home Coding Challenges, it would not be complete without explaining how you can go above and beyond. If you’ve gone through this guide and implemented my suggestions so far, you’re in a great place. However, in the interview process, you rarely know how many other applicants you’re competing with. Maybe there’s a more experienced candidate, and they were given the exact same challenge to complete. How do you ensure that you’re the top choice out of all of the candidates in the applicant pool?

The short answer is by going above and beyond. When you put a massive amount of effort into your challenge, it’s a high competence trigger because it shows that you are willing to go all in on everything that you do. What company wouldn’t want to hire someone who puts this much effort into their work? You’ll be sure to stand out from the other applicants and maximize your chances of moving on to the next interview round.

Here are 4 ideas for how you can take your coding challenge to the next level:

1. Bonuses

2. UI/UX design (for front-end or full-stack challenges)

3. Data validation and error handling (for any type of challenge)

4. Commit history

1. Bonuses

Not all coding challenges come with bonuses, but if yours does and your goal is to get a job offer, do them! Why? It’s pretty simple. If you go above and beyond in your coding challenge, it will show that you will go above and beyond once you’re hired at this company. Completing bonus requirements (or at least taking a shot at them) is a high competence trigger for the interviewer.

One time I was given a challenge that listed 5 bonuses in addition to the base challenge. I was really excited about the company, so I made it my goal to complete all of the bonuses for the challenge. The extra time I needed to complete them was definitely well spent - not only did I learn a ton, but I also ended up with a fantastic offer from the company at the end of several rounds of interviewing.

Here are the bonuses from my Tic Tac Toe app:

Make Board Responsive

Add additional boards

2. UI/UX design (for front-end or full-stack challenges)

Some front-end or full-stack challenges will mention UI/UX design as a bonus, but if they don’t, putting in some effort to make the UI look nice and be easy to use will go a long way. You can either go the route of adding your own custom CSS or plugging in a library or two to help make your styling even more painless. If you use a library, again, just make sure that you understand how it works enough to explain how you’ve used it.

Examples:

For one company, I was tasked with implementing a simple drag and drop UI with a grid of boxes. I gave the challenge a little extra detail by doing two things. First, I added the brand’s color as a prominent part of the design. Second, as part of a requirement for the challenge, the boxes had to have unique identifiers to make it clear that the drag and drop functionality worked correctly. I added the letters of the company name into each box and for duplicate letters, I inverted the color scheme. Adding these extra details gave me an edge in the interview process and made my application stand out.

For a full-stack challenge I received, after implementing the base functionality, I styled the main page to mimic styling I found on the company’s production site. In my interview, the engineers told me that they appreciated that I made the extra effort to style my app just like theirs.

As you can see, adding these thoughtful details can really make an impact and put your challenge over the top. So, spend a little time thinking about small details that you can add to personalize your challenge based on the company. It will make it clear that you’ve done your research and engineers reviewing your code will notice!

3. Data validation and error handling (for any type of challenge)

Data validation and error handling are key components in production apps. Adding either one of these (or both!) to your challenge will definitely make it stand out. Many developers who are new to coding and haven’t worked in a production codebase before don’t have a ton of exposure to either of these, so if you add error handling for edge cases it will show that you thought through a lot of different situations. You can do this with built in tooling like Rails flash messaging or on your own using simple Javascript alerts.

Also, you might learn some regex in the process! If you’re doing either client-side or server-side validation, regular expressions can be a great tool. My favorite resource for figuring out regular expressions is Regex 101.

Error Handling in Tic Tac Toe

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 _handleClick ( row , col ) { if ( this . state . winner ) { alert ( 'A winner has already been declared! Press reset to play again.' ) return ; } else if ( this . state . board [ row ][ col ] !== '' ) { alert ( 'A move has already been played in that square!' ) return ; } else { // increment turns this . setState ({ turns : this . state . turns + 1 }); // update the board let newBoard = this . state . board ; newBoard [ row ][ col ] = this . _getCurrentPlayer ( this . state ); this . setState ({ board : newBoard }); // check winner let winner = this . _checkWinner ( this . state . board ); this . setState ({ winner : winner }); } }

4. Commit History

Commit history isn’t something that every reviewer will look at, but it’s another tool that you can use to showcase your craft. Always strive to write clear and concise commit messages because they are a way to communicate changes to other developers on your team or in a larger organization. They serve as additional documentation for the code itself.

I use git blame at work regularly and often I’ll come across commits that were made by an engineer who is no longer working at the company. Reading their commit message gives me additional insight into the larger context of what they were working on when they made a specific change, which oftentimes will help me problem solve. So take pride in commit messages just like you do in code style. Here is a styleguide with examples of good vs. bad commit messages.

So now that you know how to write good commit messages, what story do you want them to tell? Breaking down large problems into small steps is a crucial part of being a top-performing engineer. If you’re diligent about breaking your work up into small pieces, and you commit each small piece, you will show that you’re capable of tackling large problems. Also, if you make a small change and break something in your app, it’s easy to investigate to see what you broke. However, if you make a bunch of changes and they are all rolled into one commit, it will be much harder for you to debug. As a rule of thumb, at the very least each task that you’ve previously planned should be its own commit.

Now that you know how to take your challenge to the next level, it’s time for a very important step: adding documentation!

Back to top

Share this post on →





11. How to write a kick ass README

After you’ve taken your challenge to the next level following my advice in the previous section, you may be thinking, “Great, now I’m ready to send my coding challenge off!” Not so fast! You may be done writing code, but you’re not done writing yet - it’s time to write your README.

Why you should include a README

READMEs are incredibly important, both for professional developers and for job seekers working on take-home challenges. Including a README shows that you care about documentation. Why should you care about documentation? Documentation helps spread knowledge across teams and serves as a supplement to your code. Having documentation for your take-home challenge ensures that anyone else (or future you) can jump into your code with a clear understanding of what you’ve built without any guessing games. Your README is also the KEY to making sure that everyone reviewing your challenge has the most painless experience possible. Finally, your README is a way of proving to your reviewer that you successfully met the requirements of the challenge.

As someone who has reviewed many coding challenges, one of the most frustrating experiences has been when candidates submit their challenges with zero documentation on how to setup and run their apps. Every app is different, so even if you are using the company’s specific technology, you might be running a different version, which can send the developer reviewing your app into environment HELL. If you waste their time with setup crap, you will definitely not be moving on to the next round of interviews.

So, how do you avoid this situation? Easy, write a kickass README.

How to write your README:

Writing a great README is not hard, and you will stand out a great deal from the other applicants with one. Here are the 5 sections I’d recommend you include:

1. Installation instructions

2. Discussion of technologies used

3. A section demonstrating that you met the requirements

4. If there are bonuses, a section demonstrating that you met them

5. For algorithms and datastructures, time and space complexity

1. Installation instructions

Have you ever read documentation or tried to attempt a tutorial where the author has left out basic steps and you’ve ended up spending a long time debugging a problem? I have, and it makes me want to pull my hair out. You end up wasting time looking for one line of code to add or change or you spend forever trying to get your app started, only to realize that a script was missing, or you didn’t realize you needed to install something. In these situations, the authors have usually made assumptions about the developer’s knowledge, which later ends up leading to frustration.

When writing your README, don’t make any assumptions. Write out all of the steps to run your app locally and test them yourself. This includes cloning the repo from Github, running installation commands (like npm install or bundle install), and starting up a server. Also, make sure to include versions of software that you are using. This will ensure that the developer reviewing your code has a seamless experience setting up and running your app and if they do happen to run into any trouble due to versioning, they will have all of the information they need right there in the README.

2. Discussion of technologies used

This section is as simple as it sounds - make a list of all of the technologies you used including frameworks and libraries. If you had to find a library for a specific piece of functionality in your take-home challenge, mention it here and include a link to the docs.

3. A section demonstrating that you met the requirements

Usually your take-home challenge will come with some sort of requirements spec, so make sure to include a section in your README where you describe the requirements and how you met them. In some cases, you can take the product spec you were given and write a short explanation of how you met each requirement in a list. In other cases, you can simply include a short paragraph explaining how you satisfied the requirements. It’s totally up to you how you do it, just make sure you include it.

4. If there are bonuses, a section demonstrating that you met them

Similar to the requirements section above, you’ll want to highlight any bonuses you completed while working on the take-home challenge. If you attempted a bonus, but couldn’t quite get something to work, then the README is also a good place to address that. You can discuss the approach or approaches you tried and what worked or didn’t work.

5. For algorithms and data structures, time and space complexity

If you had to write any algorithms or data structures as part of your take-home challenge, it’s helpful to include the space-time complexity of your final algorithm. This can be done in Big O notation - I personally like this cheat sheet for figuring out runtime.

One final word of advice: write your README in markdown so it looks nice! This will demonstrate that you know (or are willing to learn) another language that will come in handy as a full-time developer. If you’re not familiar with markdown, you can learn the basics here.

Here is an example README for my Tic Tac Toe app:

# Tic Tac Toe By [ Jane Philipps ]( mailto:jane@fullstackinterviewing.com ) [ janephilipps.github.io ]( http://janephilipps.github.io ) ## Instructions 1. Navigate to [ repo ]( https://github.com/janephilipps/tic-tac-toe ) 2. Clone locally using `git clone git@github.com:janephilipps/tic-tac-toe.git` 3. Install dependencies using `npm install` 4. Run tests using `npm test` 5. Start your server using `npm start` 6. Navigate to app in [ browser ]( http://localhost:3000 ) 7. Enjoy! ## Discussion I used the following technologies: HTML, CSS, React, Jest, and Enzyme. I used [ create-react-app ]( https://goo.gl/26jfy4 ) to generate the scaffolding for this app. ## Requirements #### Build a two player tic tac toe app where a game is played by #### alternating clicks until the game is won by X, O or is a tie. I added a `message` that displays which player's turn it is based on the number of turns taken. The `message` also displays whether a player has won or if there is a tie. #### Include a reset button so that when a game ends, the board can be #### cleared and a new game can begin. The reset button calls a method `_resetBoard()` which calls another method `_getInitialState()` to reset the board. ## Bonuses! #### Make the board fully responsive I used the `vmin` unit of measure to make the `width`, `height` , and `border` of the squares fully responsive. #### Allow for more than 1 game to be played simultaneously I have a state within the `App` that keeps track of the number of boards. Because each board also has its own state, gameplay across multiple boards can happen simultaneously without interference.

Back to top

Share this post on →





12. Final steps before you hit send

Ok, now that you’ve written your README, you’re almost ready to hit send! Before you do that, take the time to double check all of your work using the following checklist:

Re-read the take-home challenge instructions to make sure you didn’t miss any requirements

Review your app’s code to ensure that it shines

Run your app’s automated tests and make sure they are all passing

Test your app manually and make sure everything is working properly

Test your app installation instructions from your README

Start an email draft and copy your README into it for convenience

If requested, make sure to attach a zip file of your code

Write an email to your contact at the company

Your email can be short and sweet - I always like to highlight something I enjoyed about the challenge or something I learned. Here’s an example:

Hi <NAME>, I hope you had a great week! I had fun diving back into React with this challenge. Here is my github repo and I've included my README below. Please let me know if you have any questions. Just so you know, I'm interviewing with a few other companies and I just received an offer yesterday - I need to get back to them next week. Of course, I am excited about the opportunity at <COMPANY NAME>, so I'm looking forward to hearing from you! Thanks, <NAME>

Now, finally, hit send!

Back to top

Share this post on →





13. After you hit send: prepare to discuss your code

You’ve finally sent off your completed coding challenge - congratulations! You’ve worked hard to follow the steps in this guide, you’ve learned a ton in the process, and you’re excited about the final product that you sent over to the company.

For most people, this is where the work ends. However, you’re not quite done yet. What could possibly be left, you ask? Well, you need to prepare for your next steps of the interview process.

If you’ve followed the instructions in this guide, you have maximized your chances of moving on to the next interview round, which will often include discussing your project with engineers at the company. When this time comes, you’ll want to be prepared to talk about your code and to answer any questions. The worst thing would be to have put in all this work, only to botch the discussion portion.

So, how do you prepare? Here are the 3 key steps to take:

1. Reference your notes

2. Practice with a friend (or a rubber duck)

3. Be prepared to talk about any challenges, trade-offs, or possibly controversial decisions you made

1. Reference your notes

Remember earlier when you planned your project up front before writing any code? All of this planning will be a great resource for you in preparing for your next interview. In reviewing your notes, you should be able to see clearly what decisions you chose to make and why. If you’ve kept good notes during planning, you’ll be able to recall why you set up a database schema a certain way, why you built a UI a certain way, or why you made any other choice.

2. Practice with a friend (or a rubber duck)

Practicing answering questions about your app live with a friend, in front of a mirror, or with a rubber duck, will be a test run before the next step of your interview. You’ll feel less nervous going into the interview having practiced explaining your code and you’ll be able to see what areas require extra practice.

First, come up with some sample questions that your friend can ask you. Then, think about how you would answer those questions - feel free to write down talking points. Then practice answering each question multiple times - with each practice session, try to reference your notes less and less. Also, ask your friend for feedback. Are you rambling? Are you not going into enough technical detail? Are you going into too much technical detail?

Here are some sample questions:

What did you find most challenging about the assignment?

What did you find most fun about the assignment?

Is there a specific section of the code that you are most proud of?

If you had more time, what features would you like to add to this app?

Why did you architect your app this way?

Why did you build your UI this way?

How could you scale or productionize this app?

Did any interesting bugs come up? How did you solve them?

3. Be prepared to talk about any challenges, trade-offs, or possibly controversial decisions you made

Finally, aside from the questions above, you should think about any parts of your challenge that you found especially difficult. Be prepared to discuss what problems you encountered and how you solved them. Remember, interviewers want to understand how you approach problems, not just the solutions you come up with.

If you made any trade-offs due to time constraints, think about how you can convey that to your interviewer. For example, if you ran out of time and could not complete part of the requirements, instead of saying “I ran into trouble with styling and didn’t have time to finish” you can reframe it to say “Given the time constraints of the challenge, I had to prioritize automated tests over styling”.

Here is what I would say when asked about my Tic Tac Toe challenge:

One potentially controversial choice I made was to use the create-react-app generator for this challenge. I've worked with this generator before and this allowed me to save time in setting up the app the right way. The most difficult part of this take-home challenge was setting up testing with Jest. I had never worked with Jest before, but decided to use it because it was built into create-react-app. It was tricky because there was no visual component to the tests, and I had to do all of the debugging through the Chrome console. Usually when running front-end tests, I can stop the test in the browser and inspect elements to see why a test might be breaking. Not having the visual was difficult, but I learned how to use jsdom instead. One tradeoff I made was not DRYing up the tests. I decided that refactoring them to be less code would actually make them harder to read, so I traded off code succinctness for readability here.

Going back and referencing your notes, practicing with a friend, and getting prepared to discuss any challenges you faced while completing your take-home challenge will give you a huge leg up when you move on to the next interview round. The time you spend preparing AFTER you’ve completed and submitted your take-home challenge will be crucial to your continued success in the interview process, so DO NOT SKIP THIS STEP. It will be well worth it!

Back to top

Share this post on →





14. Frequently Asked Questions

I’ve put together a list of 8 frequently asked questions based on my experience with take-home challenges as well as suggestions from others. If you have any questions that aren’t addressed here, feel free to shoot me