<?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: Fedor </title>
    <description>The latest articles on DEV Community by Fedor  (@oyminirole).</description>
    <link>https://dev.to/oyminirole</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%2F3773501%2F316c4676-1504-44ab-8157-899008039388.jpg</url>
      <title>DEV Community: Fedor </title>
      <link>https://dev.to/oyminirole</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oyminirole"/>
    <language>en</language>
    <item>
      <title>AI Will Replace Programmers. Are You Sure About That?</title>
      <dc:creator>Fedor </dc:creator>
      <pubDate>Sat, 04 Apr 2026 12:20:50 +0000</pubDate>
      <link>https://dev.to/oyminirole/ai-will-replace-programmers-are-you-sure-about-that-3159</link>
      <guid>https://dev.to/oyminirole/ai-will-replace-programmers-are-you-sure-about-that-3159</guid>
      <description>&lt;p&gt;In case you missed it, back in January 2026, at the World Economic Forum in Davos, Anthropic CEO Dario Amodei stated: &lt;/p&gt;

&lt;p&gt;"&lt;em&gt;I think we might be 6 to 12 months away from when the model is doing most, maybe all of what SWEs do end-to-end.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;He then added: "&lt;em&gt;I have engineers within Anthropic who say I don't write any code anymore. I just let the model write the code, I edit it...&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;It’s April now, and spoiler alert: we are still here, and we are still coding. Especially if you're a Senior Developer with 12 years at Google. But there's a catch: this is marketing on the level of "AI will replace everyone in 12 months" - a phrase we've been hearing for four years in a row now. Just a reminder that Anthropic's CEO said literally the exact same thing back in October 2025. So let's break down in maximum detail (maybe even too much detail) why neural networks, even the most advanced ones, are physically and mathematically incapable of replacing a programmer. And why &lt;a href="https://en.wikipedia.org/wiki/Moore%27s_law" rel="noopener noreferrer"&gt;Moore's Law&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Quantum_tunnelling" rel="noopener noreferrer"&gt;quantum tunneling&lt;/a&gt;, and the very nature of probabilistic machines put a massive nail in that coffin.&lt;/p&gt;

&lt;p&gt;If you’re interested in the process and want to keep up with my future rants, I’d appreciate a follow on &lt;a href="https://x.com/OymInIRole" rel="noopener noreferrer"&gt;X (Twitter)&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. A Neural Network is Not a Brain, It's a Massive Probabilistic Machine
&lt;/h3&gt;

&lt;p&gt;Modern Large Language Models (LLMs) are neural networks that fundamentally do one thing: predict the next piece of text based on everything they've seen before. They don't understand code in the true sense. They have no internal world model; they don't know what a race condition in concurrent code actually is, or how to ensure data reliability in a distributed system. They simply output the most probable sequence of characters based on statistics gathered from terabytes of code, forums, and repositories.&lt;/p&gt;

&lt;p&gt;It's simple: if the model has seen that the token "cat" is followed by "fluffy" in 95% of cases, it picks that word next. &lt;/p&gt;

&lt;p&gt;Hence the famous hallucinations: when the model takes a low-probability detour into a parallel universe where running &lt;code&gt;DROP TABLE users CASCADE;&lt;/code&gt; seems like a perfectly reasonable solution. Chain-of-thought reasoning, web search, autonomous agents - these are all useful add-ons that drastically increase the chances of getting the right answer, but they don't change the core mechanism. It's still good old autocomplete on steroids. By the way, giving a neural network web access massively improves answer quality and user experience. It's just a pity that the services providing these search APIs are mostly garbage - offering overpriced and incomplete data. But I digress.   &lt;/p&gt;

