<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Go Code Quality &amp; Maintainability on Atharva Pandey</title><link>https://atharva.page/series/go-code-quality--maintainability/</link><description>Recent content in Go Code Quality &amp; Maintainability on Atharva Pandey</description><generator>Hugo</generator><language>en-us</language><copyright>Copyright ©</copyright><lastBuildDate>Sun, 01 Jun 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://atharva.page/series/go-code-quality--maintainability/index.xml" rel="self" type="application/rss+xml"/><item><title>Lesson 8: Linting with golangci-lint — Automate what reviewers shouldn''t waste time on</title><link>https://atharva.page/post/go/go-quality-linting/</link><pubDate>Sun, 01 Jun 2025 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-linting/</guid><description>&lt;p&gt;I made a rule for myself a few years ago: if I leave a code review comment about something a tool could have caught, I&amp;rsquo;ve wasted both the author&amp;rsquo;s time and mine. A linter can catch unused variables, missing error checks, shadowed variables, inefficient string concatenation, and dozens of other patterns automatically — in seconds, every commit, without reviewer fatigue. The code review should be about design and correctness, not about whether someone forgot to handle an error returned by &lt;code&gt;rows.Close()&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Lesson 7: Kill the Utils Package — util.go is where code goes to hide</title><link>https://atharva.page/post/go/go-quality-kill-utils/</link><pubDate>Tue, 01 Apr 2025 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-kill-utils/</guid><description>&lt;p&gt;Every Go codebase I&amp;rsquo;ve worked on for more than a year has a &lt;code&gt;util&lt;/code&gt; package. Some have a &lt;code&gt;helpers&lt;/code&gt; package. Some have both. I&amp;rsquo;ve seen &lt;code&gt;common&lt;/code&gt;, &lt;code&gt;shared&lt;/code&gt;, &lt;code&gt;misc&lt;/code&gt;, and once, memorably, &lt;code&gt;stuff&lt;/code&gt;. These packages are where code goes when a developer doesn&amp;rsquo;t know where it belongs — which means they&amp;rsquo;re the first place reviewers stop reading carefully, the last place new engineers look when they can&amp;rsquo;t find something, and the primary location of dead code in any codebase over 18 months old.&lt;/p&gt;</description></item><item><title>Lesson 6: Package Cohesion — Everything in a package should belong together</title><link>https://atharva.page/post/go/go-quality-package-cohesion/</link><pubDate>Thu, 06 Feb 2025 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-package-cohesion/</guid><description>&lt;p&gt;Go packages are the primary unit of code organization. They determine what&amp;rsquo;s visible to whom, what gets compiled together, and — most importantly — they communicate intent to every engineer who reads the codebase. A package with high cohesion says something true and useful: &amp;ldquo;everything here is about orders&amp;rdquo; or &amp;ldquo;everything here handles HTTP middleware.&amp;rdquo; A package with low cohesion says nothing — it&amp;rsquo;s a filing cabinet where things went when nobody knew where else to put them.&lt;/p&gt;</description></item><item><title>Lesson 5: Small Functions Win — If you can''t name it clearly, it does too much</title><link>https://atharva.page/post/go/go-quality-small-functions/</link><pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-small-functions/</guid><description>&lt;p&gt;There is a simple test I apply to any function I&amp;rsquo;m about to merge: can I name it clearly without using &amp;ldquo;and&amp;rdquo;? If the most honest name for a function is &lt;code&gt;validateAndSaveAndNotifyUser&lt;/code&gt;, the function is three functions pretending to be one. The naming test doesn&amp;rsquo;t lie — it&amp;rsquo;s a direct readout of the function&amp;rsquo;s responsibility. I&amp;rsquo;ve seen this test convince engineers who were unmoved by SOLID principles or Uncle Bob quotes, because it&amp;rsquo;s visceral: if you can&amp;rsquo;t say what the function does in a few words, you already know something is wrong.&lt;/p&gt;</description></item><item><title>Lesson 4: Code Review Heuristics — What to look for in a Go PR</title><link>https://atharva.page/post/go/go-quality-code-review/</link><pubDate>Sun, 20 Oct 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-code-review/</guid><description>&lt;p&gt;A good code review is not a diff-reading exercise. It&amp;rsquo;s a transfer of understanding — the reviewer asks &amp;ldquo;do I understand what this code does, why it does it, and what it doesn&amp;rsquo;t do?&amp;rdquo; If the answer to any of those is no, that&amp;rsquo;s a comment, not a nitpick. I&amp;rsquo;ve done hundreds of Go reviews and the feedback I give clusters into the same ten or fifteen patterns so reliably that I eventually wrote them down as a checklist. This lesson is that checklist, with examples.&lt;/p&gt;</description></item><item><title>Lesson 3: Idiomatic Naming — Names are your documentation</title><link>https://atharva.page/post/go/go-quality-naming/</link><pubDate>Wed, 04 Sep 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-naming/</guid><description>&lt;p&gt;When I review Go code, naming problems tell me more about the author&amp;rsquo;s understanding of the codebase than almost anything else. A function called &lt;code&gt;HandleRequest&lt;/code&gt; that parses JSON, queries a database, formats a response, and writes to a log tells me its author didn&amp;rsquo;t know what it does either. A variable called &lt;code&gt;data&lt;/code&gt; in a function that handles three different kinds of data tells me the author stopped thinking halfway through. Names are the first layer of documentation — they&amp;rsquo;re read far more often than comments, and unlike comments, they can&amp;rsquo;t drift out of sync with the code.&lt;/p&gt;</description></item><item><title>Lesson 2: Spotting Over-Abstraction — When your abstraction is the problem</title><link>https://atharva.page/post/go/go-quality-over-abstraction/</link><pubDate>Wed, 24 Jul 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-over-abstraction/</guid><description>&lt;p&gt;There&amp;rsquo;s a version of Go code I see in almost every codebase that&amp;rsquo;s been touched by developers who came from Java or C# — it&amp;rsquo;s covered in interfaces, repositories, factories, and service layers that all wrap exactly one concrete implementation. No tests mock these interfaces. No second implementation exists. The abstraction is doing nothing except adding indirection. I&amp;rsquo;ve written code like this myself, and the tell is always the same: when something breaks, I have to jump through five files to understand what happens when I call &lt;code&gt;CreateUser&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Lesson 1: Refactoring Go Code Safely — Change structure without changing behavior</title><link>https://atharva.page/post/go/go-quality-refactoring/</link><pubDate>Sun, 16 Jun 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/go/go-quality-refactoring/</guid><description>&lt;p&gt;Refactoring is the one activity that makes codebases better without adding features — and it&amp;rsquo;s also the activity most likely to introduce bugs if done carelessly. I learned this the hard way on a payments service where I renamed a function, ran the tests, saw green, deployed, and watched a webhook handler silently stop processing because it had been calling the old function name through a string-based registry I hadn&amp;rsquo;t touched. The tests were green because the old function still existed — I just hadn&amp;rsquo;t deleted it yet. The refactor was correct; the process was not.&lt;/p&gt;</description></item></channel></rss>