Strategies for take-home coding tests

Context: Why make this post?

I have been through many job applications for junior iOS developer positions. Almost all of these jobs had coding tests. Knowing how to do well on coding tests is a useful skill because nowadays, there is intense competition for a limited number of jobs.

As a junior Swift developer, I experienced a lot of pressure to perform well in job interviews and tests. I was intimidated by the application process (and I am fairly sure that I am not alone ;)). iOS Development is a large domain, and there are many things to know from the Swift language, iOS-specific design patterns, git, Xcode features, memory management, CI, testing, frameworks, and agile processes (I could list more but you get the idea ;)). I set high standards and tried to be comfortable with everything. While this meant I performed well, it also meant that I got frustrated and stuck trying to memorise lots of facts. I am writing this post to offer a new perspective for how to do better in coding tests.

Even though coding tests can feel painful and a chore in the beginning, we can relish the challenge and opportunity to prove ourselves. It felt satisfying to get a job with my latest coding test! :D Getting my dream job was a strong motivator and brought out the best from me. Using my outlined strategy, I had developed good coding ability through consistent good habits in daily work. One of the main lessons from my experience has been to do good work even when there is no pending assessment.

I was lucky enough to be given a chance as a junior iOS developer with no prior experience, so my unique perspectives could be useful to other aspiring developers.

The main goal for this post is to encourage aspiring developers and empower them to avoid the same mistakes I made. I make mistakes daily, and have been following iOS development for 5 years (independent and commercial) app-making. One of my mantras is:

”Ever tried. Ever failed. No matter. Try again. Fail again. Fail better.” ~ Samuel Beckett

Although this post is based on my mistakes in my relatively short career so far, they have been useful for me so I believe the tips can work for others too. The advice is generic across experience levels and may also help web devs, DevOps and ML devs.

My Overall Strategy

  1. Consistent, deliberate coding practice to read documentation and understand the key recipes.
  2. Pay meticulous attention to detail.
  3. Reflect and improve your code.
  4. Use coding snippets.
  5. Think pragmatically about what is important to develop.
  6. Be an Autodidact.
  7. Be open to feedback and admit what you couldn't do.
  8. Save your best project to reuse for next time.
  9. Get inspiration from well designed coding tests.
  10. Plan ahead.
  11. Apply to smaller companies first.

Consistent, deliberate coding practice

Coding is all about practical problem-solving. We learn by doing, and thus developing a strong daily workflow helps you to perform under pressure too.

If you follow me, you know I advocate for deliberately minimising StackOverflow lookups and instead reading the documentation / getting started guides.

I also am a strong advocate for writing documentation in the form of coding snippets (covered later).

Although it's tempting to Duck (Google) things every time you're stuck, this is an anti-pattern. Copy-paste cult programming (in my opinion and those of many senior devs) is a beginner habit that needs to be broken. It's fine to read code, understand what it does and tweak it to your needs before copy-pasting. However, blindly copy-pasting code from SO is not optimal for the best developers because the code may have subtle bugs or be unsuitable for different use cases.

Even though there is so much to know, you can memorise the key recipes for how to avoid memory leaks, how to set up MVVM apps and how to do data persistence. DON'T try to memorise EVERYTHING! It's impossible... trust me I've been there.

TIP: Mind-maps are great to scope out the domain and brainstorm what you need to work on. Noting things down even as physical notes or audio recordings could work better for your learning style though.

Coding, done well, is a natural extension of your mind + body. With experience, you will be able to do the basics like the back of your hand. You can look things up when you get stuck, but really you should try to keep improving and retaining info. Programming is an art that takes practice to master. Paying attention to your craft will help you excel in coding tests, because you'll be a natural.

It's hard to get started, and it doesn't get any easier as you get more experienced. Identifying the problem is a good first step, so recognise that and do your best to build up helpful habits.

MOTIVATION: Compound interest is the eigth wonder of the world.

I call daily work "the grind". It's what shapes your overall performance because it's your baseline level of performance. Improving your baseline in daily coding will eventually pay off for coding tests. :D

Take meticulous attention to detail in projects.

Paying attention to detail almost goes without saying if serious about getting a software development role, not just because it's so ingrained into coding practice but because practically it demonstrates passion. Don't neglect the details, because neglect leads to tech debt long-term!

Quality, maintainable code requires attention to detail, and employers are assessing your ability to write prod code. This is why software craftsmanship is so popular. Computers require clear, specific instructions to do things, and keeping track of details is only possible when you are dedicated to the craft. Design patterns build on the core problem-solving skillset and skills build on top of each other. Build strong foundational skills by paying attention to the whole package: developer tools, development methodologies and each software subsystem. The stronger your foundations, the stronger you can uplevel in your career.

Thinking deeply logically about every aspect of your project helps you to stand out from the hundreds of other developers who applied. Adding polish with simple touches like a well-designed app icon, launch screen, or modular workspace shows that you are passionate about producing quality apps. Attention to detail derives from passion, and good employers want passionate developers to create beautiful products.

