DEV Community

Cover image for Why Code Reviews Feel Personal
Derek Mwale
Derek Mwale

Posted on

Why Code Reviews Feel Personal

The pull request is about the code. So why does it sometimes feel like someone just criticized your intelligence?

There is a strange moment in every programmer’s life.

You spend three hours solving a problem.

Maybe five.

Maybe the entire weekend.

You stare at a bug that refuses to explain itself. You rewrite the same function four times. You search documentation. You question your career. You finally discover that the problem was a missing null check, a race condition, an incorrect database query, or a variable that was initialized in the wrong place.

Eventually, it works.

The tests pass.

The application stops crashing.

You push your branch.

You open a pull request.

And then someone leaves this comment:

“Could we simplify this?”

Suddenly, your heart rate increases.

Another comment appears.

“I think this should probably be moved into a separate service.”

Then another.

“Why are we doing this here?”

And now, somehow, a conversation about a function with 27 lines has become an existential crisis.

You read the comments again.

Maybe the reviewer is right.

Maybe the code really is complicated.

Maybe the architecture is inconsistent.

But that is not what your brain hears.

Your brain hears:

“You are not good enough.”

That is why code reviews are strange.

Technically, they are supposed to be simple.

Someone writes code.

Someone else reads it.

The team improves it.

Everyone ships better software.

But humans are involved.

And humans have egos, identities, insecurities, histories, ambitions, and an almost supernatural ability to interpret a comment about a for loop as a personal attack.

The code review is not personal.

But it often feels personal.

And understanding why might be one of the most important things you can learn as a programmer.


Code Is More Than Code

To understand why reviews feel personal, we first need to understand something uncomfortable:

Programmers do not just write code. They put themselves into it.

Every piece of code contains decisions.

Why did you use this algorithm?

Why did you choose PostgreSQL instead of MongoDB?

Why is this function asynchronous?

Why is this abstraction here?

Why did you create three classes instead of one?

Why did you use Rust?

Why is there a microservice for something that could probably be a function?

These decisions are not random.

They come from your experience.

Your education.

The tutorials you watched.

The bugs you survived.

The codebases that traumatized you.

The senior developer who once told you that global state was evil.

The startup where everything was a microservice.

The company where everything was one giant PHP file.

Your code is a compressed representation of your engineering history.

That means when someone says:

“I wouldn't do it this way.”

They may only be talking about the implementation.

But because the implementation came from you, it is easy to hear:

“I wouldn't think the way you think.”

That is the first problem.

We confuse criticism of the artifact with criticism of the creator.

A painting is criticized.

The painter feels criticized.

An article is edited.

The writer feels criticized.

A song is rejected.

The musician feels rejected.

And in software engineering, a function gets reviewed.

The programmer quietly starts questioning whether they should have studied accounting instead.


The Pull Request Is a Public Performance

Writing code privately feels very different from having your code reviewed.

When you are coding alone, you are in control.

You can experiment.

You can write terrible temporary code.

You can create a variable called:

let thing2 = thing1;
Enter fullscreen mode Exit fullscreen mode

Nobody knows.

You can promise yourself you will clean it later.

Maybe you will.

Maybe you won't.

That is between you and your Git history.

But the moment you open a pull request, something changes.

Your work becomes visible.

Other engineers can see your decisions.

They can see what you missed.

They can see what you misunderstood.

They can see that the elegant architecture you described in the stand-up meeting somehow resulted in a 400-line function called:

process_everything()
Enter fullscreen mode Exit fullscreen mode

And now you are exposed.

This is why code reviews can feel less like collaboration and more like an examination.

You are no longer simply writing software.

You are presenting your thinking.

Every line becomes evidence.

Every abstraction becomes a statement.

Every missing test becomes suspicious.

Every comment from a reviewer feels like a red pen on an exam paper.

The pull request becomes a stage.

And suddenly, engineering becomes performance.


We Attach Intelligence to Programming

Programming has another problem.

Many programmers connect their identity to intelligence.

This is dangerous.

From the moment people start learning programming, they hear stories about geniuses.

The teenager who built a billion-dollar company.

The legendary engineer who writes operating systems.

The programmer who understands distributed systems before breakfast.

The person who contributes to the Linux kernel while everyone else is still figuring out CSS.

Technology has created a strange mythology around intelligence.

