<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Static-Analysis on Özkan Pakdil Software Engineer</title>
    <link>https://ozkanpakdil.github.io/tags/static-analysis/</link>
    <description>Recent content in Static-Analysis on Özkan Pakdil Software Engineer</description>
    <image>
      <title>Özkan Pakdil Software Engineer</title>
      <url>https://ozkanpakdil.github.io/images/papermod-cover.png</url>
      <link>https://ozkanpakdil.github.io/images/papermod-cover.png</link>
    </image>
    <generator>Hugo -- 0.148.2</generator>
    <language>en</language>
    <copyright>Özkan Pakdil</copyright>
    <lastBuildDate>Wed, 22 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://ozkanpakdil.github.io/tags/static-analysis/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Beyond Functionality: Why Code Hygiene is Your Project&#39;s Immune System</title>
      <link>https://ozkanpakdil.github.io/posts/my_collections/2026/2026-04-22-code-hygiene/</link>
      <pubDate>Wed, 22 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://ozkanpakdil.github.io/posts/my_collections/2026/2026-04-22-code-hygiene/</guid>
      <description>&lt;p&gt;In the world of software engineering, we often obsess over the &amp;ldquo;Testing Pyramid.&amp;rdquo; We pour resources into unit tests, integration tests, and E2E suites. These are critical, they tell us that our features work as designed. But there’s a shadowy category of bugs that traditional tests often miss: the architectural &amp;ldquo;anti-patterns&amp;rdquo; and &amp;ldquo;API misuses&amp;rdquo; that don&amp;rsquo;t break functionality today but lead to system failures, memory leaks, or portability issues tomorrow.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In the world of software engineering, we often obsess over the &ldquo;Testing Pyramid.&rdquo; We pour resources into unit tests, integration tests, and E2E suites. These are critical, they tell us that our features work as designed. But there’s a shadowy category of bugs that traditional tests often miss: the architectural &ldquo;anti-patterns&rdquo; and &ldquo;API misuses&rdquo; that don&rsquo;t break functionality today but lead to system failures, memory leaks, or portability issues tomorrow.</p>
