<?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: M Yauri M Attamimi</title>
    <description>The latest articles on DEV Community by M Yauri M Attamimi (@yauritux).</description>
    <link>https://dev.to/yauritux</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F112793%2F16ef8dad-7a86-448e-9dc6-93c473384143.jpg</url>
      <title>DEV Community: M Yauri M Attamimi</title>
      <link>https://dev.to/yauritux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yauritux"/>
    <language>en</language>
    <item>
      <title>From Backend Engineer to AI Engineer</title>
      <dc:creator>M Yauri M Attamimi</dc:creator>
      <pubDate>Tue, 28 Jul 2026 15:02:18 +0000</pubDate>
      <link>https://dev.to/yauritux/from-backend-engineer-to-ai-engineer-3i8d</link>
      <guid>https://dev.to/yauritux/from-backend-engineer-to-ai-engineer-3i8d</guid>
      <description>&lt;p&gt;&lt;em&gt;The Natural Evolution from Backend Engineering to Agentic AI, and Why Elixir is the Runtime You Didn't Know You&amp;nbsp;Needed&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: The views expressed here reflect my personal opinions and interpretations based on hands-on experience. They are supported by community research and industry practices, but they represent my perspective, not absolute truths. AI engineering is evolving rapidly - what's current today may be obsolete tomorrow.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;If you've been in Software Engineering for the past few years, you've watched the AI landscape shift beneath your feet at a pace that makes Moore's Law look leisurely. What started as a novelty of crafting clever prompts has matured into a full-fledged engineering discipline with its own architectures, patterns, and paradigms.&lt;br&gt;
In a recent weekly developer sharing session, I presented my take on this evolution and Why I believe backend engineers are uniquely positioned to lead this next wave - and why Elixir and the BEAM VM are quietly becoming one of the most compelling platforms for the next generation of AI systems. This post is an expanded version of that talk.&lt;br&gt;
Let's walk through the journey: from prompt engineering to agentic AI systems, and why your backend engineering skills matter more than ever.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Evolution of AI Engineering
&lt;/h2&gt;

&lt;p&gt;If we zoom out and look at the trajectory of AI application development, we can identify four distinct eras - each building on the last:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Prompt Engineering (2022–2024)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The central question: "What should I say to the model?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was the era of crafting the perfect prompt. We built chatbots and copilots, and the engineering work revolved around techniques like Chain-of-Thought (CoT), ReAct, few-shot prompting, and role-playing. The focus was squarely on the input - how to phrase things so the LLM gave us the best possible output.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Context Engineering (2025)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The central question: "What information should I provide to the model?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As models grew more capable, we realized that prompting alone wasn't enough. The real differentiator became what context we fed the model. This gave rise to RAG (Retrieval-Augmented Generation) systems and grounded assistants. The engineering focus shifted to information architecture - how to retrieve, rank, chunk, and deliver the right information at the right time.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. AI Agents (2025–2026)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The central question: "How do I make it autonomous?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where things started getting interesting from a systems perspective. We moved from single-turn interactions to single autonomous agents that could reason, act, and observe in a loop. The engineering here combines what I call Harness Engineering and Loop Engineering - giving agents tools, memory, autonomy, and a structured cycle to follow.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Agentic AI Systems&amp;nbsp;(2026+)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The central question: "How do agents collaborate?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The frontier. We're now looking at multi-agent systems where multiple autonomous agents coordinate, delegate, and self-heal. This requires advanced loop engineering, distributed state management, and sophisticated orchestration - problems that should sound very familiar to backend engineers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Complete Picture&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbipgy5rj5mx5iasn8oj9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbipgy5rj5mx5iasn8oj9.png" alt=" " width="799" height="362"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What Makes an AI Agent "Agentic"?
&lt;/h2&gt;

&lt;p&gt;The term "agent" gets thrown around a lot. Not every chatbot with a tool is an agent. Let's clarify the spectrum:&lt;/p&gt;
&lt;h3&gt;
  
  
  Chatbot VS Agent VS Agentic&amp;nbsp;AI
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnnssfwu71obcuajnehn8.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnnssfwu71obcuajnehn8.png" alt=" " width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Core Traits of Agentic&amp;nbsp;AI
&lt;/h3&gt;

&lt;p&gt;For a system to truly be agentic, it should exhibit these properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autonomy:&lt;/strong&gt; Makes decisions without human intervention&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Goal-Directed:&lt;/strong&gt; Works toward defined objectives, not just responding to inputs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adaptive:&lt;/strong&gt; Adjusts behavior based on feedback and observations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent:&lt;/strong&gt; Maintains state across context window resets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable:&lt;/strong&gt; Coordinates with other agents as part of a larger system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observable:&lt;/strong&gt; Telemetry and tracing are built in, not bolted on&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The Key Shift: We're moving from "an LLM that responds" to "an LLM that executes in a loop."&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  The Two Pillars of Agentic&amp;nbsp;AI
&lt;/h2&gt;