We talk about “10x engineers.”

We celebrate people who can solve impossible algorithm problems.

We create competitive programming contests.

We measure people with technical interviews that sometimes feel like mathematical gladiator arenas.

Eventually, many developers internalize a simple idea:

If I am good at programming, I am intelligent.

Unfortunately, the reverse also becomes true.

If my code is bad, maybe I am not intelligent.

And this is where code reviews become emotionally dangerous.

Because a reviewer saying:

“This has a bug.”

Can accidentally become:

“You are not as smart as you think you are.”

A reviewer saying:

“This could be cleaner.”

Can become:

“Your thinking is messy.”

A reviewer suggesting a simpler solution can become:

“You made this unnecessarily complicated because you don't understand the problem.”

None of those things may actually be true.

But our brains are excellent at constructing emotional fan fiction.


The Effort Problem

There is another reason code reviews hurt.

Reviewers usually see the code. They do not see the struggle.

Imagine this.

You spent eight hours solving a problem.

You tried six approaches.

Three failed.

One caused production errors.

One worked but was too slow.

One created a memory leak.

Eventually, after hours of debugging, you arrive at the solution.

The reviewer opens the pull request.

They spend five minutes reading it.

Then they write:

“I think this can be done in one query.”

You stare at the comment.

One query?

ONE QUERY?

Where was this person when you were suffering?

Where were they when you had twelve browser tabs open?

Where were they when the debugger looked like a crime scene?

Where were they when you almost deleted the repository and started farming?

The reviewer sees the final result.

They do not see the journey.

And humans naturally value effort.

If something took us a long time, we unconsciously believe it deserves respect.

So when someone casually suggests replacing our eight-hour solution with something simpler, it can feel disrespectful.

Not because they are wrong.

But because they accidentally ignored the invisible work behind the code.

This is one of the most important psychological realities in software engineering:

The amount of effort required to discover a solution is often unrelated to how complicated the final solution looks.

Great solutions frequently look obvious after someone discovers them.

That does not mean they were obvious before.


Code Reviews Trigger Ownership

When you write code, something strange happens.

You begin to own it.

Even though the repository belongs to the company.

Even though the application belongs to the users.

Even though the code may be deleted next week.

You still think:

My code.

And ownership creates attachment.

Imagine you build this:

pub fn calculate_total(items: &[Item]) -> f64 {
    items.iter().map(|item| item.price).sum()
}
Enter fullscreen mode Exit fullscreen mode

Someone comments:

“Can we rename this to sum_prices?”

Technically, this is a tiny suggestion.

Emotionally?

You may suddenly become a constitutional lawyer defending the original function name.

You explain the semantic meaning.

You discuss future extensibility.

You mention domain-driven design.

You cite three software architecture books.

You create a 14-message thread.

All because someone wanted to rename a function.

Why?

Because the discussion is no longer about the function name.

It is about ownership.

When someone changes something we created, our brains sometimes interpret it as someone entering our territory.

This is irrational.

But it is human.

The healthiest engineers eventually learn something extremely liberating:

The code is not you.

You wrote it.

That does not mean you have to defend it forever.

You can delete it.

Refactor it.

Replace it.

Rewrite it.

Your identity survives.

The compiler does not care about your feelings.

And honestly, neither does production.


The Architecture of Ego

Ego in software engineering is fascinating because it often hides behind technical language.

Nobody says:

“I feel personally attached to this abstraction.”

Instead, they say:

“This architecture is more scalable.”

Nobody says:

“I don't want to admit my approach was wrong.”

Instead, they say:

“There are trade-offs.”

Nobody says:

“Changing this would hurt my pride.”

Instead, they say:

“We should avoid unnecessary refactoring.”

And sometimes those statements are true.

There really are trade-offs.

Architecture really matters.

Refactoring really can introduce risk.

But sometimes technical arguments are simply ego wearing a hoodie.

That is one of the hardest things to recognize in yourself.

Because ego rarely introduces itself.

It does not knock on the door and say:

“Hello, Derek. You are defending this terrible implementation because you don't want to admit Sarah found a better solution.”

No.

It gives you a much more sophisticated argument.

It tells you:

“The existing implementation is optimized for future scalability requirements.”

Meanwhile, there are six users.


Senior Developers Can Accidentally Make Reviews Worse

