<?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: Richard Ochola</title>
    <description>The latest articles on DEV Community by Richard Ochola (@ochola).</description>
    <link>https://dev.to/ochola</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%2F3732820%2F8b2f74e4-0bc9-4355-a739-5f3e75035dd7.jpeg</url>
      <title>DEV Community: Richard Ochola</title>
      <link>https://dev.to/ochola</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ochola"/>
    <language>en</language>
    <item>
      <title>The Death of the Front End</title>
      <dc:creator>Richard Ochola</dc:creator>
      <pubDate>Wed, 03 Jun 2026 18:15:10 +0000</pubDate>
      <link>https://dev.to/ochola/the-death-of-the-front-end-4eog</link>
      <guid>https://dev.to/ochola/the-death-of-the-front-end-4eog</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We spent thirty years building the web for human eyes. We may have gotten it wrong.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  I. The Last Time You Clicked a Blue Link.
&lt;/h2&gt;

&lt;p&gt;Think back. When did you last open a search engine and feel genuinely satisfied with what came back? Not tolerant. Not resigned. Actually satisfied the way you feel when someone answers your question instead of handing you a stack of pamphlets and wishing you luck.&lt;/p&gt;

&lt;p&gt;For most of us, that moment has already passed. We stopped searching and started asking. We got tired of the blue link lottery the SEO slop, the affiliate farms, the endless scrolling through ten pages of noise to find one sentence of signal. Quietly, without fanfare, we made a different choice.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We didn't abandon search. Search abandoned us first.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That shift wasn't just a change in habit. It was the opening chapter of something much bigger a story about what the internet is actually for, and who it was ever really built to serve.&lt;/p&gt;

&lt;h2&gt;
  
  
  II. The Citizens Nobody Designed For
&lt;/h2&gt;

&lt;p&gt;Here is the uncomfortable truth that the industry hasn't fully faced yet: we have been building the wrong infrastructure for the wrong user.&lt;/p&gt;

&lt;p&gt;Every pixel-perfect component, every A/B tested button colour, every carefully considered onboarding flow we built all of it for a user who is increasingly handing the wheel to an agent. The new first-class citizens of the internet don't need your dropdown menu. They don't have eyes. They have context windows.&lt;/p&gt;

&lt;p&gt;I've felt this personally. As AI and Ml engineer, building autonomous file analyzers and local-first data systems, the pattern became impossible to ignore: every time I wired an agent into a real-world system, the UI became an obstacle. Not a feature. An obstacle. The machine had to squint through layers of CSS and DOM noise just to extract the one thing it actually needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We are engineering for the human eye while the machine waits patiently outside, pressing its face against the glass.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  III. The Tax We Forgot We Were Paying
&lt;/h2&gt;

&lt;p&gt;There is a cost hiding inside every page load that we never put on the balance sheet. Call it the &lt;em&gt;&lt;code&gt;Token Tax&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Every time an agent parses a full DOM tree bloated with decorative spans, layout scaffolding, tracking scripts, and CSS that exists purely to make a gradient look good on a 2019 MacBook it burns compute. It burns context. It burns money. And at the end of all that burning, the agent extracts a price, an endpoint, a date. Something that could have been a single line of JSON.&lt;/p&gt;

&lt;p&gt;The absurdity of this only hits you when you sit with it. We are running sophisticated intelligence through a funnel designed for eyeballs. We are asking the most capable reasoning systems ever built to cosplay as web scrapers.&lt;/p&gt;

&lt;p&gt;The fix isn't complicated. It requires a mindset shift. We need an &lt;em&gt;&lt;code&gt;API-First Mandate&lt;/code&gt;&lt;/em&gt; not as a backend afterthought, but as the primary design contract. JSON. GraphQL. Semantic, typed, machine legible interfaces that tell an agent exactly what it needs to know, with zero visual clutter in the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  IV. The World After the Refactor
&lt;/h3&gt;

&lt;p&gt;None of this means the end of beauty. It means the beginning of a different kind of beauty one that works at two levels simultaneously. A layer humans can see, and a layer machines can read. Not competing. Parallel.&lt;/p&gt;

&lt;p&gt;Picture the phone of the near future. There are no apps to open. No home screen to swipe through. Just a conversation. "Send this." "Find me a flight." "What's left on my list?" Fluid, instant, invisible. The interface collapses into intent.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The best interface is no interface just your thought, translated into action.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The developer who thrives in this world won't be a UI engineer or a backend specialist. They'll be something new: an &lt;em&gt;&lt;code&gt;Architect of Semantic Interfaces&lt;/code&gt;&lt;/em&gt;. Someone who designs systems legible to both species human and machine with equal craft and care.&lt;/p&gt;

&lt;p&gt;This is the refactor the web has always needed. Not a teardown. A transformation. We stop building for display and start building for understanding. We stop optimising for the scroll and start optimising for the query.&lt;/p&gt;

&lt;p&gt;The front end isn't dying because we failed. It's dying because we succeeded and the thing we built is now ready to be outgrown.&lt;/p&gt;