&lt;p&gt;Building production-grade agentic AI comes down to two engineering disciplines:&lt;/p&gt;
&lt;h3&gt;
  
  
  Pillar 1: Harness Engineering
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What environment does the agent need?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The harness is everything surrounding the LLM that makes it useful and safe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tools, APIs, and Capabilities&lt;/strong&gt; - What can the agent do?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints and guardrails&lt;/strong&gt; - What shouldn't the agent do?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error recovery &amp;amp; state persistence&lt;/strong&gt; - What happens when things go wrong?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and permission models&lt;/strong&gt; - Who can the agent act on behalf of?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Pillar 2: Loop Engineering
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What cycle drives the agent toward the goal?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The loop is the engine of agency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Iteration logic&lt;/strong&gt; - The classic Reason → Act → Observe cycle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination conditions&lt;/strong&gt; - When does the agent stop?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalation policies&lt;/strong&gt; - When should it alert a human?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progress tracking and logging&lt;/strong&gt; - How do we know what it's doing?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it this way:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxv2pdyh405ebjcej71ez.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxv2pdyh405ebjcej71ez.png" alt=" " width="534" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PROMPT → CONTEXT (info) → LOOP (cycle) → HARNESS (environment)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Each layer builds on the previous one. The prompt is what you say. The context is what you know. The loop is how you think. The harness is where you operate.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why Backend Engineers Have a Massive Advantage
&lt;/h2&gt;

&lt;p&gt;Here's something the AI hype cycle often misses: building agentic AI is fundamentally a backend engineering problem.&lt;/p&gt;

&lt;p&gt;Look at the mapping:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe4f3c8qafop1tbwrph9w.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe4f3c8qafop1tbwrph9w.png" alt=" " width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've spent years building resilient, distributed backend systems, you already have the mental models for agentic AI. The LLM is just a new kind of unreliable external service that you need to wrap with retries, timeouts, state management, and observability.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why Elixir for Agentic&amp;nbsp;AI?
&lt;/h2&gt;

&lt;p&gt;This is where I get genuinely excited. The BEAM virtual machine - the runtime behind Elixir - was practically designed for the kinds of workloads that agentic AI demands. Let's look at why:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Lightweight Processes
&lt;/h3&gt;

&lt;p&gt;Each agent can run in its own isolated process, consuming as little as 25 KB of memory. If one agent crashes, it never takes down another. This maps perfectly to the "one agent, one process" model.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Supervision Trees
&lt;/h3&gt;

&lt;p&gt;OTP supervisors detect crashes and restart agents in milliseconds. Failure recovery isn't something you build - it's something you get from the runtime. The "Let It Crash" philosophy is exactly what you want when an LLM call hangs, a tool fails, or an agent enters an unexpected state.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Massive Concurrency
&lt;/h3&gt;

&lt;p&gt;BEAM schedulers handle thousands of concurrent agents with true parallelism - no thread pools to tune, no async/await gymnastics, no GIL to fight. When you're running hundreds of agents, each executing multi-step reasoning loops, this matters enormously.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Message&amp;nbsp;Passing
&lt;/h3&gt;

&lt;p&gt;Agents communicate via asynchronous messages, which is a natural fit for distributed agent systems. No shared state, no locks, just clean message-based coordination.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Hot Code&amp;nbsp;Upgrades
&lt;/h3&gt;

&lt;p&gt;You can update agent logic without downtime. In production agentic systems where agents may be running for hours or days, the ability to push behavioral updates live is critical.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Elixir Tooling Ecosystem
&lt;/h2&gt;