TIP: Lock in details with small git commits. Making small, regular commits at least locally is a great way to hone your craft.

Technology is a great enabler, because talent shines from anywhere, and there's nothing stopping you from being a good developer. Don't become arrogant as you improve, because coding ability only works effectively when you have soft skills too. Arrogance is a red flag.

My strategy is always centred around doing my best and putting my best foot forward. This goes well with attention to detail.

BELIEF: If you do your best consistently, then you won't regret trying and failing.

Dedicate time after work to reflect and improve your code.

It's impossible for anyone to write perfectly architected, clean, well-tested code the first time. That's normal, so we don't need to feel embarrassed. There's a lesson in every experience, and thus every experience is valuable. Making mistakes is normal throughout your career and is not really a mistake if you learn from it. :D

Code review is all about reflecting on your work and probing it for weaknesses. Focus intently on all aspects of your feature.

How can it break? Will the feature work across devices, orientations, system settings, and themes? Can I break the app and replace a QA? This is the right way to think about code improvement. Be bold and don't dance around issues.

Confront and look for issues early because you don't have a lot of time anyway

This is the right way to think but it's hard to follow in practice, especially if we have worked a while on something. It works! Why should I bother to change it? It's hard to admit that we could make my code better, but it's true for all developers. We make fewer mistakes with experience, i.e. only after we've made lots of them. ;)

It's a fact that your code works for now, with this framework, this language and this device. But, are you confident deploying the same code across millions of different devices and maintaining the code after a couple of years? Coding tests not only test that you can write code that works, but code that is:

  1. Maintainable
  2. Robust
  3. Performant
  4. Scalable
  5. Testable
  6. Readable

This is what separates out professional developers from hobbyists. Production code has to be architected clearly, designed well, tested and clean. It's different to the code we use in prototypes or learning projects. Most large codebases have to balance velocity with code quality and coverage. Thus, it's important to develop commercial awareness as an aspiring developer.

"Work with the end in mind." ~ Stephen Covey

Use your coding snippets to save time.

I mentioned in my previous post about making code snippets to save time when developing apps or websites. It's impossible to know everything and you can surprise yourself with how much effort you can save by copying code that worked for you in the past. Knowing common recipes for your chosen language and platform is helpful to thrive in time-pressured coding tests.

There's no shame in copying good code if you truly understand it, even if you didn't write it.

This is an exception to copy-paste programming because you're copying yourself. I also don't mind copying code from quality blog articles because I truly understand the code with their walkthroughs.

TIP: Don't mindlessly read blogs. Read with a goal in mind, and extend the article's implementation after completing the walkthrough.

Try to not get stuck by dogma. Think for yourself, and keep on improving every day.

Snippets are not an anti-pattern, however you can do even better than snippets if you can produce code from memory. I try to do this, but it's frustrating at the start to say the least. I would recommend build up your muscle memory through side projects / prototypes alongside work to make code flow naturally.

Think pragmatically about what is important to develop.

Usually coding tests are time-pressured from 1 week to 3 weeks. Delivering a great project in 1 week is impressive and the faster you can develop quality code, the better.

"Focus on what matters and you'll get there faster than most."

It's impossible to do everything, so focus on covering all the key aspects of a good app.

  1. The app shouldn't crash AT ALL.
  2. The app should look reasonably appealing. Don't go overboard with design because the focus is development, but at the same time don't neglect it.
  3. The app should work as expected according to the spec.
  4. The app should be performant without animation hitches, UI lag or blocked UI.
  5. The app should not have bugs and be robust with high code coverage.
  6. The codebase should be clean, well organised, following OOP, SOLID, and FIRST principles.
  7. The app should use small, regular commits to Git, and ideally a branching model like Git Flow.
  8. The app should implement a coherent design pattern appropriate to the stack.
  9. The app should use a well-known stack of dependencies or no dependencies to really impress.
  10. The app can make use of the latest, greatest features where appropriate.
  11. The app should be a reasonable reviewable size for a fellow developer to review (reviewers are human too! :D).

Try to follow these guidelines independently as much as possible. There are probably many more things to pay attention to for coding tests, but try to follow KISS. A large project, even if it's technically impressive, is inappropriate for a coding test. I've been burned by this in the past, so make sure your project is a reasonable size!

Be an Autodidact

I don't ask for help until I'm really stuck, and even then I don't ask on SO (unless it's something truly non-trivial). Autodidactic learning is super effective in my experience. Obviously, asking for help with writing code is fine for workplace environments under time pressure. However, I found that getting the job done independently was satisfying and helped code patterns to stick better.

For more experienced devs, asking questions on StackOverflow instead of your colleague can produce much higher quality answers if you know what you're doing. Contributing on SO is a great way to improve your developer brand and software toolkit. Many SO users are self-taught programmers, and there is no barrier to entry if you have the skills.

