<?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: Volodya Lombrozo</title>
    <description>The latest articles on DEV Community by Volodya Lombrozo (@volodya-lombrozo).</description>
    <link>https://dev.to/volodya-lombrozo</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%2F3088000%2F5bfc6444-4d91-4262-9bb1-38fb82b73beb.png</url>
      <title>DEV Community: Volodya Lombrozo</title>
      <link>https://dev.to/volodya-lombrozo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/volodya-lombrozo"/>
    <language>en</language>
    <item>
      <title>From Vibe Coder to AI-Assisted Architect</title>
      <dc:creator>Volodya Lombrozo</dc:creator>
      <pubDate>Wed, 07 May 2025 12:23:48 +0000</pubDate>
      <link>https://dev.to/volodya-lombrozo/from-vibe-coder-to-ai-assisted-architect-1nao</link>
      <guid>https://dev.to/volodya-lombrozo/from-vibe-coder-to-ai-assisted-architect-1nao</guid>
      <description>&lt;p&gt;Some claim that AI will soon replace us because it &lt;a href="https://barackobama.medium.com/conversation-at-hamilton-college-0c44228ac0bd" rel="noopener noreferrer"&gt;can code better&lt;/a&gt; than we can.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Already, the current models of AI, not necessarily the ones that you purchase&lt;br&gt;
or that you just get through the retail ChatGPT, but the more advanced models&lt;br&gt;
that are available now to companies, they can code better than, let’s call it&lt;br&gt;
60%-70% of coders.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Barack Obama&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you believe that, it's better to stop reading this article. Don't waste your time. AI is a useful assistant that helps us work much faster — true. But it’s not a replacement. Of course, the way we work has changed. We need fewer people focused solely on typing out code without understanding the bigger picture. Instead, we need more people who can design systems, think at a higher level about components, understand system architecture, follow programming best practices, and still be able to fix deep issues in AI-generated code.&lt;/p&gt;

&lt;p&gt;I’m sure you’ve already heard of &lt;a href="https://en.wiktionary.org/wiki/vibe_coder" rel="noopener noreferrer"&gt;vibe coders&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Someone who generates code by repeatedly prompting a large language model,&lt;br&gt;
and has a very limited awareness of how the code actually functions&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This new approach — with its endless &lt;a href="https://www.index.dev/blog/vibe-coding-ai-development" rel="noopener noreferrer"&gt;loop&lt;/a&gt; of&lt;br&gt;
&lt;code&gt;prompt → generation → testing &amp;amp; refinement&lt;/code&gt; — wastes a lot of time, patience, nerves, and money if used with "very limited awareness." I got stuck in this loop myself. It just doesn’t work. However, I’ve been coding effectively with AI tools for a while now and seem to have found a more concise way to program with AI — one that doesn’t lead to frustration.&lt;/p&gt;

&lt;p&gt;So, I’d like to share several ideas that I use regularly and that work in most cases. I hope they’ll save you time and money — and definitely speed up your development process. But this requires much more focus and — surprise, surprise — programming skills.&lt;/p&gt;
&lt;h2&gt;
  
  
  Idea
&lt;/h2&gt;

&lt;p&gt;To keep things simple, I’ll explain the entire process using a small example in Go. Let’s begin with the idea behind the issue or task — whatever it may be. Suppose we need to parse a YAML configuration file that contains some information about an AI model we’re going to use in our application.&lt;/p&gt;

&lt;p&gt;As a developer, you recognise that you’ll need something capable of retrieving specific values from this config file. Let’s express that through an interface:&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;type&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GetModel&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="kt"&gt;error&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;Notice that there’s no AI involved yet (though you could ask the AI to generate the interface as well). There’s no implementation either. The key point is to clearly define what you want to achieve in the end. This is the best way to explain the task formally. In my experience, the AI understands such definitions much better than plain English.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test
&lt;/h2&gt;

&lt;p&gt;Now, instead of diving into implementation details straight away, we can use an ancient technique — Test-Driven Development (&lt;a href="https://en.wikipedia.org/wiki/Test-driven_development" rel="noopener noreferrer"&gt;TDD&lt;/a&gt;). Surprisingly, this approach helps in two important ways. First, it gives us a test that will validate our future implementation. Second, it provides a clear hint to the AI about what we want to implement.&lt;/p&gt;

