<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: IndieHacker</title>
    <description>The latest articles on DEV Community by IndieHacker (@devglish).</description>
    <link>https://dev.to/devglish</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3866954%2Fe38025b3-12e2-4f42-994b-4a1d84d00f9a.jpg</url>
      <title>DEV Community: IndieHacker</title>
      <link>https://dev.to/devglish</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devglish"/>
    <language>en</language>
    <item>
      <title>The Art of Saying "No" in Code Review</title>
      <dc:creator>IndieHacker</dc:creator>
      <pubDate>Thu, 09 Apr 2026 02:18:47 +0000</pubDate>
      <link>https://dev.to/devglish/the-art-of-saying-no-in-code-review-4l7b</link>
      <guid>https://dev.to/devglish/the-art-of-saying-no-in-code-review-4l7b</guid>
      <description>&lt;h1&gt;
  
  
  The Art of Saying "No" in Code Review: 7 Levels from Soft to Hard
&lt;/h1&gt;

&lt;p&gt;There's a skill that nobody teaches in CS programs: &lt;strong&gt;how to reject code without making it personal.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Native English speakers learn this through years of cultural osmosis. Non-native speakers often learn it the hard way — by accidentally sounding rude, or by being so polite that their blocking feedback gets ignored.&lt;/p&gt;

&lt;p&gt;I've collected these 7 levels from real code reviews across 4 companies and 3 countries. Each level serves a different purpose. Master all 7, and your code reviews will be clearer, kinder, and more effective.&lt;/p&gt;