&lt;p&gt;In real-world development, 80% of code is boilerplate, basic data operations, and gluing different parts together. Here, the model genuinely speeds up the workflow exponentially (in today's world, not using AI is just plain stupid because of the speed and boilerplate reduction). But that remaining 20% is system architecture, trade-offs between performance and reliability, deep business domain knowledge, edge cases, operational resilience, legal compliance, and questions like, "What if the business decides tomorrow that we need semantic compression for cucumber logs?" This is where the probabilistic machine fails. Because the so-called "correct" answer simply doesn't exist in the training data - it requires a creative solution under conditions of incomplete information.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Moore's Law is Dead, and Quantum Tunneling Won
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepjjgb5m1thzwg7dv2hz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepjjgb5m1thzwg7dv2hz.webp" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now for the fun part: physics.&lt;/p&gt;

&lt;p&gt;Since 1965, we've lived by Moore's Law: the number of transistors on a microchip doubles every two years. This provided the exponential growth in computing power that fueled all the recent AI breakthroughs. More parameters = more "intelligence." Simple.&lt;/p&gt;

&lt;p&gt;But in 2025-2026, we hit a brick wall.&lt;/p&gt;

&lt;p&gt;The current manufacturing process is 2 nanometers. The thickness of the insulating layer is already down to 0.7-1.2 nanometers - that's literally two or three silicon atoms. At this scale, quantum tunneling kicks in: electrons start behaving like waves and, with a non-zero probability, simply "leak" through a barrier they shouldn't be able to cross according to classical physics. As a result, computing efficiency drops due to leakage current, while heat generation and power consumption skyrocket. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbaqp1gh69ul4qfq14o1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbaqp1gh69ul4qfq14o1.jpg" alt="Quantum Tunneling" width="620" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voltage scaling alongside size reduction died a long time ago, too. Now we've moved on to modular chiplets, 3D stacking, and software optimization. This gives us linear growth at best, not exponential.&lt;/p&gt;

&lt;p&gt;The problem is, training the most powerful models requires exactly that explosive, exponential growth in compute. To achieve the next major leap, you need 10 to 100 times more parameters and operations. But data centers are already consuming as much energy as small countries. The cost of training a single model is in the hundreds of millions of dollars. We've practically run out of high-quality human data on the open web, and training on "AI slop" doesn't help much - models start feeding on their own outputs and severely degrade in quality. We won't dive into the theories of what happens when neural networks train on their own inherently flawed generated content, but you can guess the outcome. &lt;/p&gt;

&lt;p&gt;So, humanity has hit a physics bottleneck, as usual. To build something truly groundbreaking, we either need to invent a vastly superior neural network architecture, or we need breakthroughs like stable quantum computers - which aren't exactly on the horizon for the next few years. And to create a better architecture - a true Artificial General Intelligence (AGI) that can do everything a human does, including creativity and problem-solving in entirely novel situations - we first need to understand how the human brain works, or at least grasp its fundamental principles to replicate and improve upon them. But as of today, we don't even understand how consciousness and intellect emerge from millions of neurons and synapses. Until we figure that out, neural networks will remain nothing more than very smart probability predictors.&lt;/p&gt;

&lt;p&gt;And if we ever do build a system that approaches the complexity of the brain, an ethical question immediately arises: is it self-aware? Does it have rights? But that's a completely different story - and we are a long way from it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. What This Means for AI, Programmers, and the Future
&lt;/h3&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68dayhvfgwks29ge4odf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68dayhvfgwks29ge4odf.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neural networks won't get "smarter" in the sense of replacing a human engineer, but they have already become an incredibly useful tool - just like Git, Docker, or Kubernetes did in their time. A Senior Developer's productivity has multiplied, and Juniors are growing into Mids and Seniors much faster. But AI won't kill the profession itself.&lt;/p&gt;

&lt;p&gt;Even if it did, a whole new set of questions immediately pops up: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Someone has to define the problem at the level of business logic and real-world physical constraints;&lt;/li&gt;
&lt;li&gt;Someone has to verify that the code doesn't just look right, but actually works in production under heavy load, handles failures, and is secure;&lt;/li&gt;
&lt;li&gt;Someone has to make architectural decisions where the cost of a mistake is billions of dollars or human lives;&lt;/li&gt;
&lt;li&gt;And finally, someone has to maintain the system for decades (oh yeah, everyone loves those legacy Java monsters with server-side rendered frontends and 6,000 lines of code stuffed into a single file).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Enough with the Marketing BS
&lt;/h3&gt;

&lt;p&gt;While AI company CEOs drop quotes like "there will be no more programmers" to pump their stock prices and secure investments, actual engineering teams at NVIDIA, Google, and even Anthropic itself are still actively hiring developers. Why? Because you can't build reliable, scalable, and secure systems purely on probabilities.&lt;/p&gt;

&lt;p&gt;AI won't replace programmers, but it is already turning good programmers into great ones. And bad programmers into unemployed ones. The only difference is who understands how this probabilistic machine works under the hood, and who knows how to ask it the right questions.&lt;/p&gt;

&lt;p&gt;Physics never lies, but marketing and people lie all the time.&lt;/p&gt;

&lt;p&gt;And that is probably the most reliable statement in the tech industry for 2026. So learn to code, and stop whining about being replaced by AI. &lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Are you sure you know how to handle errors in Go properly?</title>
      <dc:creator>Fedor </dc:creator>
      <pubDate>Wed, 25 Mar 2026 14:22:26 +0000</pubDate>
      <link>https://dev.to/oyminirole/are-you-sure-you-know-how-to-handle-errors-in-go-properly-29g7</link>
      <guid>https://dev.to/oyminirole/are-you-sure-you-know-how-to-handle-errors-in-go-properly-29g7</guid>
      <description>&lt;p&gt;If you've been writing in Go for more than a couple of months, the &lt;code&gt;if err != nil&lt;/code&gt; construct is already muscle memory. The language's philosophy dictates a simple rule: we don't ignore errors, we don't hide them, and we don't rely on global exception catchers - we handle them explicitly.&lt;/p&gt;

&lt;p&gt;But it's one thing to write a three-hundred-line script, and quite another to design a system that needs to be maintained for years. In large projects, improper error handling makes logs unreadable, and finding the root cause of a bug takes hours. In this article, we'll discuss how to build effective error tracing in a clean architecture, avoid code duplication, and properly pass the problem's context through all application layers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Panic? What panic?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49w11c0k4yd1t8x7ctvl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49w11c0k4yd1t8x7ctvl.jpg" alt=" " width="800" height="1037"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It would seem that the "always return the error up the stack" rule is the absolute baseline. That's what basic Go guides tell you. Actually, it's kind of true, but not entirely. It's like saying a brick doesn't taste good - technically true, but it doesn't quite capture the whole picture. So what about &lt;code&gt;panic()&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;There is one pattern for situations where an error is fatal and the application physically cannot continue working - functions with the &lt;code&gt;Must&lt;/code&gt; prefix. For example, when loading the configuration during application startup. If there is no config, the database has nothing to connect to, and there is no reason for the server to start. Returning an error here is pointless - you need to crash.&lt;/p&gt;

&lt;p&gt;Here is what it looks like in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// package config&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// get the env path from flags&lt;/span&gt;
    &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// some default fields...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;godotenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;envPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"load .env: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"parse env: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;MustLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to load config:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look closely at the code, you'll notice a small detail: in Load(), we use %w, but we also have the good old %v in Go. Why the distinction?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;%w&lt;/code&gt; (wrap) verb preserves the original error inside the new one, allowing it to be programmatically extracted and inspected later via errors.Is(). On the other hand, &lt;code&gt;%v&lt;/code&gt; (value) simply formats the error into a string, permanently cutting off any possibility of programmatic checks.&lt;/p&gt;

&lt;p&gt;This raises an obvious question: why do we even need &lt;code&gt;%w&lt;/code&gt; in the &lt;code&gt;Load()&lt;/code&gt; function if it’s called exactly once by &lt;code&gt;MustLoad()&lt;/code&gt;, which is just going to panic anyway? No one is going to inspect that error in a dying process.&lt;/p&gt;

&lt;p&gt;The answer: we don't. In this specific case, it makes zero functional difference whether you wrap it or not - the application is about to hit a brick wall. But through the lens of architectural canons, &lt;code&gt;Load()&lt;/code&gt; is an independent entity. It doesn't know who will call it tomorrow. Perhaps you'll write a CLI utility that tries to load the config and, if it fails, falls back to a default one. Therefore, the function is obliged to honor its contract: wrap the error and pass it up.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MustLoad()&lt;/code&gt;, knowing that a panic is imminent, simply crashes with a formatted message. We don't need fmt.Errorf inside a &lt;code&gt;panic()&lt;/code&gt; here; fmt is for wrapping or formatting errors, and at the end of the line, a simple string is enough. It’s a pattern strictly for the application’s entry point, like main(), where a failure to initialize makes further execution impossible. In reality, most developers just develop a habit of slapping &lt;code&gt;%w&lt;/code&gt; everywhere on autopilot, and there’s nothing wrong with that. In a config loader, do whatever you like - it doesn't really matter.&lt;/p&gt;

&lt;p&gt;Okay, we have sorted out the wrapping and must-prefix. But how do we make these wrapped errors show the exact place where our program crashed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why const op is the absolute baseline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Discussions often pop up in Go about how to get an error's stack trace. Many drag heavy third-party libraries into their projects, which use &lt;code&gt;runtime.Caller&lt;/code&gt; under the hood. Let me be blunt: it's slow, redundant, and you simply don't need it.&lt;/p&gt;

&lt;p&gt;The Go developers demonstrated a simpler and more elegant approach in the Upspin project: the &lt;code&gt;op&lt;/code&gt; pattern. Each function defines an &lt;code&gt;op&lt;/code&gt; (operation) constant with its name and, upon returning, wraps the error by appending this name. We get explicit tracing with zero performance loss.&lt;/p&gt;

&lt;p&gt;Personally, I use the naming formula &lt;code&gt;folder.subfolder.FunctionName&lt;/code&gt;. It's just a battle-tested approach that makes logs transparent and allows you to quickly pinpoint the point of failure.&lt;/p&gt;

&lt;p&gt;But here lies a nuance that is often forgotten. Having gotten their hands on this pattern, developers start wrapping errors in literally every tiny function without fully studying the pattern. Yes, this is often just a banal misunderstanding. As a result, the log turns into an endlessly long and duplicated list that looks more like the Dublin Spire than an actual log. To avoid this, I highly recommend a rule: wrap errors only at layer boundaries or in the main method that calls smaller sub-functions (which, in turn, simply pass these errors up without wrapping).&lt;/p&gt;

&lt;p&gt;And since we're talking about layer boundaries, it's high time we apply our theory to a real architecture and clear up the terminology a bit.&lt;/p&gt;

&lt;p&gt;If you look at modern Go projects, you'll notice that the main entities live in the &lt;code&gt;domain&lt;/code&gt; package, not &lt;code&gt;model&lt;/code&gt;. Why is that? The term &lt;code&gt;model&lt;/code&gt; was dragged in from the ancient Model-View-Controller architecture. But the name &lt;code&gt;Domain&lt;/code&gt; reflects the essence much more accurately, because a domain is your business area. This is a direct borrowing from DDD, which really helps make the code readable. However, full-blown DDD in Go is often overkill, spawning debates about where to put interfaces and whether to use anemic or rich models (although with rich ones, the code is cleaner).&lt;/p&gt;

&lt;p&gt;But let's get back to our errors. You might ask me again: author, why do we even need this &lt;code&gt;Domain&lt;/code&gt; in the context of error handling? Because &lt;strong&gt;that is exactly where our custom business errors live&lt;/strong&gt;. Things like &lt;code&gt;domain.ErrNotFound&lt;/code&gt;, &lt;code&gt;domain.ErrEmpty&lt;/code&gt;, or &lt;code&gt;domain.ErrInvalidFormat&lt;/code&gt; are declared right there in the domain. This allows all application layers to know about them, check them via &lt;code&gt;errors.Is&lt;/code&gt;, and avoid creating cross-layer dependencies.&lt;/p&gt;

&lt;p&gt;Let's see what this looks like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1: Adapter (Working with the outside world)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I intentionally avoid the term "repository". In modern realities, Postgres is just as much an external resource as Redis or a neighboring microservice's API. By calling this layer an Adapter, we unify the architectural approach, and the poor soul who has to read this crappy code won't have to spend ages figuring out "what's inside the repository". Whether it's a MongoDB unexpectedly used for caching for some reason, or Redis suddenly deciding to become the primary database for God knows what reason - it doesn't matter. They are all adapters, and all layers depend on interfaces, not on each other, to ensure modularity and testability.&lt;/p&gt;

&lt;p&gt;Here is what a clean and proper method for fetching data from Postgres looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;StyleProfileDB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetInstructionByID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Instruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// op formula: folder (postgres) + subfolder (styleprofile) + method. &lt;/span&gt;
    &lt;span class="c"&gt;// No need to write the word "adapter", "postgres" already provides full context.&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"postgres.styleprofile.GetInstructionByID"&lt;/span&gt;

    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"SELECT name, content, created_at FROM instructions WHERE id = $1"&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ins&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Instruction&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Check for a specific database error&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNoRows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// Translate the infrastructure error into a domain error&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// Wrap any other error&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use &lt;code&gt;errors.Is(err, sql.ErrNoRows)&lt;/code&gt;. The nuance is that &lt;code&gt;errors.Is&lt;/code&gt; checks if the error matches a specific value. And pay attention to a crucial detail: we translate the infrastructure error (&lt;code&gt;sql.ErrNoRows&lt;/code&gt;) into a domain error (&lt;code&gt;domain.ErrNotFound&lt;/code&gt;). The business logic above shouldn't know that we are using SQL specifically, because it simply doesn't need that data and it's not meant for it; it operates on interfaces.&lt;/p&gt;

&lt;p&gt;And one more thing: there is no logging in this code. Why? Because the adapter is a dumb component with zero knowledge of the business context. The fact that a record wasn't found might be an expected system scenario. Or it might not be - that's for the business to decide. In this case, logging at the database level will only lead to cluttering your monitoring.&lt;/p&gt;

&lt;p&gt;So where do we handle and log it? The error, neatly wrapped in the Adapter, moves one level up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2: Usecase (Business Logic)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our error lands in the Usecase layer. This is the application level of our system that manages the business logic. Requests arrive here, system decisions are made here, and this is exactly where logging happens.&lt;/p&gt;

&lt;p&gt;Data is passed between layers via DTOs (Data Transfer Objects). And here the question arises again: "Why should I breed new structs if I can just pass the domain model?".&lt;/p&gt;

&lt;p&gt;The answer is simple: a DTO makes your Usecase completely independent of the transport (be it HTTP, gRPC, or CLI). If your application is even slightly more complex than a basic CRUD, you will inevitably find that passing a hypothetical struct from the Domain directly to the handler is a one-way ticket to hell. A DTO is your strict contract. Period. The Usecase doesn't need anything else from you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Usecase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetInstructionByID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByIDInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByIDOutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"usecase.styleprofile.GetInstructionByID"&lt;/span&gt;

    &lt;span class="c"&gt;// DTO validation happens exactly in the Usecase&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// The validation error also lives in the domain. We just return it.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByIDOutput&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;ctxWithTimeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContextTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Go to the adapter for data via an interface&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxWithTimeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Log taking the business context into account&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByIDOutput&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByIDOutput&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Return the response DTO&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByIDOutput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Instruction&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a couple of important nuances here. Why do we validate the DTO specifically in the Usecase and not in the HTTP handler? And why do we return the DTO by value, not by reference? Answering the first question... just imagine that tomorrow the business asks to add a gRPC endpoint for this exact method. If the validation stays in the HTTP handler, you'll have to duplicate it in the new transport. The Usecase must protect itself. And note: the validation error (&lt;code&gt;domain.ErrEmpty&lt;/code&gt;) also lives in the domain, we just return it, &lt;strong&gt;without logging&lt;/strong&gt;. As for not accepting or returning by reference, it's simply because, by their nature, DTOs should not mutate. If someone changes something somewhere else, it shouldn't reflect on our business logic.&lt;/p&gt;

&lt;p&gt;Here we smoothly transition to logging rules. What should you even write to a log? You should log business decisions and actual failures. If a user sent an empty ID - that's the user's problem, the system worked as expected, there's nothing to log here. If the adapter didn't find a record - that's a routine situation, we write a Warn. If the database dropped dead - that's an Error.&lt;/p&gt;

&lt;p&gt;And for the love of God, stop dragging monstrous &lt;code&gt;logrus&lt;/code&gt; setups into your projects. The times when they were vitally necessary are long gone. The standard &lt;code&gt;log/slog&lt;/code&gt; out of the box does absolutely everything a modern application needs. Paired with our &lt;code&gt;op&lt;/code&gt; pattern, it produces perfect structured logs without unnecessary allocations and a zoo of dependencies. Forget about that legacy stuff and write clean code.&lt;/p&gt;

&lt;p&gt;The business logic has done its job, the logs are written, now we need to somehow return the result (or error) to the client. We are moving to the final frontier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3: Handler (Transport)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The result of the Usecase's work is passed to the Handler. This is the simplest layer of the application. Its job is to parse the HTTP request, form a DTO, call the Usecase, and properly format the HTTP response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;getInstructionByID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Extract ID from URL and check the format&lt;/span&gt;
    &lt;span class="n"&gt;idFromUrl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;chi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URLParam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idFromUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Invalid ID format"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Form a DTO to pass to the business logic&lt;/span&gt;
    &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByIDInput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Call the Usecase, again via an interface&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usecase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInstructionByID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Map domain errors to HTTP statuses&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Instruction not found"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Bad request data"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// If the error is unknown - return a standard 500 status&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Internal server error"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Return the successful result&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main nuance of this layer: the Handler does not log errors. At all. This task has already been completed in the Usecase, and if we add a log here too, we'll get duplication in our monitoring. It is isolated from the database and infrastructure. The only thing it does with an error is check its type via &lt;code&gt;errors.Is&lt;/code&gt; (consulting our dictionary from the &lt;code&gt;Domain&lt;/code&gt;) and return the corresponding HTTP status to the client. If the error is unknown, the client gets a 500 Internal Server Error status, which hides the internal workings of the system, without leaking table names or internal IP addresses to the outside world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrapping up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Proper error handling in Go is not just mindlessly copying &lt;code&gt;if err != nil&lt;/code&gt;. &lt;code&gt;Must&lt;/code&gt; functions are used exclusively for fatal crashes at startup. The &lt;code&gt;op&lt;/code&gt; pattern allows you to create a clear call stack without wasting resources or using reflection magic. Errors live in the domain, are wrapped via &lt;code&gt;%w&lt;/code&gt; strictly at layer boundaries, and are logged only where there is a business context, using the lightweight &lt;code&gt;slog&lt;/code&gt;. By sticking to this approach, you get code that is easy to read, a pleasure to debug, and cheap to maintain. (And one more thing: never collaborate with dictatorships. The restrictions and systems you build are exactly what allow them to feel comfortable and wage wars.)&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>go</category>
      <category>architecture</category>
      <category>backend</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Your "Clean Code" is Actually Unmaintainable Rubbish</title>
      <dc:creator>Fedor </dc:creator>
      <pubDate>Sun, 22 Feb 2026 19:23:45 +0000</pubDate>
      <link>https://dev.to/oyminirole/why-your-clean-code-is-actually-unmaintainable-rubbish-eoc</link>
      <guid>https://dev.to/oyminirole/why-your-clean-code-is-actually-unmaintainable-rubbish-eoc</guid>
      <description>&lt;p&gt;The ratio of time spent reading code versus writing it can reach &lt;a href="https://bayrhammer-klaus.medium.com/you-spend-much-more-time-reading-code-than-writing-code-bc953376fe19" rel="noopener noreferrer"&gt;7:1&lt;/a&gt; or even higher. Whether you’re fixing a bug, adding a feature, or refactoring, you inevitably submerge yourself in logic written by others (or by you, several months ago). This is why readability is far more critical than how fast you typed it out in the first place.&lt;/p&gt;

&lt;p&gt;Unreadable code is technical debt that bottlenecks the entire team and inflates development costs in the long run. Period.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Principles of Readable Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff980he97dfmicetw7yc5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff980he97dfmicetw7yc5.webp" alt="Uncle Bob" width="725" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think it's time to realize that "clean code" isn't a silver bullet or a set of holy, unbreakable laws. Ideal code doesn't exist and cannot exist. It’s more of a philosophy-a set of recommendations to help make code understandable. Ironically, these "unbreakable laws" often lead to people failing to agree on anything, sparking endless debates and conflicting interpretations.&lt;/p&gt;

&lt;p&gt;I don't want this to be another "proper code" summary. If you want to write purely academic code (which is impossible anyway), go ahead and read Robert Martin’s Clean Code. This article promotes rational cleanliness. Apply it where it’s actually needed-meaning, in projects that actually need to be maintained.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The best code is stupidly readable code."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Code that doesn't force your brain to grind gears just to understand the intent. Let’s just walk through the foundation, because without this, "maintainability" isn't even part of the conversation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear variable and function names.&lt;/strong&gt; This has been said 1000 times, and I’ll say it for the 1001st. It is the absolute base. A name must reveal intent. If you see a variable named &lt;code&gt;d&lt;/code&gt; or &lt;code&gt;list1&lt;/code&gt;, you’ll have to go hunting through God-knows-where or dive deep into the implementation just to figure out what it is. If it’s called &lt;code&gt;elapsedTimeInDays&lt;/code&gt; or &lt;code&gt;activeUsers&lt;/code&gt;, the questions disappear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility Principle (SRP).&lt;/strong&gt; A function should do one thing and do it well. When you see a &lt;code&gt;handleUserData&lt;/code&gt; function that fetches form data, validates it, saves it to the database, and sends an email-that’s a red flag. I &lt;em&gt;could&lt;/em&gt; tell you to split it into &lt;code&gt;validateForm&lt;/code&gt;, &lt;code&gt;saveUserToDatabase&lt;/code&gt;, and &lt;code&gt;sendWelcomeEmail&lt;/code&gt;, but the fact that you had one function doing all that in the first place is the real alarm bell. If you’re stuck with a massive monolith, this is at least a baseline for readability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Coding Style.&lt;/strong&gt; It doesn't really matter if you use tabs or spaces (though tabs take up less memory, but who cares?), or where you put the curly brace. What matters is that the whole team does it the same way. At the very least, try not to write in different paradigms yourself while in a "drunken stupor" working on a microservice meant to handle 1000000 RPS. Inconsistent style creates visual noise. Luckily, linters and formatters solved this ages ago. Set them up once and let the robots handle the style.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What? Code Review?
&lt;/h2&gt;

&lt;p&gt;Code review isn't about finger-pointing; it’s one of the most effective tools for collective growth. To keep the review systematic, keep a checklist in mind:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logic:&lt;/strong&gt; Does it solve the task? Are edge cases handled?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Readability:&lt;/strong&gt; Are the names clear? Is the structure too complex?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture:&lt;/strong&gt; Does it follow the project patterns? Is it extendable?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tests:&lt;/strong&gt; Are there tests? Do they cover the "happy path" and the alternatives?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let the robots work.&lt;/strong&gt; Humans are inconsistent. Routine checks for duplication, potential bugs, and vulnerabilities should be delegated to automation. Tools like SonarQube built into your CI/CD pipeline will catch typical issues before a human even sees them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Focus on teaching, not critiquing.&lt;/strong&gt; Instead of a directive "Fix this," use dialogue: "What if we tried this approach? I think it might simplify maintenance later." We need to be kinder to our colleagues-and everyone else. The world lacks kindness.&lt;/p&gt;




&lt;h2&gt;
  
  
  Patterns and Anti-patterns: Explained with Cats
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu10az7oyo00cj6was1my.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu10az7oyo00cj6was1my.jpg" alt="bombastic cat" width="467" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In programming, as in living with cats, there are elegant solutions and there are weird, tangled messes. Some will say, "Meh, this is just a Clean Code summary!" Well, no. I’m calling you to do what’s necessary here and now. If you apply the things below, your future self will thank you.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Deep Nesting (Arrow Code)
&lt;/h3&gt;

&lt;p&gt;Imagine your cat wants to relax and get to some catnip. But the path is treacherous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Anti-pattern:&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;if (catWantsToPlay) {
  if (isLivingRoom) {
    if (blanketOnCouch) {
      if (boxUnderBlanket) {
        if (catnipInBox) {
          // Success, the cat is high!
        }
      }
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a pyramid of indents. You have to hold the entire chain in your head.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Early Return" Pattern (Guard Clauses):&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;if (!catWantsToPlay) return; 
if (!isLivingRoom) return;   
if (!blanketOnCouch) return; 
if (!boxUnderBlanket) return; 
if (!catnipInBox) return;     

// Success, the cat is high!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code becomes flat and clear-like a cat's direct path to the goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Mystery Cat Behavior
&lt;/h3&gt;

&lt;p&gt;What if your cat’s behavior is described by numbers?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Anti-pattern:&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;if (catState === 1) {
  // Pet
} else if (catState === 2) {
  // Feed
} else if (catState === 3) {
  // Don't touch, the cat is dead
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What do 1, 2, and 3 mean? These are Magic Numbers. Today you remember, but in a month you'll be digging through documentation (if it even exists...) to decode this message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Named Constants" Pattern:&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;const STATE_PURRING = 1;
const STATE_HUNGRY = 2;
const STATE_DEAD = 3;

if (catState === STATE_PURRING) {
  // Pet
} else if (catState === STATE_HUNGRY) {
  // Feed
} else if (catState === STATE_DEAD) {
  // Don't touch
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Feeding Two Identical Cats
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Anti-pattern (Copy-Paste):&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;// Feed Barsik
putInBowl("Barsik", "kibble");
pourInBowl("Barsik", "water");
callCat("Barsik");

// Feed Murzik
putInBowl("Murzik", "kibble");
pourInBowl("Murzik", "water");
callCat("Murzik");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you add vitamins, you have to change it in two places. If you have ten cats, you will forget one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Better Way (DRY):&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;function feedCat(catName) {
  putInBowl(catName, "kibble");
  pourInBowl(catName, "water");
  callCat(catName);
}

feedCat("Barsik");
feedCat("Murzik");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But please, DO NOT DO THIS WITH DIFFERENT USE CASES! That’s an anti-pattern called "Service Hell." Every use case should be isolated. Otherwise, an error in one place will cause a mysterious crash in another. &lt;/p&gt;




&lt;h2&gt;
  
  
  Readable Code and Documentation
&lt;/h2&gt;

&lt;p&gt;Good code is self documenting. But comments are still needed to explain why. If you used a weird workaround for a bug in an external library, leave a link. Otherwise, you’ll get a surprise "prod is down" call on a Friday night. But think before you write: code gets updated, but people are often afraid to touch old comments. Don't overdo it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Micro-refactorings.&lt;/strong&gt; See a bad name? Change it. A function that does everything? Break it up but into logical blocks, not 3,000 tiny pieces. Leave the code cleaner than you found it. It’s like picking up someone else's trash while staying in your seat.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pair Programming.&lt;/strong&gt; Real-time review. A great way to share knowledge or debate the speed of QuickSort vs MergeSort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Internal Guides.&lt;/strong&gt; Agree on rules and stick to them. Actually look at them once in a while, or they're useless.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pragmatism Above All
&lt;/h2&gt;

&lt;p&gt;Readable code speeds up development. Fact. But as we’ve already discussed, "clean code" is not a panacea. Everyone will still fight over what "clean" means anyway. Don't blindly follow Martin if the task doesn't require it. If you’re writing a one-off migration script or a prototype that’s getting tossed tomorrow, spending hours on architecture is counterproductive. Context is everything.&lt;/p&gt;

&lt;p&gt;The worst thing you can do is mindlessly apply complex patterns where a simple solution works. Three weeks later, you have a monster that takes longer to start than it does to run. It solves a problem that never existed.&lt;/p&gt;

&lt;p&gt;The goal isn't to write clean code for the sake of cleanliness; it's to write maintainable code where it actually matters. Find the balance, think about the future of your project, and always keep learning. &lt;strong&gt;(And one more thing: never collaborate with dictatorships. The restrictions and systems you build are exactly what allow them to feel comfortable and wage wars.)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Good luck&lt;/p&gt;

</description>
      <category>programming</category>
      <category>cleancode</category>
      <category>career</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