&lt;p&gt;Most well-known AI tools can help generate such tests. For example, in &lt;a href="https://aider.chat" rel="noopener noreferrer"&gt;aider&lt;/a&gt;, you can use the &lt;code&gt;/add config.go&lt;/code&gt; command to add our interface, and then prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generate unit tests for a Config interface. Assume the implementation will load configuration from a YAML file. The tests should simulate YAML-based input and validate that the interface handles it correctly.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(In &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;Copilot&lt;/a&gt;, you can use the &lt;code&gt;/tests&lt;/code&gt; command for the same purpose — no prompt required.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a result, the AI will generate something like this:&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;const&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;`
default-model: 4o
models:
  4o:
    model-id: gpt-4o
`&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestGetModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MkdirTemp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"configtest"&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoveAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/config.yml"&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;0644&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;YamlConf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;model&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;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetModel&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;t&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;"Expected no error, got %v"&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;model&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"gpt-4o"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                                                                                                                                                                           
       &lt;span class="n"&gt;t&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;"Expected model ID 'gpt-4o', got %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&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;Of course, the compiler will warn us that the &lt;code&gt;YamlConf&lt;/code&gt; implementation is missing. We can generate an empty implementation using &lt;a href="https://www.jetbrains.com/help/go/generating-code.html" rel="noopener noreferrer"&gt;IDE capabilities&lt;/a&gt;, write it manually, or ask the AI to create a skeleton for us.&lt;/p&gt;

&lt;p&gt;Again, we don’t have a real implementation yet — just tests and a placeholder. At this point, we need to &lt;strong&gt;review&lt;/strong&gt; all the generated test cases. We might adjust our expectations, tweak the constructor, or modify test values. By doing this, we provide the AI with as many concrete clues as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Now we’re ready to ask the AI to implement the interface. This part is simple. All we need to do is mention both the interface and the tests in the AI prompt and request an implementation.&lt;/p&gt;

&lt;p&gt;And voilà — we get a simple but functional result:&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;type&lt;/span&gt; &lt;span class="n"&gt;YamlConfig&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Models&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="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="s"&gt;`yaml:"models"`&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;YamlConf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;YamlConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;configData&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&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="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;var&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;YamlConfig&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;yaml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configData&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;config&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="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;config&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;YamlConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetModel&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="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="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultModel&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Models&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;"model-id"&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;As always, you need to &lt;strong&gt;review&lt;/strong&gt; the generated code. Think of yourself as a code reviewer checking the work of a junior developer: the AI can assist, but you must ensure the implementation is correct. Moreover, since we are generating code in small and stable chunks, the review process is fairly straightforward.&lt;/p&gt;

&lt;p&gt;During the review, you might notice that some tests fail or that the code has flaws like duplication or inefficiencies that could be improved. In most cases, these fixes are minor and quicker to apply manually. However, nothing stops you from asking the AI for help. For example, you can simply paste the test failure message into the prompt — no extra wording required. It will understand you based on the previous context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Quality
&lt;/h2&gt;

&lt;p&gt;As you may have noticed — or perhaps not — there are a few flaws in our generated code. Actually, I didn’t spot them myself at first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config/yamlconfig_test.go:97:17: Error return value of `os.WriteFile` is not checked (errcheck)
    os.WriteFile(path, []byte(data), 0644)
                ^
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I noticed this issue only after running a &lt;a href="https://en.wikipedia.org/wiki/Lint_(software)" rel="noopener noreferrer"&gt;linter&lt;/a&gt;. Sometimes we’re not familiar with the tricky edge cases or conventions of a particular language. A convenient way to catch and fix such issues — including formatting, styling, and even some security problems — is to use &lt;a href="https://en.wikipedia.org/wiki/Lint_(software)" rel="noopener noreferrer"&gt;linters&lt;/a&gt;. For example, you can use &lt;a href="https://github.com/golangci/golangci-lint" rel="noopener noreferrer"&gt;golangci-lint&lt;/a&gt; for Go, &lt;a href="https://github.com/eslint/eslint" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; for JavaScript, and &lt;a href="https://github.com/pylint-dev/pylint" rel="noopener noreferrer"&gt;Pylint&lt;/a&gt; for Python. In fact, almost every widely used programming language has its own linter or code quality tool. Linters are especially helpful when generating code with AI — they help keep your code clean and safe, at least to some degree.&lt;/p&gt;

&lt;p&gt;Once again, we can either fix these issues manually or ask the AI to do it for us. There’s no need for a detailed prompt — just copy and paste the warning message. The AI will understand it. &lt;code&gt;aider&lt;/code&gt; even has a special &lt;code&gt;/lint&lt;/code&gt; &lt;a href="https://aider.chat/docs/usage/commands.html" rel="noopener noreferrer"&gt;command&lt;/a&gt; for this exact scenario.&lt;/p&gt;

&lt;p&gt;By the way, there’s another important aspect of code quality to consider: conventions and preferred libraries. Some teams — or you, personally — may follow specific practices. For example, instead of checking values in tests with plain Go &lt;code&gt;if&lt;/code&gt; statements:&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;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;t&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;"Expected no error, got %v"&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;model&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"gpt-4o"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                                                                                                                                                                           
  &lt;span class="n"&gt;t&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;"Expected model ID 'gpt-4o', got %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&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;I prefer to use the Go library &lt;a href="https://github.com/stretchr/testify" rel="noopener noreferrer"&gt;testify&lt;/a&gt;, which significantly simplifies the 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="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&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="s"&gt;"Error should be nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"gpt-4o"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Model ID should match"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, we could rewrite our tests to use &lt;code&gt;testify&lt;/code&gt;, but doing so every time we generate a test would be tedious. And unnecessary — this problem is already solved.&lt;/p&gt;

&lt;p&gt;You can define a configuration file (called &lt;a href="https://aider.chat/docs/usage/conventions.html" rel="noopener noreferrer"&gt;conventions&lt;/a&gt; in aider, or &lt;a href="https://docs.cursor.com/context/rules" rel="noopener noreferrer"&gt;rules&lt;/a&gt; in Cursor) to instruct the AI on your preferred coding practices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; Use the &lt;span class="sb"&gt;`testify`&lt;/span&gt; library (&lt;span class="sb"&gt;`github.com/stretchr/testify`&lt;/span&gt;) for all Go tests.
&lt;span class="p"&gt;-&lt;/span&gt; Prefer &lt;span class="sb"&gt;`assert`&lt;/span&gt; and &lt;span class="sb"&gt;`require`&lt;/span&gt; from &lt;span class="sb"&gt;`testify`&lt;/span&gt; over Go's standard &lt;span class="sb"&gt;`testing`&lt;/span&gt; assertions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removes the burden of constantly rewriting and rephrasing the same prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do We Really Need to Write Tests First?
&lt;/h2&gt;

&lt;p&gt;At this point, we've already discussed the core development loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface -&amp;gt; test -&amp;gt; implementation -&amp;gt; code quality
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But do we really need to write the test first? Although I personally believe it's the fastest way to reach working code, you can adjust the process to suit your needs. For example, you might ask the AI to generate an implementation skeleton &lt;em&gt;before&lt;/em&gt; writing the test — this helps avoid compiler errors early on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface -&amp;gt; implementation (empty) -&amp;gt; test -&amp;gt; implementation (real) -&amp;gt; code quality
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For some people, this approach may work better. In reality, the key principle behind all of these steps is to keep the context you're working with as small as possible — no matter which steps you put first. Don’t add the entire application to the AI’s context, and don’t try to solve the entire problem at once — that’s a path to nowhere. You’ll likely spend more time fixing large blocks of AI-generated code than if you’d built it up gradually, piece by piece.&lt;/p&gt;

&lt;p&gt;Keep in mind: even though the AI has its own context, &lt;strong&gt;so do we&lt;/strong&gt;. And since we must constantly review the generated code, keeping the scope small benefits us too. This way, you're more likely to review everything carefully, which leads to greater confidence and a more enjoyable development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I encourage you to embrace AI, but don’t be a vibe coder. Be an experienced developer — or even an architect — who treats AI as a tool to speed up the development process. Don’t think of it as a replacement for your expertise. Just integrate it effectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use interfaces and method signatures as formal requirements.&lt;/strong&gt;
This gives the AI a clear structure to work from and guides it toward generating the code you actually need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate tests extensively.&lt;/strong&gt;
Tests not only improve code quality but also help better understand the task. They also give the AI clearer objectives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be focused and concise.&lt;/strong&gt;
Avoid overloading the AI with unnecessary context. The more you add, the more money you spend, the more cluttered and unpredictable the output becomes — and the more time you'll spend cleaning it up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always review the changes.&lt;/strong&gt;
AI is not perfect; it makes mistakes all the time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use linters to fix code style and catch subtle issues.&lt;/strong&gt;
They’re incredibly helpful — especially when generating code with AI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s also worth noting that a solid understanding of the AI tools you use will make a big difference. Learn the available commands, modes, supported models, and prompt techniques. There’s always room for improvement and customisation to fit your specific workflow.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>softwaredevelopment</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
