On being a "bad cop"
As was mentioned before, the way to go is detaching yourself or any person for that matter from the issues to be raised. This means:
- Your rules need to be clear and written down, be it in a wiki, a styleguide, company documents, whatever you are using. This material must be accessible to the dev in question.
- When pointing out mistakes in a review, do not use phrases that involve you in any way. Instead shift blame to your documents, such as the styleguide and to your processes in general. An example of this can be, "Line X: According to the styleguide [link] static member variables have to follow the Y pattern."
You will not be able to avoid the bad cop feeling entirely, this is part of reviews. However with careful tone you can establish a review culture, where it is clear that not a developer is questioned, but only the code itself. It needs to be understood by all parties, that a review is not about criticizing a person or their work, but merely about impoving code and therefore your product.
Assigning proper tasks
This is probably my most important point and the one I think justifies my answer in the first place, as there are redundancies accross all answers posted:
Another answer by @Ertai87 mentions that correcting all minor mistakes is exhausting, I assume both for the reviewer as well as the reviewee. You also mention there is so much to correct, that the whole exercise somewhat derails. The answer I am referring to then states to focus on the major issues and ignore minor problems.
In my view this is not the correct approach.
When the tasks solved by the developer in question are so laiden with issues that reviewing them turns into an enormous undertaking, then I want to argue these tasks are too large for the developer in question. They are not ready and need to be assigned smaller tasks and get down the minor stuff first. That means, assigning e.g. bugfixes that only come with presumably only a few lines of code, only very minor features and other issues of the sort. Otherwise you will pass a ton of nonsense into your codebase because you are so busy with fixing their major mistakes, that you cannot afford to fix all the minor nonsense. Ultimately this will likely be time spent by other employees, who end up fixing all these things when they in turn work on the same code passages.
You should not expect your junior to be at the same level as everyone else, as the process of improving must be incremental. Still they are an employee, so you can expect that they bring value to the company, even if that value is relatively minor and only comes with and increases over time. So assign them smaller tasks and let them get the basics down first. The better they get, the larger their area of responsibility may become and so their tasks can increase in significance too.
Ask yourself this. With the time spent fixing that developer's code, how much time in comparison would you have spent doing it yourself?
As a team lead it is not written in stone that you have to review all code. Reviews can be done by all experienced employees, you have the option to use this tactic. A common way of doing this is to have a set of reviewers and a designated timeslot, e.g. once a week, when reviews are being processed. During that time all members of the set are required to review issues that are awaiting acceptance/rejection.
There are three main advantages to this:
- Code reviewing is a task that requires a lot of concentration. You can do only so much of it on your own during a day before you start passing mistakes into production. More people on this task means more concentration as a resource.
- No matter how experienced you are, there are likely some patterns in your code and some mistakes you repeat and are unaware of. This is true for your peers as well. When multiple people review members of your team and each other, at the very least the reviewee gets to see other patterns and other ways of solving problem X. This way knowledge is distributed in your team.
- The more people do reviews, the less a single person is running the risk of becoming the bad cop.
I will say though, this may depend on the company and the processes in place. Some workplaces may require a team lead to sign off on each and any piece of code and some workplaces may even do so due to a specific qualification that only an expert brings to the table. An example of this could be safety in a medical setting. If there are no such special requirements, but the processes currently require you to personally review all code that goes to production, then this can be raised with management arguing for increased efficiency of the team. Only you will know how things work at your company, use your best judgement whether distributing reviews can be achieved at your workplace.
A personal note: When we started code reviews at our company it was bumpy at first too, because it is hard not to feel criticized when your merge request is rejected with a bunch of stuff to fix. By now the team cherishes code reviews. Personally I have learned a lot from getting my code reviewed and so did my peers.
On defensive behavior
There are some things that can be discussed and some things that do not require a debate. Discussing this or that architecture is not uncommon. When doing so it is important to have a good reason for you want to change implementation X to implementation Y. Just saying "this is better" is insufficient. Of course you can go the authoritative way, but this is likely to demoralize and can show a lack of insight. On the other hand, when your team developed your styleguide I would expect you to have put some thought into why you decided you wanted to do thing X in way Y. These things should not end up in endless debates every single time, at least if the team's concensus on the matter has not changed.
All in all defensive behavior is not that quick or simple a problem to solve in my experience. I suggest doing one-on-one talks from time to time. Akin to performance reviews, but intended to be a non-interrogative talk between two team members, rather than a boss giving their subordinate the business. This is a time where you can share your gripes with how the employee performs by suggesting improvements. It is important to listen to their side as well. Are they content in what they are doing? If not, what are the issues on their mind? How can these be resovled?
That being said - if all such attempts do not bear fruit, then the authoritative way may be all that remains. In this case, explain to the developer that their performance is not satisfactory, as hard as it seems. This is basically a warning shot and at this point I would consider letting that person go.
I understand this may sound harsh, but ultimately every employee needs to bring value to the table eventually. The value of a junior in the beginning may be barely above zero, it may even be an investment into future productivity, without any immediate gain. However if time passes and no improvement is seen, then the company is wasting money and the employee is not the right fit for you.
There are a lot of things to try before this happens though, some mentioned above. You should ask yourself, if you can improve your communication with that employee and go from there. Are you phrasing things that force them into a defensive stance? If the developer turns out to be an asset to the company that was only hindered by poor communication between them and you, then everyone wins once this is recognized and resolved.
Another personal note: I have been working with and teaching quite a view juniors by now in my last couple of companies - mostly students in their bachelor's and master's, doing the first steps coding for real world applications, but also self-taught coders as well as juniors with a different educational background. One thing many students learn after taking this step, is that technical skills, no matter how good you are, are one part of a larger equation. Soft skills are largerly important and need to be caught up on if necessary.
Nowadays we filter candidates by assessing their character rather than their technical skill. They have similar education and we rely on this fact. Personality compatibility however is highly important, because one bad apple can poison the whole basket. So far, primarily by promoting a very welcoming company culture, we have been able to integrate all of our students and every single one of the became an asset eventually, but we take our time with them and don't assign someone who is learning the ropes giant tasks. As said - progress is incremental.
I hope this wall of text helps you in one way or the other. Good luck!