Experience creates another strange dynamic.

Senior developers often see problems faster.

That is their advantage.

They have seen similar bugs.

Similar architectures.

Similar failures.

They can look at something and immediately think:

Oh no. This is going to hurt later.

The problem is that expertise can create impatience.

A senior developer sees an obvious issue.

The junior developer spent two days solving it.

The senior developer writes:

“This is wrong.”

Technically accurate.

Emotionally catastrophic.

Because communication matters.

There is a massive difference between:

“This is wrong.”

And:

“I think this approach might create a problem when we have concurrent requests. What do you think about handling the state differently?”

Both comments may lead to the same technical solution.

But one treats the author like a defective machine.

The other treats them like an engineer.

Good code reviews are not just about detecting mistakes.

They are about transferring understanding.

The best reviewer does not simply say:

“Fix this.”

They help answer:

Why is this a problem?

Because when someone understands the reason, they become better.

When they only follow instructions, they become dependent.


The Difference Between a Review and a Judgment

This distinction is everything.

A review examines the work.

A judgment examines the person.

A review says:

“This function has too many responsibilities.”

A judgment says:

“You don't understand clean architecture.”

A review says:

“We might have a race condition here.”

A judgment says:

“You clearly don't understand concurrency.”

A review says:

“Could we add a test for this edge case?”

A judgment says:

“Why do you never write tests?”

The technical content may be similar.

But the psychological effect is completely different.

The first focuses on the software.

The second assigns identity.

And once identity enters the conversation, people become defensive.

Because now the discussion is no longer:

How do we improve this system?

It becomes:

Am I a good programmer?

That is a much harder question to answer in a GitHub comment.


Why Tone Is So Difficult in Text

Code reviews happen mostly through text.

And text is terrible at carrying emotional nuance.

Consider this comment:

“Why did you do this?”

Maybe the reviewer is genuinely curious.

Maybe they want context.

Maybe they are trying to understand a business requirement.

But the author may read it as:

“What kind of idiot would do this?”

The words are identical.

The tone exists entirely inside the reader's head.

That makes asynchronous communication dangerous.

You cannot see facial expressions.

You cannot hear hesitation.

You cannot tell whether someone is smiling.

You cannot hear:

“Why did you do this? 🙂”

Instead, you see:

WHY DID YOU DO THIS.

And suddenly you are preparing for war.

This is why experienced teams often develop review cultures around phrases like:

  • “What do you think about…”
  • “Could we consider…”
  • “I'm wondering if…”
  • “Would this cause…”
  • “Maybe we could…”
  • “Non-blocking suggestion:”

These phrases are not just corporate politeness.

They reduce unnecessary emotional friction.


The Dangerous Phrase: “Obviously”

There are few words more destructive in software engineering than:

“Obviously.”

Nothing is obvious to everyone.

If something is obvious to you, it usually means you have information the other person does not.

Experience makes patterns obvious.

Context makes decisions obvious.

History makes architecture obvious.

But saying:

“Obviously this should be asynchronous.”

Does not teach anyone anything.

It only communicates:

“I understand something you don't.”

That creates hierarchy.

And hierarchy creates insecurity.

A much better comment is:

“If this runs synchronously, could it block the request thread under heavy load? Would moving it to a background job help?”

Now the reviewer is still demonstrating expertise.

But they are also sharing the reasoning.

That changes everything.


Junior Developers Often Feel Reviews More Deeply

When you are experienced, you have evidence that you can survive being wrong.

You have written terrible code before.

You have broken production.

You have fixed impossible bugs.

You have rewritten entire systems.

You know that being wrong is not the end of your career.

But junior developers do not have that emotional history yet.

Every mistake feels significant.

Every rejected pull request feels like evidence.

Every comment feels like someone adding another entry to a secret list titled:

Reasons We Should Never Have Hired This Person.

Of course, that list probably does not exist.

But anxiety does not require evidence.

That is why mentorship matters.

A good senior engineer understands that the goal is not simply to produce perfect code today.

The goal is to help produce stronger engineers tomorrow.

Sometimes that means being technically correct and emotionally intelligent.


Code Review Culture Can Make or Break a Team

Two companies can use the exact same technology stack.

The same programming language.

The same CI pipeline.

The same repository structure.

The same cloud provider.

And have completely different engineering cultures.

