DEV Community

Azad Shukor
Azad Shukor

Posted on

Identity-Driven Premature Closure: The PR Review Trap I Fell Into Every Day

I review a PR. The diff is small. I scroll until something catches my eye:

if (!person.Data) return empty;
Enter fullscreen mode Exit fullscreen mode

I've seen patterns like this before. Something about it feels off. A familiar irritation rises — this ticket has been reopened multiple times. The developer has a history of missed scenarios. I don't trace the callers. I don't pull the branch. I don't read the full function. I post:

"Why isn't this checking .Data.name and returning 'anonymous'?"

Then I pull the code locally. I see the whole function — more lines, more context, the full shape. The logic becomes apparent. The guard clause is correct. The name replacement happens in the caller. The implementation follows best practice. I reply: "actually it is correct."

No apology. Just embarrassment. Again.

This happens on nearly every PR I review.

I called this laziness. I was wrong.


The Science Behind It

It's not laziness. It's identity-driven premature closure.

Three mechanisms converge:

1. Need for Cognitive Closure

In 1996, psychologist Arie Kruglanski defined the need for cognitive closure as the desire for "an answer on a given topic, any answer… compared to confusion and ambiguity" (Kruglanski & Webster, Psychological Review, 1996). It has two components:

  • Urgency tendency ("seizing"): the impulse to reach a conclusion as quickly as possible
  • Permanence tendency ("freezing"): the impulse to hold onto that conclusion once reached

When I see unfamiliar code in a narrow diff window, I feel confusion. Confusion is uncomfortable. My brain wants it resolved — fast. I seize on the first familiar pattern (return empty → "missing something"), freeze on it ("this is wrong"), and post.

The discomfort drives the speed. The speed prevents correction.

2. Confirmation Bias in Code Review

Devroey, Matton, and Vanderose (2024, arXiv:2407.01407) studied cognitive biases in code review. They found that confirmation bias — searching for evidence that supports your pre-existing belief — is especially strong when:

  • A reviewer identifies heavily with a "gatekeeper" role
  • The reviewer enters the review with expectations about the author

Both apply to me. I believe my job is to find what's wrong. I enter reviews of repeatedly-reopened tickets with a pre-existing story: "this developer doesn't check all scenarios." I don't read the code neutrally. I read it looking for a confirmation of that story — and I find one.

3. Identity-Protective Cognition

This is the deepest layer. Kunda (1990, Psychological Bulletin) showed that when reasoning touches self-concept, people don't just make errors — they're motivated to reach conclusions that protect their identity.

My identity is organized around being the person who catches bugs. Catching a real bug "feels the best." Finding clean code triggers embarrassment — because if the code is clean, then what value did I add? The review becomes less about code quality and more about proving I'm competent.

The quick criticism serves an identity function: it proves I'm doing my job. Even when it's wrong.


What Is the Proof?

Here is the chain — mapped from my own answers under direct questioning:

TRIGGER
  PR on a reopened ticket
  + Author with a bug history
  + Diff view that shows only fragments
        ↓
INTERNAL REACTION
  "Why is this still open?"
  + Identity activation: "I am the bug-catcher"
  + Irritation from missing context
        ↓