&lt;p&gt;The community is already building the tools we need.&lt;/p&gt;
&lt;h3&gt;
  
  
  ReqLLM - Composable LLM Interactions in&amp;nbsp;Elixir
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://req-llm.hexdocs.pm/overview.html" rel="noopener noreferrer"&gt;ReqLLM&lt;/a&gt; provides a unified, idiomatic Elixir interface for interacting with LLMs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unified API across providers (OpenAI, Anthropic, local models)&lt;/li&gt;
&lt;li&gt;Flexible model specifications (string, tuple, struct formats)&lt;/li&gt;
&lt;li&gt;Rich prompt support with structured data generation&lt;/li&gt;
&lt;li&gt;Idiomatic Elixir - pipe-friendly, pattern-matching native&lt;/li&gt;
&lt;li&gt;Tracks 92+ non-text operation models (vision, audio, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;response =
  ReqLLM.chat!(
    "openai:gpt-4o",
    [
      %{role: "system", content: "You are a helpful assistant."},
      %{role: "user", content: "What is the capital of France?"}
    ]
  )

# Pattern match on the response
%ReqLLM.Message{content: answer} = response
IO.puts(answer)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Full source code: &lt;a href="https://github.com/yauritux/reqllm_demo" rel="noopener noreferrer"&gt;github.com/yauritux/reqllm_demo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Jido Framework - Production-Grade Agents in&amp;nbsp;Elixir
&lt;/h3&gt;

&lt;p&gt;takes things further by providing a framework for building production-grade agentic systems on the BEAM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OTP-Native Architecture&lt;/strong&gt; - Agents are GenServers with supervision trees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Immutable Agents&lt;/strong&gt; - State transitions are explicit and traceable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Optional&lt;/strong&gt; - Not every step needs an LLM; mix deterministic logic with AI reasoning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit Effect Boundaries&lt;/strong&gt; - Side effects are declared, not hidden&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Massive Concurrency&lt;/strong&gt; - Built on the BEAM's process model from day one. Every agent runs in its own lightweight process. If one crashes, nothing else is affected.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Real-World Example: Smart Ticketing Agents with&amp;nbsp;Jido
&lt;/h2&gt;

&lt;p&gt;To see how this comes together, let's look at a Smart Ticketing System built with Jido. Imagine a raw, panicked customer email comes in:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;INPUT:&lt;/strong&gt; "My dashboard is loading super slow and showing a 503 error. I have a big presentation in an hour and I'm freaking out!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of a single monolithic script trying to do everything, we route this through a multi-agent pipeline:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Triage Agent
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Strategy&lt;/strong&gt;: Uses the &lt;strong&gt;CREATE&lt;/strong&gt; framework (Context, Result, Explain, Audience, Tone, Edit) combined with &lt;strong&gt;Chain-of-Thought&lt;/strong&gt; (CoT).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input&lt;/strong&gt;: Raw email text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action&lt;/strong&gt;: Analyzes the emotional weight and extracts technical signals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output&lt;/strong&gt;: Structured JSON.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ 
  "reasoning": "customer is highly desperate...",
  "sentiment": "highly_negative", 
  "priority": "critical", 
  "error_code": "503"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. The Diagnostic Agent
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Strategy&lt;/strong&gt;: Uses a ReAct Loop (Reason + Act) combined with Few-Shot Prompting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input&lt;/strong&gt;: The extracted error_code = "503" from the Triage Agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: check_server_status/1, restart_service/1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action&lt;/strong&gt;: The agent reasons about the 503 error, calls the check_server_status tool, realizes the frontend process crashed, and executes restart_service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output&lt;/strong&gt;: Technical resolution report.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ 
  "issue": "503 service unavailable", 
  "root_cause": "web frontend process crashed", 
  "resolution": "service restarted successfully", 
  "status": "resolved"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because these agents are built on Jido and the BEAM, the Triage Agent and Diagnostic Agent run in isolated processes. If the Diagnostic Agent hits a timeout while calling the external API, it crashes and restarts without bringing down the Triage Agent or the rest of the application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out the full implementation at &lt;a href="https://github.com/yauritux/smart_ticket" rel="noopener noreferrer"&gt;github.com/yauritux/smart_ticket&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Conclusion: The Backend Engineer's Moment
&lt;/h2&gt;

&lt;p&gt;The AI industry spent years telling us that the future belonged to ML researchers and data scientists. And for the era of model training, that was true. But we've entered a new era - the era of agentic AI systems - where the hardest problems are about orchestration, resilience, state management, and distributed coordination.&lt;br&gt;
These are backend engineering problems. And the tools we've been using for decades - message queues, supervision trees, process isolation, hot deployments - are exactly the right tools for this job.&lt;br&gt;
If you're a backend engineer looking at the AI space and wondering where you fit in: you're not behind. You're early. And if you're looking for a runtime that was practically designed for the concurrency, fault-tolerance, and distribution challenges of agentic AI, take a serious look at Elixir, Jido, and the BEAM.&lt;br&gt;
The evolution from prompt engineering to agentic AI systems is the most exciting shift I've seen in my career. And the best part? The skills you already have are the skills this new era demands.&lt;/p&gt;

&lt;p&gt;Go build something autonomous.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Questions? Thoughts? I'd love to hear from you. Feel free to reach out or drop a comment below.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>elixir</category>
      <category>agents</category>
    </item>
    <item>
      <title>How I Personally Grasp the Essence of Concurrency in Go</title>
      <dc:creator>M Yauri M Attamimi</dc:creator>
      <pubDate>Wed, 25 Mar 2026 18:02:44 +0000</pubDate>
      <link>https://dev.to/yauritux/how-i-personally-grasp-the-essence-of-concurrency-in-go-238e</link>
      <guid>https://dev.to/yauritux/how-i-personally-grasp-the-essence-of-concurrency-in-go-238e</guid>
      <description>&lt;h2&gt;
  
  
  Philosophy, Patterns &amp;amp; The Power of Built-in Tools
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Why Go says “Don’t communicate by sharing memory” and how to build robust systems without external libraries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you come from a background in Java (like me), Python, or JavaScript, the word “concurrency” might trigger a slight sense of anxiety. We are taught that threads are dangerous, race conditions are lurking around every corner, and debugging deadlocks is a nightmare.&lt;/p&gt;

&lt;p&gt;Then you meet Go.&lt;/p&gt;

&lt;p&gt;Go doesn’t just offer a new way to write concurrent code; it offers a new way to think about it. But beyond the famous mantras, how does this philosophy translate to actual engineering ? And perhaps most importantly, do you need external libraries to make it work ?&lt;/p&gt;

&lt;p&gt;The answer is a resounding NO. Everything you need to build enterprise-grade concurrent systems is built directly into the language and its standard library.&lt;/p&gt;

&lt;p&gt;In this post, we’ll recap the core philosophies of Go concurrency, explore the patterns that make it powerful, and highlight the built-in tools that let you implement them without adding a single dependency.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. The Core Philosophy: CSP vs. Shared Memory&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The most famous quote in Go concurrency comes from Rob Pike:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Don’t communicate by sharing memory; share memory by communicating.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the principle of CSP (Communicating Sequential Processes). To understand it, we need to contrast it with the traditional model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Traditional Model: Shared Memory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a single-occupancy bathroom in an office or any public places.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Resource: The bathroom (a variable in memory). &lt;/li&gt;
&lt;li&gt;The Problem: Multiple people (threads) need to use it.&lt;/li&gt;
&lt;li&gt;The Solution: A lock on the door (mutex). You must acquire the key, use the bathroom, and return (release/unlock) the key after you use it.&lt;/li&gt;
&lt;li&gt;The Risk: What if someone forgets to unlock the door ? (Deadlock). What if someone sneaks in without the key ? (Race Condition).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Go Model: CSP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a factory conveyor belt (a Channel).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Resource: The parts being built (data).&lt;/li&gt;
&lt;li&gt;The Process: Worker A places a part on the belt. The belt moves it to Worker B.&lt;/li&gt;
&lt;li&gt;The Safety: At any specific moment, only one person is holding the part. When it is on the belt, no one is touching it.&lt;/li&gt;
&lt;li&gt;The Focus: You aren’t protecting a static (shared) variable; You are managing the flow of data.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In Go: You don’t protect a variable with a lock! You pass the variable over a chan. Ownership is transferred safely from one goroutine to another.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. The Engineering Mantra: Sequence and Backpressure
&lt;/h2&gt;

&lt;p&gt;There is a second, practical mantra that follows the philosophy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Don’t over engineer things by using shared memory and complicated, error prone synchronization primitives; instead, use message-passing between Goroutines so variable and data can be used in the appropriate sequence.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where Go shines in production. Channels aren’t just for moving data; they are for controlling time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Relay Race Analogy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shared Memory: Workers check a whiteboard every second to see if the previous step is done. (Busy waiting, complex logic)&lt;/li&gt;
&lt;li&gt;Channels: Workers stand in a line. Worker 2 physically cannot start until Worker 1 hands them the baton.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sequence Guaranteed:&lt;/strong&gt; A receive operation ( &lt;code&gt;&amp;lt;-&lt;/code&gt; ) blocks automatically until data arrives. You don’t need to write if done {...} loops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural Backpressure:&lt;/strong&gt; If the Consumer is slow, the Channel fills up. The Producer automatically blocks and waits. This prevents your program from consuming all RAM trying to process data faster than the database can save it.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. The Producer-Consumer Problem (Solved Simply)
&lt;/h2&gt;

&lt;p&gt;The classic Producer-Consumer pattern is kind of “Hello World” of concurrency. It solves the problem of balancing speed between data creation and data processing.&lt;/p&gt;

&lt;p&gt;In many languages, implementing a &lt;strong&gt;bounded-buffer&lt;/strong&gt; (a queue that stops accepting data when full) requires complex condition variables and locks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Traditional Way (as conceptually handled in Java)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Requires Mutex, Condition Variables, Wait(), Signal(), etc.&lt;/span&gt;
&lt;span class="c1"&gt;// Easy to get wrong. Hard to read.&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;acquire&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isFull&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release&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;&lt;strong&gt;The “Go” Way&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Go, a &lt;strong&gt;Buffered Channel&lt;/strong&gt; is a thread-safe Producer-Consumer queue.&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;// Create a buffer that holds exactly 5 items&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Producer&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="c"&gt;// Automatically blocks if channel is full (Backpressure!)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="c"&gt;// Consumer&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// Automatically blocks if channel is empty&lt;/span&gt;
        &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&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;&lt;strong&gt;That’s it.&lt;/strong&gt; No locks. No condition variables. No manual signaling. The language runtime handles the synchronization for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The Go Standard Toolbox (No External Libraries Needed)
&lt;/h2&gt;

&lt;p&gt;One of Go’s greatest strengths is that you do not need third-party frameworks to handle different patterns of concurrency. The standard library is batteries-included.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------------+----------------+------------------+--------------+
|.  Pattern.          |. Tool.         | Package.         |.  Built-In ? | 
+---------------------|----------------|------------------|--------------+
| Lightweight Threads | goroutine      | Language Keyword |  ✅ Yes      |
| Communication       | chan           | Language Keyword |  ✅ Yes      |
| State Protection    | sync.Mutex     | sync             |  ✅ Yes      |
| Wait Groups         | sync.WaitGroup | sync             |  ✅ Yes      |
| High Perf Counters  | atomic         | sync/atomic      |  ✅ Yes      |
| Lifecycle/Timeout   | context        | context          |  ✅ Yes      |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Structure Concurrency with&lt;/strong&gt; &lt;code&gt;context&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In traditional concurrency, knowing when to stop a &lt;code&gt;goroutine&lt;/code&gt; is hard. Go solves this with the &lt;code&gt;context&lt;/code&gt; package. It allows you to cascade cancellation signals.&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="n"&gt;ctx&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;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&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;// Pass ctx to your goroutines. &lt;/span&gt;
&lt;span class="c"&gt;// If the timeout hits, all listening goroutines stop gracefully.&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This prevents &lt;strong&gt;goroutine leaks&lt;/strong&gt;, a common bug in other languages where background tasks keep running forever after a request finishes.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. When to Break the Rules
&lt;/h2&gt;

&lt;p&gt;While “Share memory by communicating” is the default path, Go is pragmatic. As an engineer we know that there’s “size fits for all”. It always depends on the usecase / problem we’re trying to solve. There are times when shared memory is better:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Simple State:&lt;/strong&gt; If you just need to protect a simple config map or cache, a &lt;code&gt;sync.Mutex&lt;/code&gt; is often clearer than setting up a channel loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Channels have a small overhead. For extremely high-frequency counters, &lt;code&gt;sync/atomic&lt;/code&gt; is faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal State:&lt;/strong&gt; If a struct has internal state that shouldn’t be exposed, protecting it with a mutex inside its methods is cleaner.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;The Rule of Thumb:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;channels&lt;/strong&gt; to orchestrate &lt;strong&gt;flow&lt;/strong&gt; (pipelines, worker pools)&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;mutexes&lt;/strong&gt; to protect state (caches, configs)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. Beyond the Basics: Actor Model &amp;amp; Async
&lt;/h2&gt;

&lt;p&gt;Go’s model is unique compared to other ecosystems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vs. Async/Await (JS/Python):&lt;/strong&gt; Go hides the complexity. You write code that &lt;em&gt;looks synchronous&lt;/em&gt; (e.g., &lt;code&gt;response:= http.Get(...)&lt;/code&gt;), but the runtime parks the &lt;code&gt;goroutine&lt;/code&gt; efficiently. &lt;strong&gt;No callback hell&lt;/strong&gt;, &lt;strong&gt;no explicit&lt;/strong&gt; &lt;code&gt;await&lt;/code&gt; keywords everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vs. Actor Model (Erlang/Elixir/Akka):&lt;/strong&gt; &lt;strong&gt;Go&lt;/strong&gt; is similar but more flexible. In &lt;em&gt;Actor Model&lt;/em&gt; pattern: mailboxes (&lt;em&gt;channel&lt;/em&gt; in &lt;strong&gt;Go&lt;/strong&gt;) belong to actors. In &lt;strong&gt;Go&lt;/strong&gt;, &lt;em&gt;channels&lt;/em&gt; are independent entities that multiple &lt;code&gt;goroutines&lt;/code&gt; can share. However, you can build an Actor in Go using a &lt;code&gt;goroutine + switch statement + channel&lt;/code&gt;, but you aren’t forced into that paradigm.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Concurrency in Go is not just about doing multiple things at once; its about &lt;strong&gt;composing&lt;/strong&gt; those things safely.&lt;/p&gt;

&lt;p&gt;By adopting the CSP philosophy, you shift your mindset from &lt;strong&gt;protecting resources&lt;/strong&gt; (&lt;em&gt;locks&lt;/em&gt;) to &lt;strong&gt;managing flow&lt;/strong&gt; (&lt;em&gt;channels&lt;/em&gt;). By leveraging the built-in tools like &lt;code&gt;chan&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt;, and &lt;code&gt;sync&lt;/code&gt;, you avoid the dependency hell common in other ecosystems.&lt;br&gt;
You get:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; Race conditions are harder to introduce.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backpressure:&lt;/strong&gt; Systems self-regulate under load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity:&lt;/strong&gt; Complex workflows look like simple pipeline.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So.. the next time you face a concurrency problem, remember the mantra: &lt;strong&gt;Don’t communicate by sharing memory. Share memory by communicating&lt;/strong&gt;. And trust the tools that come right out of the box.&lt;/p&gt;

</description>
      <category>go</category>
      <category>goroutine</category>
      <category>multithreading</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Clean Code Architecture in Go</title>
      <dc:creator>M Yauri M Attamimi</dc:creator>
      <pubDate>Sun, 05 Apr 2020 14:40:57 +0000</pubDate>
      <link>https://dev.to/yauritux/clean-code-architecture-in-go-9fj</link>
      <guid>https://dev.to/yauritux/clean-code-architecture-in-go-9fj</guid>
      <description>&lt;p&gt;Everyone can write code to produce a software that functionally works as expected, yet not everyone care about how's their code architecture look like. The best chosen algorithms not always save us from the bad software design. There are many code architectures around, and recently i've been struggling and trying to promote the &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"&gt;Clean Code Architecture&lt;/a&gt; from Robert C. Martin a.k.a. &lt;a href="http://cleancoder.com/products"&gt;Uncle Bob&lt;/a&gt;. Let's start with how this sort of code architecture looks like in &lt;a href="https://golang.org/"&gt;Go&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I’m gonna start by implementing some of the functionalities within a shopping cart since it’s pretty straightforward. Bear in mind that what i’ll be showing here is restricted to the &lt;em&gt;bounded context&lt;/em&gt; of the shopping cart, means we’ll just focus with the process of how a user/buyer choose the item and adding that particular item into his cart, and subsequently continue with the checkout. As for the billing/payment part, that will be in the &lt;em&gt;bounded context&lt;/em&gt; of another service such as payment service. (if you’re neither really familiar nor confidence with what &lt;em&gt;bounded context&lt;/em&gt; is, i would suggest you to read another article of mine from &lt;a href="https://medium.com/@yauritux/ddd-part-i-introduction-cabab1d2e27d"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By the way, all of the source code i explain here can be cloned/forked from &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qF2jUiUG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-6a5bca60a4ebf959a6df7f08217acd07ac2bc285164fae041eacb8a148b1bab9.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/yauritux"&gt;
        yauritux
      &lt;/a&gt; / &lt;a href="https://github.com/yauritux/clean-code-architecture"&gt;
        clean-code-architecture
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      My personal opinion on the Clean Code Architecture in the context of Domain Driven Design (DDD), yet i adopted some terms from the Onion Architecture such as domain to avoid any misleading interpretations with the Entity in DDD
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f4cC0FsO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cfgza08oi41iq9ke9us0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f4cC0FsO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cfgza08oi41iq9ke9us0.jpg" alt="Common Shopping Cart Process"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What are highlighted in the grey colors were standing outside of our shopping cart &lt;em&gt;bounded context&lt;/em&gt;. Hence, we won’t tackle the nitty gritty details of those objects within our code implementation since those things would be in other services (e.g. &lt;strong&gt;product catalogue service&lt;/strong&gt; and &lt;strong&gt;user service&lt;/strong&gt;). Nevertheless, we’ll still be having those objects within our code, in the &lt;em&gt;context&lt;/em&gt; of what our shopping cart needs. For instance, we won’t need user credentials information in our shopping cart since that should be catered from the &lt;strong&gt;user service&lt;/strong&gt; context. Basically, we just need user information which is related to the shopping cart itself, such as: &lt;strong&gt;user_session_id&lt;/strong&gt;, &lt;strong&gt;shipping address&lt;/strong&gt;, &lt;strong&gt;billing address&lt;/strong&gt; (furthermore, address information should also be catered from another service, e.g. : &lt;strong&gt;address service&lt;/strong&gt;, even this is also optional).&lt;/p&gt;

&lt;p&gt;There are some rules for this architecture those we must bear within our mind. I've summarized those rules as following: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dependency between layer should be going inward in one direction. As far as i concern, it was designed like this to avoid any &lt;a href="https://en.wikipedia.org/wiki/Circular_dependency"&gt;circular dependencies&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A layer should depend only on one direct layer (one level) beneath it, it shouldn’t know any layers beyond that level. For instance, &lt;strong&gt;A&lt;/strong&gt; depends on &lt;strong&gt;B&lt;/strong&gt; ( &lt;strong&gt;A → B&lt;/strong&gt; ), and &lt;strong&gt;B&lt;/strong&gt; depends on &lt;strong&gt;C&lt;/strong&gt; ( &lt;strong&gt;B → C&lt;/strong&gt; ), yet &lt;strong&gt;A&lt;/strong&gt; shouldn’t know anything about &lt;strong&gt;C&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Each layer should depends upon abstraction ( interface ) rather than implementation. This complies with what &lt;strong&gt;Uncle Bob&lt;/strong&gt; said about 2 rules to fix &lt;strong&gt;RFI&lt;/strong&gt; issues, you can read it from my old article &lt;a href="https://yauritux.wordpress.com/2011/04/03/history-of-dependency-injection-di/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s jump to the implementation by creating our project folder from the terminal and also initialize the go module as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir cart-service &amp;amp;&amp;amp; cd cart-service
go mod init github.com/yauritux/cart-svc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Next step is creating our &lt;code&gt;pkg&lt;/code&gt; directory (&lt;code&gt;mkdir pkg&lt;/code&gt;) from the same terminal. This &lt;code&gt;pkg&lt;/code&gt; directory will contain our implementation logic for the &lt;strong&gt;shopping cart&lt;/strong&gt; which complies with the &lt;strong&gt;clean code architecture&lt;/strong&gt; we’re discussing here.&lt;/p&gt;

&lt;p&gt;By referring to the depicted shopping cart process diagram earlier, we’ll be having these following &lt;strong&gt;entities&lt;/strong&gt; within our code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User&lt;/strong&gt; (this also represents a &lt;strong&gt;Buyer&lt;/strong&gt; in the &lt;strong&gt;shopping cart&lt;/strong&gt; &lt;em&gt;bounded context&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cart&lt;/strong&gt; (as the name implies, this is our cart object which holds our shopping items).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product&lt;/strong&gt; (used as a placeholder for the product information. And for the sake of simplicity…, we won’t have any product categories because our goal here was merely to discuss the Clean Code Architecture).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I create those 3 &lt;strong&gt;entities&lt;/strong&gt; within my &lt;code&gt;pkg/domain/entity&lt;/code&gt; folder. To keep it simple, i deliberately marked all of the fields as &lt;em&gt;exported fields&lt;/em&gt; (moving forward, we can think about hiding the fields information behind the &lt;em&gt;setter&lt;/em&gt; / &lt;em&gt;getter&lt;/em&gt; which are commons in &lt;strong&gt;Java&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Cart Entity&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;code&gt;User Entity&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Product Entity&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And here our &lt;strong&gt;value objects&lt;/strong&gt; ( &lt;code&gt;pkg/domain/valueobject&lt;/code&gt; ):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cart Items&lt;/strong&gt; (strongly related to &lt;strong&gt;Product&lt;/strong&gt; entity).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buyer Address&lt;/strong&gt; (comprises of &lt;strong&gt;Billing&lt;/strong&gt; and &lt;strong&gt;Shipping addresses&lt;/strong&gt;, determined by the &lt;em&gt;Address Type&lt;/em&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;CartItem Value Object&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;BuyerAddress Value Object&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Additionally, we will also have our &lt;strong&gt;enums&lt;/strong&gt; as shown below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;If you’re wondering about the differences between entities and value objects, you can read it from &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/@yauritux/ddd-part-ii-b0735ba584ca" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AGc2xPFW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2AMoWVt2pb-eE9N4KXCxXfFg.png" alt="M Yauri Attamimi"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/@yauritux/ddd-part-ii-b0735ba584ca" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;DDD Part II - M Yauri Attamimi - Medium&lt;/h2&gt;
      &lt;h3&gt;M Yauri Attamimi ・ &lt;time&gt;Jul 15, 2017&lt;/time&gt; ・ 5 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aYMKNcyE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-fbdac08496f06c5bd53be920c7bc8d56d355b69c0fb7e49cac6357a70140af17.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
.

&lt;p&gt;The next important thing to do is to implement our core business logic, which is part of &lt;strong&gt;Entities&lt;/strong&gt; in &lt;strong&gt;Clean Code Architecture&lt;/strong&gt;, or &lt;strong&gt;Core Domain&lt;/strong&gt; in terms of &lt;a href="https://www.thinktocode.com/2018/08/16/onion-architecture/"&gt;Onion Architecture&lt;/a&gt;. This is something that is related to the enterprise business rules out of the application service rule.&lt;/p&gt;

&lt;p&gt;In order to implement this kinda thing, we need to setup our &lt;strong&gt;aggregate root&lt;/strong&gt; (i call it as &lt;strong&gt;user_cart aggregate&lt;/strong&gt;). Again, take a look at what i wrote &lt;a href="https://medium.com/@yauritux/ddd-part-ii-b0735ba584ca"&gt;here&lt;/a&gt; if you’re still wondering about what is the aggregate all about.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Another to-do thing is to setup our &lt;strong&gt;repositories&lt;/strong&gt;. Bear in mind, that when we’re talking about repository, it’s not always about the &lt;strong&gt;database&lt;/strong&gt;. The storage implementation could be anything such as: &lt;strong&gt;web services&lt;/strong&gt;, &lt;strong&gt;file&lt;/strong&gt;, &lt;strong&gt;in-memory&lt;/strong&gt;, etc.., and they should be abstracted by following some contracts defined on the interface. In that way, we can use them interchangeably later since we make our client code depends on the interface rather than directly on the implementation. In order to make it possible, we should start by abstracting our &lt;strong&gt;repositories&lt;/strong&gt; with &lt;strong&gt;interfaces&lt;/strong&gt; such as following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Cart Repository Interface&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;User Repository Interface&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Product Repository Interface&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;I would assume that some of you will be asking about those &lt;strong&gt;empty interfaces&lt;/strong&gt; :-). Why do they exist ? Why do we use them ?.&lt;/p&gt;

&lt;p&gt;As far as i concern, we’ll be having different models for every layer in order to make our architecture more loosely-coupled. In that case, we should abstract our interface model as far as we can, thus we can have more flexibility within our code. Let’s say for the user repository interface, we can have 2 implementations for it, one implementation to get the user information from the database, and another one to get the information from a web service (e.g. REST). Therefore, definitely we’ll have 2 models here, one based on the database model, and another one is based on the web request-response model. That’s the reason why we use &lt;strong&gt;empty interface&lt;/strong&gt; ( &lt;code&gt;interface{}&lt;/code&gt; ) within our repository interface. You get it right ? :-). Don’t worry, everything will become clear once we implement our interface.&lt;/p&gt;

&lt;p&gt;For the sake of simplicity, we'll be implementing just &lt;strong&gt;in-memory repository&lt;/strong&gt; for now since our first goal is merely to discuss about how’s our clean code architecture will be looked like. However, i will incrementally update the code later for another kind of storage / repository, such as database or web service.&lt;/p&gt;

&lt;p&gt;Let’s start to implement our repository interface by creating another directory (at the same level with our &lt;code&gt;domain&lt;/code&gt; directory) as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p pkg/adapter/repository/inmem/model
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And here are our models (inside the &lt;code&gt;pkg/adapter/repository/inmem/model&lt;/code&gt; directory) to be used in the context of our &lt;strong&gt;in-memory repository&lt;/strong&gt; (remember about the &lt;code&gt;interface{}&lt;/code&gt; before, when we designed our repository contract interface).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User Model for In-Memory Repository Implementation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Cart Model for In-Memory Repository Implementation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Product Model for In-Memory Repository Implementation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;subsequently followed by our in-memory repository implementation for those 3 models respectively (inside &lt;code&gt;/adapter/repository/inmem directory&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User In-Memory Repository Implementation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Cart In-Memory Repository Implementation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Product In-Memory Repository Implementation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And the &lt;em&gt;use cases&lt;/em&gt; for &lt;strong&gt;cart&lt;/strong&gt; and &lt;strong&gt;user&lt;/strong&gt; as written below :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User Usecase Port&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;User Usecase Interactor&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Cart Usecase Port&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Cart Usecase Interactor&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Product Usecase Interactor&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Last but not least, let’s create a small CLI program to test our shopping cart functionalities that we’ve created so far.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Shopping Cart CLI tester using in-memory repository&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Ok, some of you might get overwhelmed with all of the code here (while some of you might not), especially in regards with the &lt;strong&gt;use case port&lt;/strong&gt; and &lt;strong&gt;interactor&lt;/strong&gt; (what would be the difference between those 2).&lt;/p&gt;

&lt;p&gt;Test our CLI by using this following command from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run cmd/cli/main.go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can grab the full code from &lt;a href="https://github.com/yauritux/clean-code-architecture"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know for any concerns and/or questions from you guys :-).&lt;/p&gt;

</description>
      <category>go</category>
      <category>architecture</category>
      <category>cleancodearchitecture</category>
    </item>
  </channel>
</rss>