At Company A:

Every pull request feels like a courtroom.

People defend every decision.

Reviewers hunt for mistakes.

Comments are aggressive.

Nobody wants to look stupid.

Developers avoid asking questions.

Junior engineers copy patterns without understanding them.

People optimize for being right.

At Company B:

Reviews are conversations.

People ask questions.

Reviewers explain trade-offs.

Authors are comfortable saying:

“You're right. I missed that.”

Senior developers admit mistakes.

Junior developers challenge assumptions.

People optimize for learning.

Technically, both companies review code.

Culturally, they are doing completely different things.

One is using code review as a gatekeeping mechanism.

The other is using it as a knowledge-sharing system.

The difference is enormous.


The Best Engineers Are Comfortable Being Wrong

This might be one of the most underrated engineering skills.

Not intelligence.

Not speed.

Not knowing every framework.

The ability to say:

“You're right.”

That is powerful.

Imagine discovering that your entire approach was wrong.

Your database schema.

Your abstraction.

Your API design.

Your concurrency model.

Someone points out a better solution.

You have two choices.

Option One

Defend everything.

Find reasons why the new approach is risky.

Bring up edge cases.

Mention theoretical scalability.

Create increasingly complicated arguments.

Eventually win the discussion.

And keep worse code.

Option Two

Say:

“Good catch. I didn't consider that.”

Fix it.

Move on.

The second option requires confidence.

Insecure people often think admitting mistakes makes them look weak.

In reality, the opposite is usually true.

Strong engineers do not need to pretend they are always correct.

They know they will be wrong again.

And they are comfortable with that.


Your First Draft Is Not Your Final Identity

One reason programmers struggle with reviews is because they treat the first implementation as a declaration.

They think:

This is my solution.

But software engineering is not about producing perfect thoughts on the first attempt.

It is iterative.

The first version is supposed to be imperfect.

That is why we have:

  • Pull requests
  • Tests
  • Staging environments
  • CI pipelines
  • Refactoring
  • Monitoring
  • Bug reports
  • Version control

The entire software industry is basically a giant admission that humans do not get things right immediately.

If every programmer could produce perfect software alone, Git would be unnecessary.

Teams would be unnecessary.

Code reviews would be unnecessary.

Production would probably still find a way to crash, but at least we would feel confident.

The review exists because your first idea is not necessarily your best idea.

And that is okay.


How to Receive Code Reviews Without Losing Your Mind

Here are a few principles that have helped me think about reviews differently.

1. Assume the Reviewer Is Attacking the Code, Not You

Unless someone is clearly being disrespectful, start with the most charitable interpretation.

They found a problem.

That is literally part of the process.

If someone says:

“This could cause a memory leak.”

Do not immediately start analyzing their personality.

Check whether it could cause a memory leak.

The bug does not care who wins the argument.


2. Ask for the Reason

If you disagree with a suggestion, do not immediately defend yourself.

Ask:

“Can you explain the concern here?”

Sometimes you will discover that the reviewer has context you don't.

Sometimes they will discover that you had context they didn't.

Either way, the conversation becomes technical rather than emotional.


3. Don't Defend Every Line

You do not need to be the lawyer for every variable you have ever named.

Sometimes a reviewer suggests something better.

Accept it.

You are allowed to change your mind.

The world will continue spinning.


4. Separate Preference From Correctness

This is a major source of pointless arguments.

Some things are objectively dangerous.

A SQL injection vulnerability is not a style preference.

A race condition may not be a style preference.

A missing authentication check is definitely not a style preference.

But:

Tabs versus spaces?

Function naming?

File organization?

Brace placement?

Sometimes engineers fight as if these questions determine the future of civilization.

They don't.

Use linters.

Use formatters.

Automate the boring arguments.

Save your emotional energy for problems that matter.


How to Give Better Code Reviews

Being a good reviewer is also a skill.

Here are a few principles.

Review the Code, Not the Person

Bad:

“You don't understand how this works.”

Better:

“I think this might behave unexpectedly when multiple requests arrive simultaneously.”

The second one teaches.

The first one humiliates.


Explain the Why

Instead of:

“Change this.”

Try:

“Could we change this? I'm concerned that the current version might create duplicate records if the request is retried.”

Now the author learns something.


Separate Blocking Issues From Suggestions