SHORTCUT
  Scroll until something familiar catches my eye
  + Familiarity feels like understanding (it isn't)
  + "I've been right before" → permission to trust my judgment
  + Skip: callers, tests, full function, pulling locally
        ↓
IMMEDIATE REWARD
  Temporary resolution of "what's my role?" anxiety
  + Relief from the discomfort of confusion
  + The possibility of that "best feeling" (catching a real bug)
        ↓
MISTAKE
  The code was correct. My criticism was based on a fragment.
  Flat retraction: "actually it is correct."
        ↓
LONG-TERM COST
  Embarrassment that compounds
  + Colleagues learn my reviews are unreliable
  + I model "criticize first, understand later"
  + I never practice reading unfamiliar code
  + Pattern repeats — every PR
Enter fullscreen mode Exit fullscreen mode

The evidence is in the pattern, not a single incident

This isn't one bad review. It's every review. The behavior persists because it's intermittently reinforced. Some of my criticisms are correct — real bugs do slip through. That variable reward (the same mechanism that makes slot machines addictive) keeps the habit alive. Enough of my snap judgments are right that my brain keeps gambling on the next one.

The familiarity illusion

I mistook familiarity for understanding. Recognizing a code pattern feels like comprehending the logic — but it isn't. The narrower my view (a diff fragment vs. the full function), the more my brain fills gaps with assumptions. And those assumptions feel as solid as facts.

I learned this when I traced what happens when I pull the branch locally: more lines, more context, bigger view → the logic becomes apparent → the irritation disappears → "this code is correct." The diff physically hides the evidence that would disprove my assumption.

The irritation was never about the developer

Under questioning, this surfaced: the irritation I feel during review isn't about the developer. It's about missing context. I feel irritated because I'm looking at a fragment and my brain needs the whole shape to function. I misattribute that irritation to the developer — and criticize them instead of closing the context gap. When I pull the code and see the full function, the irritation vanishes. The developer didn't change. The context did.


How to Fix It

The goal isn't to stop having the impulse. The goal is to redirect it before it produces damage.

The method: "I Observed / I Expected / Help Me Understand"

Adapted from the SBAR communication framework used in aviation and medicine (Haig, Sutton, & Whittington, 2006), where structured communication reduces errors in high-stakes judgment.

Every review comment must include three fields:

I observed: [concrete line(s) from the diff — not your interpretation]
I expected: [what pattern you thought should be there]
Can you help me understand: [the flow, the reasoning, the missing context]
Enter fullscreen mode Exit fullscreen mode

Why each field matters

Field What it does
I observed Forces you to name the actual code, not your story about it. The fragment becomes visible as a fragment — not as the whole truth.
I expected Surfaces your assumption. Once written, you can see it's an assumption — not an observation. The gap between "I observed" and "I expected" is where your error lives.
Can you help me understand Replaces accusation with inquiry. You're not a critic delivering a verdict. You're an understander who found a gap and wants to close it. This removes the identity threat for both you and the author.

Example: my own PR review, rewritten

Instead of:

"Why isn't this checking .Data.name and returning 'anonymous'?"

The method produces:

I observed: if (!person.Data) return empty — a guard clause checking Data, not the .name field.

I expected: to see a check for person.Data.name with an 'anonymous' fallback, since this ticket is about filling empty names.

Can you help me understand: where the name replacement happens in the flow? I may be missing the callers.

The second version doesn't assert. It reveals. The missing context (callers, the rest of the function) becomes a visible gap — and my instinct to scan the whole thing drives me to close it before posting.

Why this works for the specific mechanism

Problem How the method addresses it
Diff hides disconfirming context Writing "I observed only this fragment" makes the missing context feel physically present
Familiarity mistaken for understanding Writing "I expected" separates the recognition from the comprehension — you see the gap
Irritation misattributed to developer The "help me understand" phrase redirects the energy toward closing the gap, not blaming
"I've been right before" permission slip The template delays the post. The permission loses its urgency in the pause
Identity threat ("if I don't criticize, what's my role?") The understander role is equally valuable. Understanding clean code is a success, not a failure

The two-week protocol

Days 1–3: Every review comment uses the template. No exceptions. You will feel the obstacle. That's the friction of a habit changing.

Days 4–7: Add a fourth field: "What I have NOT yet seen: [callers / tests / full function / error paths]." Name the missing context explicitly before posting.

Days 8–14: Pull the branch before any critical comment. Use the template as your draft while viewing the full function locally. Check whether the "I expected" field changes once you have full context.

How to know it's working

Track three numbers daily:

Metric Target
Comments posted
Comments retracted ("actually it is correct") Zero by Day 14
Comments phrased as questions, not assertions 80%+ by Day 14

Track one qualitative signal: at the end of each day, write one sentence about how you felt during reviews. Irritation should shift from developer-directed to context-directed — and then to curiosity.

If it doesn't work

Two failure modes to watch for:

  1. Empty template: You fill the fields mechanically without actually pulling context. "I observed the diff. I expected it to be different. Help me understand." This is compliance, not change. The fix: the "What I have NOT yet seen" field is your honesty check. If you can't name a specific file or function you haven't inspected, you're not using the method.

  2. Template as weapon: You use the structure to sound more authoritative while still being wrong. "I observed a critical flaw. I expected best practices. Help me understand why this was done incorrectly." The fix: if "Can you help me understand" isn't a genuine question, rewrite it until it is.


Conclusion

I called myself lazy. I wasn't lazy. I was running a learned pattern:

  • Professional identity fused with finding fault
  • Need for cognitive closure triggered by unfamiliar code in narrow context
  • Familiarity mistaken for understanding
  • Irritation from missing context, misattributed to developers
  • "I've been right before" as a permission slip to skip verification
  • Intermittent reinforcement maintaining the habit across every PR

The name for this pattern is identity-driven premature closure. It's not a personality flaw. It's not a diagnosis. It's a behavioural mechanism that can be dismantled once you see it clearly.

The fix isn't "try harder." It's not "read more carefully." It's a structure that makes your own gaps visible to you — before you post. Three fields: what you saw, what you expected, what you need help understanding.

The method doesn't silence the impulse to judge. It gives the impulse a shape that leads to truth instead of error. And over time, it rewires what "doing my job" means. My job isn't to be the best critic. It's to be the best understander. When I understand fully and the code is clean, that's not a failed review. That's a successful one.


References

  • Kruglanski, A. W., & Webster, D. M. (1996). Motivated closing of the mind: "Seizing" and "freezing." Psychological Review, 103(2), 263–283.
  • Devroey, X., Matton, N., & Vanderose, B. (2024). Towards debiasing code review support. arXiv:2407.01407.
  • Kunda, Z. (1990). The case for motivated reasoning. Psychological Bulletin, 108(3), 480–498.
  • Haig, K. M., Sutton, S., & Whittington, J. (2006). SBAR: A shared mental model for improving communication between clinicians. The Joint Commission Journal on Quality and Patient Safety, 32(3), 167–175.
  • Parnin, C., & Orso, A. (2011). Are automated debugging techniques actually helping programmers? Proceedings of the 2011 International Symposium on Software Testing and Analysis (ISSTA), 199–209.

Top comments (0)