&lt;p&gt;The next era belongs to those who build for the intelligence that comes next. The architects who see both the human and the machine, and design for both without apology, without compromise.&lt;/p&gt;

&lt;p&gt;Start building for them. The future is already asking.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>agents</category>
      <category>career</category>
    </item>
    <item>
      <title>Mistakes every Go beginner makes. Part 1 : Time Complexity Issues</title>
      <dc:creator>Richard Ochola</dc:creator>
      <pubDate>Tue, 03 Feb 2026 11:43:15 +0000</pubDate>
      <link>https://dev.to/ochola/mistakes-every-go-beginner-makes-part-1-time-complexity-issues-4ao5</link>
      <guid>https://dev.to/ochola/mistakes-every-go-beginner-makes-part-1-time-complexity-issues-4ao5</guid>
      <description>&lt;p&gt;When you start learning Go, the syntax feels clean and the speed feels amazing. But there is a trap many beginners fall into: writing code that works perfectly for small tasks but crawls to a halt when the data gets bigger.&lt;/p&gt;

&lt;p&gt;Recently, I was working on an &lt;strong&gt;ASCII Art Generator&lt;/strong&gt;. The logic was simple: take a string, find the corresponding ASCII characters in a template file, and print them out. However, I noticed that as my input text got longer, the program started lagging.&lt;/p&gt;

&lt;p&gt;The culprit? &lt;strong&gt;How I was collecting my results.&lt;/strong&gt; Let's look at the two "silent" performance killers I found in my own code.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The String Concatenation Trap
&lt;/h2&gt;

&lt;p&gt;In my project, I had a function to build the final output string. I was using the &lt;code&gt;+=&lt;/code&gt; operator to join every line together.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Before" Code (Slow):
&lt;/h3&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="n"&gt;OutputCharacters&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charmap&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;rune&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="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&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;BuildASCII&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="n"&gt;charmap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="c"&gt;// The Hidden Performance Killer&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;res&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Technical "Why"
&lt;/h3&gt;

&lt;p&gt;In Go, &lt;strong&gt;strings are immutable&lt;/strong&gt;. This means once a string is created in memory, it can never be changed.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;res += line&lt;/code&gt;, Go doesn't just "tack" the new text onto the end. Instead, it performs a costly cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It allocates a &lt;strong&gt;brand new memory block&lt;/strong&gt; large enough for the old string + the new line.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;copies&lt;/strong&gt; every single byte from the old string into the new one.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;copies&lt;/strong&gt; the new line into the new memory.&lt;/li&gt;
&lt;li&gt;It throws away the old string for the Garbage Collector to clean up.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As your loop grows, you are copying the same data over and over again. This creates a *&lt;em&gt;Time Complexity of *&lt;/em&gt;. If you have 1,000 lines, you aren't just doing 1,000 operations; you're performing millions of byte copies!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: &lt;code&gt;strings.Builder&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Go provides &lt;code&gt;strings.Builder&lt;/code&gt;, which uses a mutable byte slice internally. It grows smarter (usually doubling in size) so it doesn't have to copy everything every time.&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="n"&gt;OutputCharacters&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charmap&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;rune&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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Builder&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;BuildASCII&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="n"&gt;charmap&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&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;lines&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&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;builder&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="c"&gt;// Final string is created only ONCE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. The Unallocated Slice Issue
&lt;/h2&gt;

&lt;p&gt;Inside my &lt;code&gt;BuildASCII&lt;/code&gt; function, I was creating a slice of strings to hold the art, but I was initializing it as an empty slice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="c"&gt;// Length: 0, Capacity: 0&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;A slice in Go is backed by an &lt;strong&gt;underlying array&lt;/strong&gt;. When you &lt;code&gt;append&lt;/code&gt; to a slice that is full, Go has to "move house":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It finds a new, larger spot in memory.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;copies&lt;/strong&gt; all current elements to the new spot.&lt;/li&gt;
&lt;li&gt;It updates the slice pointer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my ASCII project, I knew that every word in the input would result in exactly 8 lines of ASCII art. By not telling Go this, I was forcing the program to stop and "move house" (reallocate) multiple times as the list grew.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Pre-allocation with &lt;code&gt;make&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you can calculate or even estimate the size, you should pre-allocate the capacity. This "reserves" the memory upfront.&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="n"&gt;BuildASCII&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charmap&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;rune&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="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="c"&gt;// We know the exact size: 8 lines per input word&lt;/span&gt;
    &lt;span class="n"&gt;totalExpected&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;len&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="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
    &lt;span class="n"&gt;res&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&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;totalExpected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Length 0, but Capacity is set!&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&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;input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// ... build lines ...&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Zero reallocations happen now!&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;res&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;When you're a beginner, "making it work" is the priority. But as you grow, "making it efficient" becomes the goal. By understanding how Go handles memory, you can prevent your programs from slowing down as they scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you run into these "slow loops" before? What other beginner traps should I cover in Part 2? Let me know below!&lt;/strong&gt; &lt;/p&gt;

</description>
      <category>programming</category>
      <category>devops</category>
      <category>beginners</category>
      <category>go</category>
    </item>
  </channel>
</rss>