Not everything needs to stop the pull request.

Use categories mentally:

Blocking

This must be fixed.

Important

This should probably be fixed.

Suggestion

This might improve readability.

Nitpick

I personally prefer this.

Without this distinction, developers can feel like every comment is equally serious.

And suddenly:

“Rename this variable.”

Feels as urgent as:

“This endpoint exposes every user's password.”

They are not the same problem.

Hopefully.


Leave Positive Feedback Too

Code review should not become a bug detector.

Sometimes someone makes a good decision.

Say it.

“Nice handling of the retry logic here.”

“Good test coverage.”

“I like this abstraction.”

“This is much simpler than the previous implementation.”

Positive feedback helps reinforce good engineering decisions.

It also reminds developers that reviews are not just a list of reasons they are disappointing.


The Real Goal of Code Review

The ultimate goal is not perfect code.

There is no such thing.

Every system contains compromises.

Every architecture contains assumptions.

Every abstraction eventually annoys someone.

The goal of code review is to improve the probability that the software survives reality.

Reality is brutal.

Users will enter unexpected data.

Networks will fail.

Servers will restart.

Databases will slow down.

APIs will return nonsense.

Someone will deploy on Friday.

Someone will accidentally remove an environment variable.

Someone will discover that the “temporary solution” has been running in production for four years.

Code review is a defense mechanism against human limitations.

You are not reviewing code because the author is incompetent.

You are reviewing it because everyone is blind to some of their own mistakes.

That includes senior engineers.

Especially senior engineers.

Experience does not make you incapable of mistakes.

It just gives you more sophisticated ways to make them.


The Humbling Truth

Here is the truth every programmer eventually learns.

Some of the code you are incredibly proud of today will embarrass you in five years.

Maybe sooner.

You will open an old repository and think:

Who wrote this?

Then you will check Git.

And discover:

Oh. Me.

This is actually good news.

If your old code embarrasses you, it probably means you improved.

The goal is not to create code you will defend forever.

The goal is to become the kind of engineer who can look at old decisions and say:

“That made sense with what I knew then. I know more now.”

That is growth.

And code reviews accelerate that growth.

They expose you to other ways of thinking.

Other patterns.

Other experiences.

Other mistakes.

A good reviewer can save you from discovering something the hard way.

And the hard way is usually production.


Conclusion: It's Personal Because We Are Human

Code reviews feel personal because programming is deeply connected to identity.

We spend hours thinking.

Designing.

Debugging.

Building.

We make decisions with incomplete information.

Then we expose those decisions to other people.

Of course it feels vulnerable.

But vulnerability is not weakness.

It is part of collaboration.

The healthiest engineering teams understand something important:

The person is not the code.

The code can be wrong while the programmer is talented.

The code can be messy while the engineer is learning.

The architecture can fail while the decision was reasonable.

A pull request can be rejected without rejecting the person who wrote it.

And sometimes the best thing someone can do for your growth is point at something you spent three days building and say:

“Have you considered another approach?”

That comment might annoy you.

You might stare at it for five minutes.

You might temporarily question the reviewer's ancestry.

But eventually, if the team culture is healthy, you will realize something.

They were not trying to destroy your work.

They were trying to improve it.

And maybe improve you along the way.

The best engineers are not the ones whose code never gets criticized.

Those engineers probably aren't letting anyone look at their code.

The best engineers are the ones who can survive the uncomfortable moment when someone says:

“I think we can do better.”

Then look at the code.

Take a breath.

And answer:

“Show me.”

Because in the end, that is what code review should be.

Not a battle.

Not an exam.

Not a public trial of your intelligence.

Just a group of imperfect humans trying to make fewer mistakes before the software reaches millions of other imperfect humans.

And honestly?

That might be the most human thing about programming.

The code may be logical.

The machines may be precise.

The compiler may be brutally honest.

But the people writing the software?

We are emotional.

We are insecure.

We are proud.

We are curious.

We are wrong.

We learn.

And somewhere between a pull request, a red comment, and a slightly passive-aggressive suggestion about renaming a variable, we slowly become better engineers.

Maybe that is why code reviews feel personal.

Because behind every line of code is a person saying:

“This is how I thought the problem should be solved.”

And behind every good review is another person saying:

“Interesting. Let's think about it together.”

Top comments (0)