&lt;h2&gt;
  
  
  Level 0: The Positive Observation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Not saying no at all — just pointing out what's good.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nice approach here — the early return keeps the happy path clean.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TIL about this API. Clean usage.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This is much more readable than the previous version. 👍
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When code is genuinely good. Sounds obvious, but most reviewers only comment when something is wrong. Positive comments build trust so that your "no"s land softer later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-native speaker trap:&lt;/strong&gt; Don't write "Good job!" — it sounds patronizing from a peer. Stick to specific observations: what is good and why.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Sounds off&lt;/th&gt;
&lt;th&gt;✅ Sounds native&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Good job!&lt;/td&gt;
&lt;td&gt;Nice — this handles the edge case cleanly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Very good code&lt;/td&gt;
&lt;td&gt;This reads well, especially the error handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I think this is perfect&lt;/td&gt;
&lt;td&gt;LGTM 👍&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Level 1: The Nitpick
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"You could change this, but you don't have to."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nit: `userCount` might read better than `cnt` here.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ultra-nit: extra blank line on L42.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Style nit: we usually put the constant on the left in comparisons.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Naming, formatting, minor style preferences. Things that don't affect functionality or correctness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The magic word:&lt;/strong&gt; "Nit" or "Nit:" at the start. This single word tells the author: "I noticed this, but don't block your PR on it." It's a social contract — if you label something a nit, you can't later block the PR over it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-native speaker trap:&lt;/strong&gt; Don't write "You should rename this variable." Without the "Nit:" prefix, it sounds like a hard requirement.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Sounds like a command&lt;/th&gt;
&lt;th&gt;✅ Sounds like a suggestion&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;You should rename this&lt;/td&gt;
&lt;td&gt;Nit: maybe &lt;code&gt;fetchUser&lt;/code&gt; instead of &lt;code&gt;getData&lt;/code&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change this variable name&lt;/td&gt;
&lt;td&gt;Nit: &lt;code&gt;count&lt;/code&gt; → &lt;code&gt;activeUserCount&lt;/code&gt; for clarity?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;This name is bad&lt;/td&gt;
&lt;td&gt;Nit: the name doesn't tell me what it counts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Level 2: The Suggestion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Here's an alternative approach. Take it or leave it."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Consider extracting this into a helper — it's used in 3 places already.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Another option: we could use a Map here instead of filter + find. 
Would bring this from O(n²) to O(n). Up to you.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Have you considered using early return here? Might reduce the nesting.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When you see a better approach but the current one isn't wrong. The author should feel free to disagree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key phrases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Consider..." — the Swiss army knife of suggestions&lt;/li&gt;
&lt;li&gt;"Another option:" — explicitly frames it as optional&lt;/li&gt;
&lt;li&gt;"Have you considered..." — implies you're curious, not commanding&lt;/li&gt;
&lt;li&gt;"Up to you" / "Take it or leave it" — explicit opt-out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-native speaker trap:&lt;/strong&gt; "I think you should..." is NOT a suggestion in English. "Should" carries obligation. "I think" doesn't soften it enough.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Hidden command&lt;/th&gt;
&lt;th&gt;✅ Actual suggestion&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;I think you should use a Map here&lt;/td&gt;
&lt;td&gt;Have you considered using a Map here?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;It would be better to extract this&lt;/td&gt;
&lt;td&gt;Consider extracting this — it's used in 3 places&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need to add caching&lt;/td&gt;
&lt;td&gt;This might benefit from caching if it's called frequently&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Level 3: The Question
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"I don't understand this. Help me understand before I judge."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Curious: why `setTimeout` here instead of `requestAnimationFrame`?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Is there a reason we're not using the existing `parseDate` util? 
Might be duplicating logic — or maybe I'm missing context.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What happens if `user` is null here? I might be wrong, but this 
looks like it could panic on L47.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When you think something might be wrong but you're not sure. The question format gives the author an out — maybe they have context you don't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this is powerful:&lt;/strong&gt; Questions are face-saving. If the author made a mistake, they can fix it without anyone explicitly saying "you're wrong." If they had a good reason, they can explain without feeling defensive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-native speaker trap:&lt;/strong&gt; "Why did you do it this way?" sounds confrontational in English, even if it's genuinely curious in your language. Add a softener.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Sounds confrontational&lt;/th&gt;
&lt;th&gt;✅ Sounds curious&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Why did you do it this way?&lt;/td&gt;
&lt;td&gt;Curious about the approach here — was X considered?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Why didn't you use X?&lt;/td&gt;
&lt;td&gt;Is there a reason we're not using X? (Might be missing context)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;This doesn't make sense&lt;/td&gt;
&lt;td&gt;Help me understand the flow here — I'm not sure I follow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is this for?&lt;/td&gt;
&lt;td&gt;Could you add a brief comment here? I had to read it twice&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Level 4: The Concern
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"I think this might cause problems. Let's discuss."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Concern: this allocates on every render. With 1000+ items, 
we might see jank. Want to memoize or move it outside the loop?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm a bit worried about the race condition here — if two requests 
hit this endpoint simultaneously, we could double-write. 
Could we add a lock or use an upsert?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Heads up: this pattern has bitten us before in the billing module 
(see #312). Might be worth adding a guard.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Real problems that need addressing, but where you're open to the author choosing &lt;em&gt;how&lt;/em&gt; to fix it. You're flagging the issue, not dictating the solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key phrases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Concern:" — like "Nit:" but serious&lt;/li&gt;
&lt;li&gt;"I'm a bit worried about..." — personal concern, not accusation&lt;/li&gt;
&lt;li&gt;"Heads up:" — framing as a friendly warning&lt;/li&gt;
&lt;li&gt;"This pattern has bitten us before" — evidence-based, not opinion-based&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-native speaker trap:&lt;/strong&gt; "This is wrong" or "This has a bug" is too direct even when it's true. Frame it as a risk or concern.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Too direct&lt;/th&gt;
&lt;th&gt;✅ Appropriately concerned&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;This is wrong&lt;/td&gt;
&lt;td&gt;I think there might be an issue here — [explain]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;This will crash&lt;/td&gt;
&lt;td&gt;This could panic if &lt;code&gt;user&lt;/code&gt; is nil — want to add a guard?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You have a race condition&lt;/td&gt;
&lt;td&gt;Heads up: I think there's a race condition here between X and Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;This code is inefficient&lt;/td&gt;
&lt;td&gt;Concern: this is O(n²) — might be slow with large datasets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Level 5: The Blocker
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"This needs to change before we can merge."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;Blocking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;vulnerable&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;injection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; 
&lt;span class="n"&gt;We&lt;/span&gt; &lt;span class="n"&gt;need&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;parameterized&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;See&lt;/span&gt; &lt;span class="n"&gt;our&lt;/span&gt; &lt;span class="n"&gt;guide&lt;/span&gt; &lt;span class="k"&gt;at&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This needs to be addressed: the API key is hardcoded on L23. 
Should come from env/secrets.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I can't approve this as-is: the migration is irreversible and 
we don't have a rollback plan. Can we discuss before merging?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Security vulnerabilities, data loss risks, breaking changes without migration, violations of critical conventions. Things that would cause real damage in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key phrases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Blocking:" — the nuclear prefix, use sparingly&lt;/li&gt;
&lt;li&gt;"This needs to be addressed:" — clear that this isn't optional&lt;/li&gt;
&lt;li&gt;"I can't approve this as-is:" — states your position, invites discussion&lt;/li&gt;
&lt;li&gt;"Can we discuss before merging?" — escalates to synchronous conversation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-native speaker trap:&lt;/strong&gt; Two opposite mistakes here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Being too soft on blockers: "Maybe we should consider not hardcoding the API key?" — NO. If it's a security issue, be direct.&lt;/li&gt;
&lt;li&gt;Using blocker language for nits: "This needs to change: rename &lt;code&gt;cnt&lt;/code&gt; to &lt;code&gt;count&lt;/code&gt;." — NO. Save the strong language for real issues.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Too soft for a real issue&lt;/th&gt;
&lt;th&gt;✅ Appropriately firm&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Maybe don't hardcode the API key?&lt;/td&gt;
&lt;td&gt;Blocking: API key on L23 must come from env. Hardcoded secrets will hit our security scanner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I think this might have a SQL injection&lt;/td&gt;
&lt;td&gt;Blocking: SQL injection on L45. Must use parameterized queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perhaps we should add auth here&lt;/td&gt;
&lt;td&gt;This endpoint needs auth — it's currently public and returns PII&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Level 6: The Redirect
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"This is the wrong direction. Let's step back."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I think we might be overcomplicating this. The existing `UserService.fetch()` 
already handles this case — could we use that instead of building a new path?

Happy to pair on this if it'd help.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before we go further: I chatted with @sarah and this feature is being 
redesigned in Q3. Might be worth checking if this approach still aligns. 
Can we sync briefly?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stepping back a bit: the original issue (#234) was about reducing latency, 
but this PR adds a new caching layer. I wonder if we could solve it at the 
DB query level instead? Simpler and fewer moving parts.

What do you think?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When the approach itself is wrong, not just the implementation. This is the hardest "no" because you're rejecting the author's design decision, not a line of code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key phrases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Stepping back a bit:" — signals you're zooming out&lt;/li&gt;
&lt;li&gt;"I wonder if..." — softest possible way to suggest an alternative direction&lt;/li&gt;
&lt;li&gt;"What do you think?" — makes it a conversation, not a veto&lt;/li&gt;
&lt;li&gt;"Happy to pair on this" — shows you're willing to invest time, not just criticize&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-native speaker trap:&lt;/strong&gt; "This approach is wrong" or "You should start over" will nuke the relationship. Even if the whole PR needs to be scrapped, frame it as a conversation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Relationship-ending&lt;/th&gt;
&lt;th&gt;✅ Redirecting with respect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;This approach is wrong&lt;/td&gt;
&lt;td&gt;Stepping back — I wonder if there's a simpler path here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start over&lt;/td&gt;
&lt;td&gt;Before we go further, can we sync on the approach? I have some ideas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;This is not what we need&lt;/td&gt;
&lt;td&gt;I think the original issue might be solvable without this layer — want to discuss?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Why did you build this?&lt;/td&gt;
&lt;td&gt;I might be missing context — is there a reason we're not using the existing X?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Cheat Sheet
&lt;/h2&gt;

&lt;p&gt;Print this. Pin it next to your monitor. Use it every code review.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Example opener&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(none)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;This is good&lt;/td&gt;
&lt;td&gt;"Nice — this handles..."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Nit:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Change if you want&lt;/td&gt;
&lt;td&gt;"Nit: maybe X instead of Y?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Suggestion:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Here's an alternative&lt;/td&gt;
&lt;td&gt;"Consider..." / "Another option:"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(question)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Help me understand&lt;/td&gt;
&lt;td&gt;"Curious:" / "Is there a reason...?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Concern:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This might cause problems&lt;/td&gt;
&lt;td&gt;"I'm a bit worried about..."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Blocking:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Must fix before merge&lt;/td&gt;
&lt;td&gt;"This needs to be addressed:"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(conversation)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Wrong direction&lt;/td&gt;
&lt;td&gt;"Stepping back:" / "Can we sync?"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Meta-Rules
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Match severity to language.&lt;/strong&gt; Don't use Level 5 language ("This needs to change") for a Level 1 issue (variable naming). Don't use Level 1 language ("Nit: maybe don't") for a Level 5 issue (SQL injection).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One "Blocking" per review is enough.&lt;/strong&gt; If you have 3 blockers, something went wrong upstream (unclear requirements, no design review). Have a conversation instead of leaving 3 red flags on a PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Always pair criticism with context.&lt;/strong&gt; "This is O(n²)" is a complaint. "This is O(n²) — with our current dataset of 50K rows, this loop takes ~3s. Using a Map brings it to ~5ms" is actionable feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Separate "what" from "how."&lt;/strong&gt; Flag the problem (Level 4-5), but let the author choose the solution unless there's only one right answer. "This could panic on nil" is better than "Add a nil check on line 47" — the author might have a better fix in mind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. If you're angry, save as draft.&lt;/strong&gt; Come back in 30 minutes. The PR will still be there. Your relationship with the author won't survive a review written in frustration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters Beyond Code
&lt;/h2&gt;

&lt;p&gt;Code review is one of the few places where developers give and receive direct feedback daily. How you do it shapes how people perceive you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too soft → your feedback gets ignored, bugs ship&lt;/li&gt;
&lt;li&gt;Too harsh → people stop requesting your review, you lose influence&lt;/li&gt;
&lt;li&gt;Just right → you become the reviewer everyone wants, and your team's code quality goes up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For non-native speakers, the stakes are higher. You're already navigating a language gap. Getting the tone wrong in code review can create a reputation problem that has nothing to do with your technical ability.&lt;/p&gt;

&lt;p&gt;The good news: unlike grammar, code review tone is a &lt;strong&gt;finite skill with learnable patterns.&lt;/strong&gt; The 7 levels above cover ~95% of situations. Practice them deliberately for two weeks and they'll become automatic.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of my "English for Developers" series. &lt;a href="https://dev.to/indiehacker_9527/how-to-write-a-pr-description-that-sounds-native-2n72"&gt;Part 1: How to Write a PR Description That Actually Sounds Native&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm building &lt;a href="https://devglish.com" rel="noopener noreferrer"&gt;DevGlish&lt;/a&gt; — a macOS menu bar app that gives you these kinds of context-aware English suggestions while you work. Select text → ⌘⇧D → instant guidance. It detects whether you're in GitHub, Slack, or email and adjusts the tone and phrasing accordingly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://devglish.com" rel="noopener noreferrer"&gt;Try it free →&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>codequality</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How to Write a PR Description That Sounds Native</title>
      <dc:creator>IndieHacker</dc:creator>
      <pubDate>Wed, 08 Apr 2026 05:21:18 +0000</pubDate>
      <link>https://dev.to/devglish/how-to-write-a-pr-description-that-sounds-native-2n72</link>
      <guid>https://dev.to/devglish/how-to-write-a-pr-description-that-sounds-native-2n72</guid>
      <description>&lt;h1&gt;
  
  
  How to Write a PR Description That Actually Sounds Native
&lt;/h1&gt;

&lt;p&gt;I've reviewed thousands of PRs from developers across 6 countries. The code is usually fine. The English? That's where things get interesting.&lt;/p&gt;

&lt;p&gt;Here's a collection of real patterns I've seen (anonymized), what native speakers actually think when they read them, and how to fix each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Please Kindly" Pattern
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What non-native speakers write:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please kindly review this PR. I have made some changes to the authentication module. 
Please let me know if you have any questions. Thank you for your time.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What native speakers think:&lt;/strong&gt; "This reads like a customer service email, not a PR description."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to write instead:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## What&lt;/span&gt;
Refactored the auth module to use JWT refresh tokens.

&lt;span class="gu"&gt;## Why&lt;/span&gt;
Session tokens were expiring mid-workflow (see #142). Refresh tokens let us extend sessions without re-auth.

&lt;span class="gu"&gt;## How&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Added &lt;span class="sb"&gt;`refreshToken()`&lt;/span&gt; to AuthService
&lt;span class="p"&gt;-&lt;/span&gt; Updated middleware to auto-refresh on 401
&lt;span class="p"&gt;-&lt;/span&gt; Migration: new &lt;span class="sb"&gt;`refresh_tokens`&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; PR descriptions are technical documents, not letters. Use What/Why/How structure. Skip greetings and pleasantries.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "I Think Maybe" Pattern
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What non-native speakers write:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I think maybe we should consider possibly using a different approach here, 
if that's okay with you.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What native speakers think:&lt;/strong&gt; "Are they unsure about the technical approach, or just being overly polite? I genuinely can't tell."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to write instead:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'd suggest using a connection pool here instead of creating new connections per request. 
The current approach will hit scalability issues around ~100 concurrent users.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; One hedge word is polite. Three hedge words is confusing. "I'd suggest" or "Consider" is enough — then state your case directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "You Should" Pattern
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What non-native speakers write:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You should change this variable name. You should also add error handling here. 
You should not use var.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What native speakers think:&lt;/strong&gt; "This feels like a lecture, not a code review."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to write instead:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Template&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nitpick&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Nit: [suggestion]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nit: &lt;code&gt;userCount&lt;/code&gt; reads better than &lt;code&gt;cnt&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suggestion&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Consider [doing X] — [reason]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Consider extracting this into a helper — it's used in 3 places&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocking&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[Issue]: [explanation]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This will panic on nil input — we need a guard here&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; Frame feedback as observations about the code, not instructions to the person. "This will panic" vs "You should add a nil check."&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Fixed Bug" Commit Message
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What non-native speakers write:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fixed bug
update code
modify function
add some changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What native speakers think:&lt;/strong&gt; "What bug? What code? I'm going to have to read the entire diff."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to write instead (Conventional Commits):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;fix(auth): prevent session expiry during active requests

The JWT middleware was checking token expiry before processing the request,
causing 401s for long-running uploads. Now checks after.

Closes #142
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The template:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;(&lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;): &lt;span class="nt"&gt;&amp;lt;what&lt;/span&gt; &lt;span class="na"&gt;changed&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;why&lt;/span&gt; &lt;span class="na"&gt;it&lt;/span&gt; &lt;span class="na"&gt;changed&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;context&lt;/span&gt; &lt;span class="na"&gt;that&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;diff&lt;/span&gt; &lt;span class="na"&gt;alone&lt;/span&gt; &lt;span class="na"&gt;doesn&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;t&lt;/span&gt; &lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;reference&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="na"&gt;issue&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;ticket&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Types: &lt;code&gt;feat&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;refactor&lt;/code&gt;, &lt;code&gt;docs&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;chore&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Please Help Me" Standup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What non-native speakers write:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Yesterday I was working on the task. Today I will continue working on it. 
I have no blockers.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What native speakers think:&lt;/strong&gt; "This tells me nothing."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to write instead:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gs"&gt;**Yesterday:**&lt;/span&gt; Got the JWT refresh flow working end-to-end. Tests passing locally.
&lt;span class="gs"&gt;**Today:**&lt;/span&gt; Integration testing against staging, then PR.
&lt;span class="gs"&gt;**Blocked:**&lt;/span&gt; Need access to the staging KV namespace — @ops can you add me?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; Be specific. Name the feature, the status, the next concrete action. "Working on the task" is a non-update.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Cheat Sheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instead of...&lt;/th&gt;
&lt;th&gt;Write...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Please kindly...&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(just skip it)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I think maybe we should consider...&lt;/td&gt;
&lt;td&gt;I'd suggest... / Consider...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You should...&lt;/td&gt;
&lt;td&gt;Nit: / Consider... / This will [problem]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fixed bug&lt;/td&gt;
&lt;td&gt;fix(scope): description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I was working on the task&lt;/td&gt;
&lt;td&gt;Got [specific thing] working, next up [specific thing]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Please let me know if you have any questions&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(just skip it — they'll ask if they have questions)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thank you for your time&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(unnecessary in PR context)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I want to ask...&lt;/td&gt;
&lt;td&gt;Quick question: ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can I know...?&lt;/td&gt;
&lt;td&gt;Do you know...? / Is there a way to...?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I have met a problem&lt;/td&gt;
&lt;td&gt;I ran into an issue with...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;These aren't grammar mistakes. They're &lt;strong&gt;register mistakes&lt;/strong&gt; — using email-formal language in a casual-technical context, or using a command tone when a suggestion tone is expected.&lt;/p&gt;

&lt;p&gt;Native speakers won't correct you. They'll just form a vague impression that your communication is "a bit off." Over time, that impression compounds.&lt;/p&gt;

&lt;p&gt;The good news: the patterns are finite and learnable. Once you internalize the ~20 templates above, you'll sound native in 90% of dev communication.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I built &lt;a href="https://devglish.com" rel="noopener noreferrer"&gt;DevGlish&lt;/a&gt; to solve this exact problem. It's a macOS menu bar app that gives you context-aware English suggestions while you work — select text, press ⌘⇧D, get instant guidance on pronunciation, phrasing, and native speaker conventions. It even detects which app you're in (Slack vs GitHub vs email) and adjusts the tone.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Free tier: 10 lookups/day. &lt;a href="https://devglish.com" rel="noopener noreferrer"&gt;Try it →&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>github</category>
      <category>softwareengineering</category>
      <category>writing</category>
    </item>
  </channel>
</rss>
