I have recently been involved in evaluating recruitment assignments for the company I work for. From these experiences, and from the feedback I've received myself on various occasions, a concept is emerging of what I'd like a well-written assignment to look like. I'll be writing from a backend perspective, but I'll try to frame my thoughts in a way that makes them as universal as possible.
I realize that my experience is quite narrow and will certainly not be universal. Some advice may meet with controversy.
One piece of golden advice
If I condensed everything I'm about to write into one sentence, it would be this:
"Write the application as if you were actually going to maintain it”.
I know that in college it's often about bouncing off functionality, but at work you'll be doing serious stuff.
So, what sins do candidates (including me) commit?
First, and probably most important, is mixing high-level abstractions with low-level details. An example of such a thing can be putting all the code into the part responsible for handling HTTP requests. The function or method that receives the request should only use dependencies to perform data parsing, permission checking, and data processing. Let's consider two such solutions (code written without any relation to any framework). Which handler is easier to understand?
In the first case, all the details are brought to the surface. Any change actually affects everything. Changing the way we do database queries can affect permission checking. In the second solution, we inject and manage dependencies. The code is much more readable, we make changes in places that have clearly defined responsibilities.
Another issue is git support.
The common approach of treating git as a tool to zip code is a pain in projects. The absolute minimum for me is a clear commit message and a squash of commits doing the same thing. Seeing five commits in a row with a "fixes" or "asdf" message does not speak well of the candidate's approach.
I also advise against commits that contain code with protected data. If you accidentally put a private key into the repository, you need to delete the commit. It would be good to create a branch for each feature. Ideally, you should have one protected branch allowing code only if it passes automated tests.
While we're at it - CI is always welcome. GitHub and GitLab allow you to run tests for free and it's worth taking advantage of.
However, tests are required for this. Sometimes it is a rigid requirement, sometimes not. If it is, then you should write them. If not, then... write them anyway. Even if we don't do TDD, tests in the long run make life easier and, after all, we’re supposed to write the application as if we were going to maintain it.
Sometimes (this happens in real work, too) we are so pressed for time that we cannot test everything. What should we do then?
We test the most important functionalities. If access to some resource is to be only allowed for logged-in users, let's at least check if we blocked access for users who are not logged-in. If we are to grant a discount, let's at least check the correctness of the algorithm out of context - HTTP requests, database, etc.
Okay, but testing isn't the only thing that we’ve ran out of time for. What then?
Write everything poorly or write some things well? I prefer the second option. It may happen that some company will prefer the first approach (here I point out a potential conflict, which I wrote about at the beginning), but at this point it is worth considering whether we want to work somewhere where it is standard to half-bake things. In my opinion it is normal that doing a recruitment task in one’s free time leads to not always being able to devote enough hours to do everything well.
When reviewing assignments, I try to evaluate how the candidate thinks, not whether the application provides "business value". Sometimes you can negotiate an extra couple of days to complete the task, sometimes it may be that what we have implemented may be enough. It's worth having a conversation here.
Is that all?
No, but these tips cover about 80-90% of my comments on the code I review. I've seen these pain points in the code of candidates for everything from junior to senior positions, so I dare say that it's not common knowledge. I don't guarantee that by sticking to these guidelines you will get the job, but I do guarantee that you will increase your chances. Good luck.