In this industry, you learn by doing.

Never stop learning! :D

Be open to feedback and admit what you couldn't do.

Regardless of how senior you are, we all write bugs and we can't know everything. Our field is constantly evolving and feedback is important to learn faster. It's important to document what we manage to complete, identify areas to improve and admit our mistakes when (not if) we make them.

It's actually the sign of a mature, senior developer to admit and learn from mistakes. Being open solves problems quicker and helps a team to grow together. You should still try and minimise mistakes but don't sweat TOO much otherwise you'll get analysis paralysis (I hate that feelin').

TIP: I recommend writing a README.md file for coding tests to make a thought process transparent.

I used to hate code review because it felt like people were attacking me. However, in good companies, the focus is placed on valid improvements (content) to the codebase and not the fact it's your code. Keeping ego out of work makes a job more enjoyable and helps accelerate progress because people could know more than you in different areas.

The goal should be to improve the app, learn new technologies, and not feed your ego. Code review CAN BE FUN!!

Write great code AND have fun!! :D

Save your best project to reuse for next time.

Caching projects saves time if you're applying to a batch of companies. Coding tests often repeat the same core format and task, so get the most out of your efforts.

We need to adapt and update coding test projects if they were written a while ago (legacy code). Quality code shares a common trait: Maintainability. As such, if you've produced a quality project in the past, you should in theory be able to refactor and update it easily. Run and test with a fine-toothed comb to make sure the app still works as expected without any new bugs.

TIP: Read Refactoring by Martin Fowler for practical strategies on refactoring legacy code.

Having prepared projects in advance saves time during the hiring process and may give you a headstart on other candidates too ;).

Get inspiration from well-designed coding tests.

If I were to do my job search again, I would do most things differently. I would learn all the shiny new APIs, tools and language features well in advance so that I can show off in the project. I am not sure whether this is the right strategy in general though because of differences between domains. It's also hard to follow as a junior ;). Going forward however, I would prepare a mock coding test project for the company I want to apply to, spending a week refactoring, testing and then finally submit the project immediately after clearing earlier rounds.

"The early bird catches the worm."

Coding tests are hard, and not everyone prepares well. Great preparation gives you such a strong advantage and it's NOT cheating. I would recommend using every advantage at your disposal because of more competition nowadays.

Plan ahead.

Completing a coding test well takes short and long-term planning. I feel coding tests will gradually get easier with time and review. View the whole process as an exciting challenge, and see the fun in self-improvement! I think this positive, proactive mindset can rapidly accelerate your job progression by encouraging you to stick with your plan.

"When stuck, make and execute a plan. If that plan fails, make a new plan and execute it. Don't stop moving forward."

Example plan

  1. Memorise interview questions and answers for your domain.
  2. Make code snippets.
  3. Use regular, small Git commits daily until it becomes a habit.
  4. Shortlist available jobs and rank them by preference.
  5. Research what coding tests the companies you're applying to use.
  6. Prepare a project for similar example take-home coding tests on GitHub. Use code snippets where you can and time yourself.
  7. Add polish with new APIs, language features and patterns.
  8. Review your code first, and maybe ask someone else to review it too.
  9. Review and refactor the codebase meticulously. Use a linter.
  10. Apply to the company and use your prepared coding project as much as possible. If not, use whatever resources you have to my advantage. Work hard at it.

Short-term planning

Take each day as it comes. Improve every day, and work hard.

"Hard Work beats Talent when Talent doesn't work Hard."

There's a lot to work on and learn, so don't put yourself down. Building up good habits in side projects and during the learning process is fun! :D

Mindset

You'll either get the job or you won't, don't worry about it. There's lots more opportunities out there, and you can learn for next time :).

Apply to smaller companies first.

Apply to companies you're less keen on first so that you can use the experience as a practice run. When I did this for my iOS internship, I bombed my first interview but smashed the next one. Failure is a good motivator for me, and helped me learn from my mistakes.

This can be linked to your planning process by scoping out your most desired jobs first and researching their design patterns, culture and hiring processes. Junior developer roles are hard to come by, so make the most of all advertised openings and plan ahead. Junior roles in particular are the most competitive IMO.

There are so many talented developers out there these days, partly because of better courses and coding bootcamps. If you are really passionate and determined to get your dream job, then you will get it.

"Deliberate practice gets better results than blind practice."

If you failed in previous job interviews, don't feel discouraged by viewing the experience as learning / feedback. Learn from the experience and keep putting yourself out there.

"Measure yourself against who you were yesterday, not against others."

You may even find that you get the job the next time you apply, or your next job application. Have faith that things will work out if you put your best foot forward.

Summary

Coding tests are cumbersome and stressful for everyone. That being said, it is possible to improve at them with strategic preparation, practice and planning. Plan ahead, make the most of your available resources (memory, time, documentation) and stay positive. There are lots of opportunities out there, so if one doesn't work out, another one is just round the corner.

Good luck! :D