<p>This is where <strong>Code Hygiene</strong> comes in.</p>
<h2 id="what-is-code-hygiene">What is Code Hygiene?</h2>
<p>Code Hygiene is the practice of using automated tools to enforce non-functional constraints, coding standards, and safety patterns across a codebase. Unlike a unit test that checks if <code>Add(1, 1) == 2</code>, a hygiene scanner checks if you’re using an API in a way that’s technically &ldquo;valid&rdquo; but practically dangerous.</p>
<p>In Computer Science, this is formally known as <strong>Static Program Analysis</strong>. While general &ldquo;linting&rdquo; catches stylistic issues, Code Hygiene focuses on domain-specific safety and architectural integrity.</p>
<h2 id="the-evolution-from-api-safety-to-platform-portability">The Evolution: From API Safety to Platform Portability</h2>
<p>One of the most powerful applications of code hygiene I’ve ever implemented involved managing a high-stakes support matrix. We had a system that executed various Linux commands across a wide range of distributions: Ubuntu, SUSE, and RedHat, all in different versions.</p>
<h3 id="the-problem-the-command-parameter-minefield">The Problem: The Command Parameter Minefield</h3>
<p>As Linux distributions evolve, command-line parameters change. A flag that works on Ubuntu 20.04 might be deprecated on RedHat 9, or worse, behave subtly differently. Standard CI runs on a single OS wouldn&rsquo;t catch these issues until a customer on a specific RedHat version hit a runtime error.</p>
<h3 id="the-solution-static-analysis--testcontainers">The Solution: Static Analysis + Testcontainers</h3>
<p>To solve this, I developed a two-tier hygiene strategy:</p>
<ol>
<li><strong>The Scanner:</strong> We built a custom static analysis tool to crawl through the codebase and identify every single <code>exec</code> or shell-out call.</li>
<li><strong>The Matrix Validation:</strong> Using <strong>Testcontainers with C#</strong>, we spun up the exact versions of Ubuntu, SUSE, and RedHat defined in our support matrix. We then fed the commands discovered by our scanner into these containers to verify their exit codes and behavior.</li>
</ol>
<p>This &ldquo;Hygiene for Portability&rdquo; transformed our release process. We stopped guessing if our commands were compatible and started <em>knowing</em>.</p>
<h2 id="case-study-the-order-of-operations-leak">Case Study: The &ldquo;Order of Operations&rdquo; Leak</h2>
<p>Hygiene isn&rsquo;t just for external commands; it’s for internal APIs too. Recently, I dealt with a scenario where a database library had a specific requirement: <code>BeginTransaction()</code> had to be called <em>after</em> certain context configurations, but <em>before</em> others.</p>
<p>Syntactically, the code <code>db.WithContext(ctx).Begin()</code> looked fine. It compiled. It even passed unit tests. However, in tests, it caused intermittent memory leaks because the context wasn&rsquo;t being associated with the transaction object correctly.</p>
<p>A simple <strong>AST (Abstract Syntax Tree)</strong> scanner fixed this permanently. We wrote a rule that flags any instance where these calls are out of order. Institutional knowledge was turned into an automated gatekeeper.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Using Go&#39;s AST (Abstract Syntax Tree) to detect out-of-order method calls.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// This identifies &#39;db.WithContext(ctx).Begin()&#39; which should be &#39;db.Begin().WithContext(ctx)&#39;.</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">insp</span>.<span style="color:#a6e22e">Preorder</span>([]<span style="color:#a6e22e">ast</span>.<span style="color:#a6e22e">Node</span>{(<span style="color:#f92672">*</span><span style="color:#a6e22e">ast</span>.<span style="color:#a6e22e">CallExpr</span>)(<span style="color:#66d9ef">nil</span>)}, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">n</span> <span style="color:#a6e22e">ast</span>.<span style="color:#a6e22e">Node</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">call</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">n</span>.(<span style="color:#f92672">*</span><span style="color:#a6e22e">ast</span>.<span style="color:#a6e22e">CallExpr</span>)
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Check if the outer function call is &#34;Begin&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">outerSel</span>, <span style="color:#a6e22e">ok</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">call</span>.<span style="color:#a6e22e">Fun</span>.(<span style="color:#f92672">*</span><span style="color:#a6e22e">ast</span>.<span style="color:#a6e22e">SelectorExpr</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> !<span style="color:#a6e22e">ok</span> <span style="color:#f92672">||</span> <span style="color:#a6e22e">outerSel</span>.<span style="color:#a6e22e">Sel</span>.<span style="color:#a6e22e">Name</span> <span style="color:#f92672">!=</span> <span style="color:#e6db74">&#34;Begin&#34;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Ensure we are calling Begin on a *gorm.DB or result of WithContext on gorm.DB</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> !<span style="color:#a6e22e">isGormDB</span>(<span style="color:#a6e22e">pass</span>, <span style="color:#a6e22e">outerSel</span>.<span style="color:#a6e22e">X</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Check if &#34;Begin&#34; was called on the result of another function</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">innerCall</span>, <span style="color:#a6e22e">ok</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">outerSel</span>.<span style="color:#a6e22e">X</span>.(<span style="color:#f92672">*</span><span style="color:#a6e22e">ast</span>.<span style="color:#a6e22e">CallExpr</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> !<span style="color:#a6e22e">ok</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Check if that inner function call was &#34;WithContext&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">innerSel</span>, <span style="color:#a6e22e">ok</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">innerCall</span>.<span style="color:#a6e22e">Fun</span>.(<span style="color:#f92672">*</span><span style="color:#a6e22e">ast</span>.<span style="color:#a6e22e">SelectorExpr</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">ok</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">innerSel</span>.<span style="color:#a6e22e">Sel</span>.<span style="color:#a6e22e">Name</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;WithContext&#34;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">pass</span>.<span style="color:#a6e22e">Reportf</span>(<span style="color:#a6e22e">call</span>.<span style="color:#a6e22e">Pos</span>(), <span style="color:#e6db74">&#34;Hygiene Alert: Use &#39;db.Begin().WithContext(ctx)&#39; to prevent leaks.&#34;</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>})
</span></span></code></pre></div><h2 id="why-you-need-a-hygiene-strategy">Why You Need a Hygiene Strategy</h2>
<ol>
<li><strong>Preventing &ldquo;Silent&rdquo; Failures:</strong> Catch memory leaks, race conditions, and API misuses that don&rsquo;t trigger a test failure but kill performance.</li>
<li><strong>Institutional Memory:</strong> When a team learns a hard lesson, a hygiene rule ensures that new developers (or your future self) don&rsquo;t repeat the mistake.</li>
<li><strong>Scalable Reviews:</strong> Humans are bad at spotting subtle pattern errors in 1,000-line PRs. Computers are perfect at it.</li>
<li><strong>Platform Confidence:</strong> In a world of multi-arch and multi-OS support, scanners can validate that your code respects the constraints of every target environment.</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>Testing tells you the code is <strong>right</strong>. Hygiene tells you the code is <strong>healthy</strong>.</p>
<p>By integrating custom static analysis and matrix-based validation into your workflow, you move from a reactive &ldquo;hotfix&rdquo; stance to a proactive &ldquo;preventative&rdquo; culture. It’s time to look beyond functionality and start caring about the structural health of your codebase.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
