Note 1: This post is not to hack your way through the interview process, but to avoid situations where you might put 10h of work, to just be rejected by a small mistake.
Note 2: This checklist is not specific to babylon health. The goal is to enhance your chances of nailing this phase of the interview process, independently of the company.
It has become quite common to submit a demo test when interviewing for an iOS role. These tests typically take between 6 to 12 hours, but it's not uncommon to be longer than that. The sad reality is, after reviewing more than 100, it only takes me typically around 5 to 10 minutes to have an overall feeling.
In this post I will share some of the things I look for when reviewing tests. Obviously, this might not work for every single interview you have (different reviewers, will look for different things), but hopefully it will at least improve your chances to get to the next phase.
Pay attention to the spec. A lot of times companies are very specific about certain things: don't use nib files, don't use 3rd party libraries, code needs to be unit tested. As an example, I once got rejected because I didn't use Storyboards. Although it might seem stupid, or irrational, it doesn't really matter, those are the requirements and you should respect/follow them. If it's something that doesn't make sense, clarify any doubt with your point of contact. In the other spectrum, like at babylon health, we leave the spec open enough for the candidate to make his/her own decisions. It's important to note that: with great power, comes great responsibility. If the candidate goes to the next phase, we will then ask why he/she picked X instead of Y approach.
This might be a polarising topic, but I prefer the Xcode's file structure, to mimic the system's. I don't have statistics on this, but most people I know prefer this approach as well. I wouldn't reject a candidate base on this, but someone else might, so keep this in mind. (ps: you can always use synx to make sure it does.)
Following the previous point, your folder structure should have some sort of reasoning/logic behind it. Do you have the folders based on features? Do you put them according to View / Models / Controllers? What's the pattern you are following and does it make sense?
AppDelegate.swiftclean. This shows care about your project and attention to detail. When you create a new project, your
AppDelegatewill have a couple of
UIApplicationDelegatemethods that don't do anything, so just remove them. This won't make me reject a candidate, but again, it shows attention to detail. This is true for any file you create that comes with a default implementation.
UIViewControllerand see how much stuff each one is doing: often anything related to network, or persistence, being done there is an automatic rejection. The
UIViewControllerwill typically be small (as an exercise, keep it under 200 lines). It will normally communicate with a Controller or a ViewModel (or some other entity, depending on your architecture) and customize UI (colors, fonts, frame positions, etc). For extra points, make sure you are injecting its dependencies and that you abstract those via protocols. For a senior position, I wouldn't expect otherwise.
One of the easiest ways to have an overall feeling of a project, is to just look at a single method:
tableView:cellForRowAtIndexPath:. If you are setting the value of a cells directly (
cell.myLabel.text = ...), or you have a big
switchin it, it's normally a pretty bad sign and a misunderstanding of responsibilities. 99% of the cases where I have seen this, the project won't pass the review, but I have been proven wrong. In that case, the candidate went with that approach, but the rest of the project was in a pretty good shape, so he moved to the next phase. It will take you less than 5 minutes to create a new entity that you pass to the cell, so I would advise doing so. The usage will then be something like:
When it comes to the network layer, a lot of people will just defer to a 3rd party library. I am mostly ok with this, although for a demo test, it's probably better to just use an
For the persistence layer, using a third party like Realm is pretty common, so I wouldn't be surprise if a demo project would use it. Most importantly I would advise on creating a separation between the objects you are persisting and the objects you are passing around the App. This is quite fast to do and will show that you understand the problems of models shifting under you feet. You could do this instead.
NSUserDefaultsfor persistence. 🙄
Depending on the project, you might need to orchestrate multiple services accessing network at the same time and waiting for their responses. There are many approach to this: GCD,
NSOperation, Promises, FRP frameworks, etc. My only advise is: don't use boolean flags for this.
Something that is often overlooked is the separation between: Network, Parser and Persistence. You might think that this is just over-engineering, but the person reviewing your code will assume that's your default approach: mixing these entities. You can find an example of the separation, using just vanilla closures, here. Typically a person applying for a senior position will be rejected if he/she mixes these.
It's important to see how you do error handling in your app. Picking the multiple services orchestration example, it should be clear at the UI level, why it failed. Having an
Unknown errormessage, is not really acceptable. The failure path is as important as the golden path. Bubbling up this error through all the layers, will show your skills as an architect. A person applying for a senior position, should have this nailed down.
Don't use approaches/libraries you are not familiar with. If you don't know about viper, or flux/redux, don't use them in your demo project. The chances of getting it right are small and the goal here is to pass to the next phase.
If you are using
git, keep the commits small with clear messages (please don't put random 💩 in the messages).
Ideally you will have Unit tests, but if you don't:
- Use Dependency Injection, so you can show it would be straightforward to do so.
- Leave a comment when submitting your App, why you didn't do Unit tests (lack of time is a very valid reason!)
- Delete the Unit Tests target and all the stuff you are not actually using, that Xcode creates for you.
TODOs if you have to. You would normally avoid these, but it will show to the reviewer your reasoning. There is also the case where you missed one of the requirements, but at least you communicate to the reviewer where you would do it if you had the time:
//TODO: Ideally we would invalidate the cache every 30 minutes here.
This one is a cheeky tip, but if you see a given technology/approach, is used by the company you are applying to, use it in your project. For example, if I would apply to Pinterest, I would probably use AsyncDisplayKit. This shows that you are aware of how they work and what they use internally. You can also do the same if the person that is reviewing the test is into a certain approach/technology: people love to see things that are familiar/dear to them. Obviously, only do this, if you are comfortable with it, since this can easily backfire.
Use localization. It takes very little time and again shows attention to detail.
Take some time reviewing your entities names and that they make sense. Naming things is a difficult task, so if you have to take 10 minutes or more thinking about it, so be it.
Most developers out there, are more familiar with Objective-c than they are Swift. It's important that your code looks "swifty". It's easy/tempting to write Swift as if it was Objective-c, reviewers will quickly pick up on this.3
Be consistent in your code. Stick to the same style throughout the project. You can use something like this to guide you.
Make sure your project compiles and actually does what it's supposed to do. A lot of times we get caught in the code and completely forget about what we are actually trying to achieve.
Run Instruments to make sure you don't have any memory leak.
Have a look at every file in your project one last time before submitting, if needed use the rubber duck approach.
Most of these tips won't take you a lot of time and hopefully will add a lot of value to your project. It's important to also note, that depending on the position, the reviewer will be more or less strict4. In any case, keep all of them in mind when submitting your project. 👍
Best of luck! 😊
So a list of personal preferences and pet peeves disguised as something other than that? Got it.
I try very much to not be biased when reviewing every demo submitted. Obviously, this is impossible. So each project is reviewed by 5, or more, different people, with different levels of experience and different backgrounds. We take a democratic approach on this and if the majority think it's a good project, we will invite the candidate to the next phase. This checklist is an attempt to improve your project in a general away, independently of the company you are applying to.
Didn't see anything about actual problem solving skills. I understand following a model and not overloading any one part, but there's nothing mentioned about actually solving complex problems. This seems more like 'coding' and less about solving complex problems. I guess it depends on what the job is, but just being able to see what code goes where, isn't the same as creative problem solving.
Anyways, it would be more meaningful if you said something more than "don't use NSUserDefaults for persistence" Maybe explain why.
Your solving skills are evaluated on how you do the project. Which will of course depend on the project itself. The majority of the projects out there are normally around accessing an API, parse the response and display to the user, so I followed that recipe for this checklist. Yes, this checklist is around code, not about creative problem solving. 😕
NSUSerDefaults, a quick google search would provide you the answer.
It would be disheartening to spend 10 hours on this guy's demo project and not separate concerns exactly how he prefers or something. I've done similar long demo projects, and I've come to the conclusion that companies asking for long projects either don't know what they are doing or are willing to abuse people in a large talent pool.
This demo is not for me (personally). It's simply a general recipe to hopefully improve your code, based on the amount of companies I have applied to and the demos I have myself reviewed. Is this subjective? Some might be, but I have tried to be very objective in each point.
This is a solid article especially if you're doing an entry level spot however #7 with regards to the model being a struct/enum is completely wrong. In fact, Apple says the opposite in it's own documentation of structs. There are several reasons for this. One even though a struct is a value type that is no guarantee that is has value semantics. This is because a struct can be composed of reference types (classes) that do not have value semantics (mutable classes). This is not necessarily bad as it can used wisely for performance gains however that is a more advanced topic. Secondly while it is true that a struct is maintained on the stack, which is helpful performance wise, that is only true if the struct is very small in fact it can only be 3 words before it must allocate memory on the heap. Most model objects are not that small. Really making your large model objects structs, especially if you are using POP, will be a performance hit. Value semantics is the true goal not value types.
I have to agree with this comment, the goal is to achieve value semantics, independently of the implementation (
class). Post will be modified to reflect it.
It's beyond the scope of this post to explain value vs reference semantics and why/when you should use one instead of the other. This post by Andy Matuschak is pretty good and I would advise reading it. ↩
I actually have seen this a couple of times. ↩
I would be very impressed if a junior candidate would nail 9. ↩