<?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: Nevena</title>
    <description>The latest articles on DEV Community by Nevena (@nevpetda).</description>
    <link>https://dev.to/nevpetda</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%2F3675023%2F3f9da5ea-9aa1-49c9-b446-21ad260f8226.png</url>
      <title>DEV Community: Nevena</title>
      <link>https://dev.to/nevpetda</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nevpetda"/>
    <language>en</language>
    <item>
      <title>Stop Fixing Kubectl Typos: Let an AI Agent Handle It</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Mon, 20 Apr 2026 09:54:05 +0000</pubDate>
      <link>https://dev.to/nevpetda/stop-fixing-kubectl-typos-let-an-ai-agent-handle-it-42fb</link>
      <guid>https://dev.to/nevpetda/stop-fixing-kubectl-typos-let-an-ai-agent-handle-it-42fb</guid>
      <description>&lt;p&gt;What happens if you let an AI read your Kubernetes docs and actually run the commands? Eugene Kiselev, an engineer at &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt&lt;/a&gt;, tried a small experiment: an AI agent scans a messy k8s lab, extracts commands, runs them in a real cluster, fixes errors, and rewrites the docs. The result shows how small and large models behave in real conditions, where they fail, and how a tiny agent can act like a junior engineer keeping labs clean and working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab Environment
&lt;/h2&gt;

&lt;p&gt;To test the idea, I acted as a k8s instructor and created a set of simple labs covering core tasks: creating, scaling, and exposing deployments. Each lab includes up to 20 commands with deliberate typos, wrong flags, labels, and namespaces.&lt;/p&gt;

&lt;p&gt;K8s labs are well-suited for this kind of experiment. The environment is safe, so if something goes wrong, I just delete the K3D cluster and start over in under a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;A small LLM isn't reliable enough to handle the full workflow. The tool is split into components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Command extraction&lt;/li&gt;
&lt;li&gt;Syntax validation&lt;/li&gt;
&lt;li&gt;Execution in k8s&lt;/li&gt;
&lt;li&gt;Stderr analisys&lt;/li&gt;
&lt;li&gt;Iterative fixing based on the results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond syntax errors, the agent also checks that the lab remains logically correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach and Constraints
&lt;/h2&gt;

&lt;p&gt;No CrewAi or LangChain here. I drew inspiration from articles like Docker in Bash and Docker in Ruby, where engineers took a simple approach to rebuilding enterprise tools. I kept that same spirit here, using plain prompts, Python, and local models.&lt;/p&gt;

&lt;p&gt;And yes, I know that Cursor, Antigravity, and Claude can do this. But for me, this is a fun experiment, and the goal is to integrate the tool into a pipeline, not an IDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extraction: Small Ollama-Hosted Models
&lt;/h2&gt;

&lt;p&gt;I started small with &lt;strong&gt;Gemma 3:1B&lt;/strong&gt;, a model running on Ollama on my MacBook. The goal: parse the lab's commands and see what happens. I wrote a simple extraction prompt and ran the extractor against the smallest model.  It was fast and cheap, and my MacBook stayed cool. Here are the results from three runs.&lt;/p&gt;

&lt;p&gt;====================================================&lt;/p&gt;

&lt;p&gt;Iter  | Cmds  | Curl?  | JSON?  | Lat (s)  | Tokens&lt;/p&gt;




&lt;p&gt;1     | 10    | True   | True   | 7.92     | 583  &lt;/p&gt;

&lt;p&gt;2     | 9     | True   | True   | 6.75     | 544  &lt;/p&gt;

&lt;p&gt;3     | 8     | False  | True   | 7.06     | 575  &lt;/p&gt;

&lt;p&gt;====================================================&lt;/p&gt;

&lt;p&gt;The results were messy. With this level of determinism, prompt-based fixing isn't reliable. We'll need some help from &lt;strong&gt;Qwen8b&lt;/strong&gt;. Unfortunately, Qwen just cooked my MacBook for seven minutes and didn't give me anything useful.&lt;/p&gt;

&lt;p&gt;On to &lt;strong&gt;Gemma 3:4B&lt;/strong&gt;. The difference is like night and day: the model identified 16 out of 16 commands across multiple iterations with no syntax errors. It was slower (about 27 seconds instead of 7). Still, the 4B version handled tricky tasks that the smaller model missed, such as escaping nested JSON strings in kubectl patch commands and spotting environment variable dependencies like export NODE_PORT. And this was without adjusting temperature or top_k settings.&lt;/p&gt;

&lt;p&gt;====================================================&lt;/p&gt;

&lt;p&gt;Iter  | Cmds  | Curl?  | JSON?  | Lat (s)  | Tokens&lt;/p&gt;




&lt;p&gt;1     | 16    | True   | True   | 28.51    | 1237 &lt;/p&gt;

&lt;p&gt;2     | 16    | True   | True   | 27.44    | 1202 &lt;/p&gt;

&lt;p&gt;3     | 16    | True   | True   | 27.18    | 1183 &lt;/p&gt;

&lt;p&gt;==================================================&lt;/p&gt;

&lt;p&gt;Cool? Yes, kind of.&lt;/p&gt;

&lt;p&gt;The next day, I tried extraction again with a tougher prompt, and the model struggled. It was still consistent, but I only got 12 out of 16 right. LLMs, like people, have good and bad days. Keep that in mind!&lt;/p&gt;

&lt;p&gt;Let’s set the temperature to 0, to make it less "creative”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"num_predict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"top_k"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"top_p"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After I shortened the output and switched to one-shot parsing, the results became consistent again.&lt;/p&gt;

&lt;p&gt;=====================================================&lt;/p&gt;

&lt;p&gt;Iter  | Cmds  | Curl?  | JSON?  | Lat (s)  | Tokens&lt;/p&gt;




&lt;p&gt;1     | 16    | True   | True   | 29.72    | 1310 &lt;/p&gt;

&lt;p&gt;2     | 16    | True   | True   | 27.95    | 1310 &lt;/p&gt;

&lt;p&gt;3     | 16    | True   | True   | 27.94    | 1310 &lt;/p&gt;

&lt;p&gt;===================================================&lt;/p&gt;

&lt;p&gt;So, 4b looks like it can work grep | wc -l, and gather the commands from the lab. But is it doing the job correctly?&lt;/p&gt;

&lt;p&gt;When I introduced intentional errors like &lt;strong&gt;depolments&lt;/strong&gt; and &lt;strong&gt;-o wede&lt;/strong&gt;, the model fixed the typos on its own and returned the correct commands. That’s impressive, but it doesn’t solve the documentation validation problem.&lt;/p&gt;

&lt;p&gt;Giving the model a clear instruction in the prompt helped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. **LITERAL COMMAND EXTRACTION**: You are a copy-paste robot. Extract commands EXACTLY as they appear, including all typos. DO NOT FIX THEM.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did it actually work? Since the model is deterministic, I ran it a few more times to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab 1
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Target (Typo/Error in Lab)&lt;/th&gt;
&lt;th&gt;Run 1 Status&lt;/th&gt;
&lt;th&gt;Run 2 Status&lt;/th&gt;
&lt;th&gt;Run 3 Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sca.le (dot typo)&lt;/td&gt;
&lt;td&gt;FAIL (ID missed)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;Unstable focus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;depolyment (typo)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;Stable (expected behavior)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-o json_path (underscore)&lt;/td&gt;
&lt;td&gt;FAIL (fixed to jsonpath)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;Inconsistent auto-fixing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;items[0] → items[*]&lt;/td&gt;
&lt;td&gt;FAIL (corrupted)&lt;/td&gt;
&lt;td&gt;FAIL (corrupted)&lt;/td&gt;
&lt;td&gt;FAIL (corrupted)&lt;/td&gt;
&lt;td&gt;Systemic Hallucination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nginx-deployments (plural)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;Stable (expected behavior)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Lab 2
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature / Target&lt;/th&gt;
&lt;th&gt;Run 1 Status&lt;/th&gt;
&lt;th&gt;Run 2 Status&lt;/th&gt;
&lt;th&gt;Run 3 Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;crete (typo)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;Perfect literal extraction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deploymenst (typo)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;SUCCESS (preserved)&lt;/td&gt;
&lt;td&gt;Perfect literal extraction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment Export&lt;/td&gt;
&lt;td&gt;FAIL (skipped)&lt;br&gt;missed export command&lt;/td&gt;
&lt;td&gt;FAIL (skipped)&lt;br&gt;missed export command&lt;/td&gt;
&lt;td&gt;FAIL (skipped)&lt;br&gt;missed export command&lt;/td&gt;
&lt;td&gt;Systemic Context Loss&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-command Blocks&lt;/td&gt;
&lt;td&gt;FAIL (filtered)&lt;br&gt;missed two commands&lt;/td&gt;
&lt;td&gt;FAIL (filtered)&lt;br&gt;missed two commands&lt;/td&gt;
&lt;td&gt;FAIL (filtered)&lt;br&gt;missed two commands&lt;/td&gt;
&lt;td&gt;Semantic Filtering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Lab2 is a bit larger and, surprisingly, more stable, but still not quite there. It deterministically drops commands from multicommand blocks, picking only what it thinks is most important, and keeps only the kubectl part from commands like export XXX | kubectl YYY.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extraction: Big Models
&lt;/h2&gt;

&lt;p&gt;Poor extraction hurts the process, no matter how good the next model is. Even clear instructions can be missed by small models. Time to bring in the big guns: Claude or Gemini.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini3-flash-preview&lt;/strong&gt; from AI Studio gave good results and parsed everything correctly. It followed the prompt and kept the output as-is.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Command Extracted&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Extraction Strategy&lt;/th&gt;
&lt;th&gt;Logic Preservation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1–2&lt;/td&gt;
&lt;td&gt;cluster-info, get nodes&lt;/td&gt;
&lt;td&gt;SUCCESS&lt;/td&gt;
&lt;td&gt;Atomic: Split one block into 2 entries.&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3–5&lt;/td&gt;
&lt;td&gt;crete, deploymenst, get pods&lt;/td&gt;
&lt;td&gt;SUCCESS&lt;/td&gt;
&lt;td&gt;Literal: Preserved typos crete and deploymenst.&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;jsonpath='{.spec.type}'&lt;/td&gt;
&lt;td&gt;SUCCESS&lt;/td&gt;
&lt;td&gt;Exact: No attempt to "fix" syntax.&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;export NODE_PORT=$(...)&lt;/td&gt;
&lt;td&gt;SUCCESS&lt;/td&gt;
&lt;td&gt;Contextual: Recognized export as a vital command.&lt;/td&gt;
&lt;td&gt;Perfect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;curl -I ...$NODE_PORT&lt;/td&gt;
&lt;td&gt;SUCCESS&lt;/td&gt;
&lt;td&gt;Dependency: Kept the variable usage intact.&lt;/td&gt;
&lt;td&gt;Perfect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;get pods ... -o wede&lt;/td&gt;
&lt;td&gt;SUCCESS&lt;/td&gt;
&lt;td&gt;Literal: Preserved wede typo.&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15–16&lt;/td&gt;
&lt;td&gt;get svc, get endpoints&lt;/td&gt;
&lt;td&gt;SUCCESS&lt;/td&gt;
&lt;td&gt;Atomic: Did not filter out "verification" steps.&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's the main point: a small model without fine-tuning or clear instructions is a poor parser. It ignores instructions and outputs what's statistically likely rather than what's actually in the text. Even if it knows kubectl syntax well, it's not a reliable extractor. For better results, use a larger model. Gemini-flash is fast, cheap, and good enough for this. The task doesn’t require deep reasoning; just a model that can follow instructions over a medium-sized context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax Validation: Small Ollama-hosted Models
&lt;/h2&gt;

&lt;p&gt;Now it gets interesting.  We have a JSON file from Gemini3 with the extracted commands. Let's run syntax checks and see if the model can spot simple typos and handle tougher cases like wrong labels or missing namespaces.&lt;/p&gt;

&lt;p&gt;A simple one-shot attempt showed that the model is good at finding and fixing typos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"fix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl create deployment nginx-demo --image=nginx:stable"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Typo: 'crete' should be 'create'"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"fix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl get deployment nginx-demo"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Typo: 'deploymenst' should be 'deployment'"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s exactly what I wanted. But the results aren’t consistent across all runs and error types. Here’s what happened in a second test:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error Category&lt;/th&gt;
&lt;th&gt;Original Input&lt;/th&gt;
&lt;th&gt;Model Response&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;Analysis&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Command Typo&lt;/td&gt;
&lt;td&gt;crete deployment&lt;/td&gt;
&lt;td&gt;crete deployment&lt;/td&gt;
&lt;td&gt;FAILED / PARTIAL&lt;/td&gt;
&lt;td&gt;Identified as INVALID, but the fix was identical to the error.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource Typo&lt;/td&gt;
&lt;td&gt;get deploymenst&lt;/td&gt;
&lt;td&gt;get deployment&lt;/td&gt;
&lt;td&gt;PASSED&lt;/td&gt;
&lt;td&gt;Correctly identified and fixed the typo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alias Handling&lt;/td&gt;
&lt;td&gt;patch svc&lt;/td&gt;
&lt;td&gt;VALID&lt;/td&gt;
&lt;td&gt;PASSED&lt;/td&gt;
&lt;td&gt;Recognized svc as a legitimate alias for service.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flag Value&lt;/td&gt;
&lt;td&gt;--replicas=-1&lt;/td&gt;
&lt;td&gt;--replicas=1&lt;/td&gt;
&lt;td&gt;FAILED (Over-fix)&lt;/td&gt;
&lt;td&gt;Performed a logical fix instead of a syntax audit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output Format&lt;/td&gt;
&lt;td&gt;-o wede&lt;/td&gt;
&lt;td&gt;(Skipped / Ignored)&lt;/td&gt;
&lt;td&gt;FAILED&lt;/td&gt;
&lt;td&gt;Completely missed the typo in the output flag.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I have intentionally added a specific case to test model limitations. This is what I have in the test lab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;"kubectl create deployment fail-demo --image=nginx --replicas=-1"&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has replicas -1, which is obviously incorrect, and the model is smart enough to see this. But it doesn't know the correct value: 1, 2, or 11. The model should flag it, not fix it. Gemma corrected it to 1 anyway. The command works, but that's not the point.&lt;/p&gt;

&lt;p&gt;When I changed the prompt to separate syntax fixes from semantic ones, the results became inconsistent. The model can’t reliably distinguish between them.&lt;/p&gt;

&lt;p&gt;Small models try to help even when it's not needed, a bit like our helpful relatives. We can’t trust their guesses, so it’s time to use larger models again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax Validation: Big Models
&lt;/h2&gt;

&lt;p&gt;When asked to correct syntax, the big model found typos during extraction without any specific prompting. In the expected outcome field, it is already noted:&lt;/p&gt;

&lt;p&gt;"expected_outcome": "Attempts to create a deployment; will fail due to typo 'crete'."&lt;/p&gt;

&lt;p&gt;In other words, it extracts and validates syntax simultaneously, something larger models do well.&lt;/p&gt;

&lt;p&gt;This changes the setup. Instead of using several validators, we can let Gemini extract and validate, then run the commands in the cluster and check the results. For labs in the 5–8K token range, big models handle this just fine.&lt;/p&gt;

&lt;p&gt;We’re going from complicated:&lt;/p&gt;

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

&lt;p&gt;to simple:&lt;/p&gt;

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

&lt;p&gt;The updated output includes intent, suggested fix, and original text for full context:&lt;/p&gt;

&lt;p&gt;The model successfully grabbed the commands, suggested fixes, and correctly provided the user's intent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl crete deployment nginx-demo --image=nginx:stable"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"suggested_fix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl create deployment nginx-demo --image=nginx:stable"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"original_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"## Step 1: Create Nginx Deployment&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Create a basic Nginx deployment to serve as the backend for our services.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;# Create the deployment"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"intent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Create a deployment named nginx-demo using the nginx:stable image."&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"expected_outcome"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[WILL_FAIL] The verb 'crete' is a typo. Kubernetes will return 'Unknown command'."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks good, but LLMs can be confidently wrong, so validation is still necessary.&lt;/p&gt;

&lt;p&gt;It helps to have the LLM take on another role and check the results of the first step. I asked Gemini Flash to act as a quality assurance lead and review the work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### ROLE
Infrastructure Quality Assurance Lead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Sonnet would be the best choice here, since it’s known for handling these tasks well. But Claude isn't available in Google's free AI studio, and Anthropic doesn't offer a similar free option, so I used Gemini Flash again.&lt;/p&gt;

&lt;p&gt;The results are promising.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Gemini&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;completed:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;19.43&lt;/span&gt;&lt;span class="err"&gt;s,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Tokens:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5772&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"missing_commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On cost, this call was free under AI Studio's free tier, but at market rate, it would run about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input cost: Approximately $0.0008658
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, if we have to validate several labs twice a month, it's possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent: The Tools that Will Run the Commands.
&lt;/h2&gt;

&lt;p&gt;The extractor works, and the validator checks its output. Now it‘s time to create a real agent. The component that will execute commands one by one, read the result, and suggest a fixed command if something went wrong. For the first iteration, we won't implement complex retries or chains. The basic architecture is the following.&lt;/p&gt;

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

&lt;p&gt;To make things more interesting, I introduced not only syntax errors but also logical ones. Which I expect will need some effort.&lt;/p&gt;

&lt;p&gt;Take lab1:Some commands are missing the namespace key. The command itself is valid, but it fails because it runs in the wrong namespace.&lt;/p&gt;

&lt;p&gt;The expected behavior for an agent to add the missing "create ns" command, and a -n flag for all commands where it's not presented.  It's a bit more complex than just fixing typos, so let's see. As an alternative, I expect the agent to cut corners and remove the -n flag, using the default namespace for everything. We'll use prompting to steer it away from that shortcut.&lt;/p&gt;

&lt;p&gt;Here's the full list of errors in lab 1:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error Category&lt;/th&gt;
&lt;th&gt;Specific Token / Issue&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Reference (ID)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Syntax (Typo)&lt;/td&gt;
&lt;td&gt;depolyment&lt;/td&gt;
&lt;td&gt;Typo in the Kubernetes resource noun.&lt;/td&gt;
&lt;td&gt;#3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syntax (Typo)&lt;/td&gt;
&lt;td&gt;sca.le&lt;/td&gt;
&lt;td&gt;Illegal character (dot) within the kubectl verb.&lt;/td&gt;
&lt;td&gt;#6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syntax (Flag)&lt;/td&gt;
&lt;td&gt;-o json_path&lt;/td&gt;
&lt;td&gt;Incorrect flag naming; used an underscore instead of the standard jsonpath.&lt;/td&gt;
&lt;td&gt;#8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logical (Namespace)&lt;/td&gt;
&lt;td&gt;Missing &lt;code&gt;-n test&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Command is valid, but targets the default namespace instead of the previously created test environment.&lt;/td&gt;
&lt;td&gt;#4, #7, #9, #10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logical (Pre-requisite)&lt;/td&gt;
&lt;td&gt;Namespace not found&lt;/td&gt;
&lt;td&gt;Attempting to create a deployment in a namespace that doesn't exist yet.&lt;/td&gt;
&lt;td&gt;#3 (Attempt 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logical (Selector)&lt;/td&gt;
&lt;td&gt;app=nginx-deployments&lt;/td&gt;
&lt;td&gt;Misalignment between the label defined in the deployment and the label used in the query (plural vs. singular).&lt;/td&gt;
&lt;td&gt;#12&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To guide the agent toward the right fixes (for example, add namespace, not delete -n flag), the following rules were added to the prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### STRATEGIC RULES

1. **Contextual Continuity**: Resources in Kubernetes are scoped (Namespaced or Clustered). Analyze the Execution History to identify the scope where target resources were previously managed. Ensure the fixed command operates within that same scope.

2. **Environmental Pre-requisites**: If a command fails due to a missing environmental object (as indicated by STDERR), prepend necessary commands to establish the required state before executing the main task.

3. **Syntax Integrity**: Correct structural errors, misspellings of subcommands, or malformed flags while strictly preserving the logic defined in the Target Intent.

4. **Selector Alignment**: For commands involving filtering (labels, selectors), cross-reference the history to ensure identifiers match those of the actual resources in the cluster.

5. **Minimal Disruption**: Do not modify values (images, replicas, names) that are syntactically correct and aligned with the Target Intent, even if the command failed for other reasons.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For namespace and label issues, the agent can't work atomically and relies solely on the command's execution result. The LLM should know that the namespace was previously created, and that the commands already have the -n test flag added.&lt;/p&gt;

&lt;p&gt;The LLM should know that during the previous step, a pod named CAT was created, so verifying pod DOG is wrong. For small labs, feeding the full execution history works. To save tokens, passing only the last successful commands is enough. Providing everything risks the model getting confused and trying to fix its own previous fixes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It's not worth using a local model here because the context is too complex. The model needs to know the command, the intent, what's broken, and what happened before. That's too much for a small 4B model.&lt;/p&gt;

&lt;p&gt;And let's finally run it and see what will happen. The agent created the namespace, fixed the typo, deployed, and added the -n flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;"original_command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl create depolyment nginx-deployment --image=nginx:1.14.2 -n test"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"attempts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl create deployment nginx-deployment --image=nginx:1.14.2 -n test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error: failed to create deployment: namespaces &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; not found"&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl create namespace test &amp;amp;&amp;amp; kubectl create deployment nginx-deployment --image=nginx:1.14.2 -n test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"stdout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"namespace/test created&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;deployment.apps/nginx-deployment created"&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"semantic_verification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Verified: Command executed successfully."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even better, the agent started adding -n test to all subsequent commands that were missing the flag. It also fixed other issues.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl get pods -l app=nginx-deployment -o jsonpath='{.items[0].spec.containers[0].image}'"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"failed"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error: error executing jsonpath &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;{.items[0].spec.containers[0].image}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: Error executing template: array index out of bounds: index 0, length 0. Printing more information for debugging the template:&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s2"&gt;template was:&lt;/span&gt;&lt;span class="se"&gt;\n\t\t&lt;/span&gt;&lt;span class="s2"&gt;{.items[0].spec.containers[0].image}&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s2"&gt;object given to jsonpath engine was:&lt;/span&gt;&lt;span class="se"&gt;\n\t\t&lt;/span&gt;&lt;span class="s2"&gt;map[string]interface {}{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;apiVersion&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;v1&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;items&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:[]interface {}{}, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;kind&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;List&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;metadata&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:map[string]interface {}{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;resourceVersion&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"\"&lt;/span&gt;&lt;span class="s2"&gt;}}"&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl get pods -l app=nginx-deployment -n test -o jsonpath='{.items[0].spec.containers[0].image}'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"stdout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nginx:1.14.2"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And handled rate limits correctly.&lt;/p&gt;

&lt;p&gt;One case that both the extraction and fixer parts missed is 14.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl get pods -l app=nginx-deployment -o jsonpath='{.items[*].spec.containers[0].image}'"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"stdout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I mentioned earlier, the command ran “successfully” in the wrong namespace, where there was nothing to fix. This fix doesn't need an LLM: if a get or describe command returns no output with a zero exit code, route it to the fixer. This simple logic change works. For more complex scenarios, a semantic validation layer that queries the cluster and verifies the command actually did what it was supposed to do would help, but that's out of scope for this agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Security
&lt;/h2&gt;

&lt;p&gt;At the end of execution, something unexpected happened:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kubectl get deployments nginx-deployment"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"failed"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error from server (NotFound): deployments.apps &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;nginx-deployment&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; not found"&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error: 429 You exceeded your current quota, please check your plan and billing details. For more information on this error, head to: https://ai.google.dev/gemini-api/docs/rate-limits. To monitor your current usage, head to: https://ai.dev/rate-limit. &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* Quota exceeded for metric: generativelanguage.googleapis.com/generate_content_free_tier_requests, limit: 20, model: gemini-3-flash&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Please retry in 26.365091249s. [links {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  description: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Learn more about Gemini API quotas&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;  url: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;https://ai.google.dev/gemini-api/docs/rate-limits&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;, violations {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  quota_metric: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;generativelanguage.googleapis.com/generate_content_free_tier_requests&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;  quota_id: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;GenerateRequestsPerDayPerProjectPerModel-FreeTier&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;  quota_dimensions {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    key: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;    value: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;gemini-3-flash&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;  }&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  quota_dimensions {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    key: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;location&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;    value: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;global&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s2"&gt;  }&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  quota_value: 20&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;, retry_delay {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  seconds: 26&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/bin/sh: Error:: command not found&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;/bin/sh: line 1: __pycache__: command not found&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;/bin/sh: line 2: Please: command not found&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;/bin/sh: line 3: description:: command not found&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;/bin/sh: line 4: url:: command not found&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;/bin/sh: -c: line 5: syntax error near unexpected token `}'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;/bin/sh: -c: line 5: `}'"&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One more answer to the question &lt;strong&gt;"What happens when I let an LLM generate output and have the agent run commands on my cluster?”&lt;/strong&gt; I expected missed syntax errors and odd attempts, but this time something else happened.&lt;/p&gt;

&lt;p&gt;AI Studio hit a limit, and the agent took the error message and tried to run it as a shell command. Luckily, it wasn’t something dangerous like rm -rf /, so it was just funny, but we need to be careful. The agent should have a validation layer. The simplest way is to use a strict whitelist of allowed commands. Anything else gets dropped with a warning. For this test, I used a clean, small, and isolated K3D cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing the Docs
&lt;/h2&gt;

&lt;p&gt;After validating and fixing the commands, the last step is updating the docs. We should get the results, regenerate the lab, have fixes in place, warnings where the agent can't help, and expect human intervention. I used Gemini again, and it worked well. It had the list of correct commands, the fixed commands, and the original lab markdown file, and made careful replacements.&lt;/p&gt;

&lt;p&gt;To prevent the model from getting creative, I gave Gemini one job: act as a "sophisticated sed". No new content, no rewrites, just make precise replacements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### STRATEGIC RULES
1. **Precision Replacement**: Locate the exact code blocks containing failing commands. Replace the content of those code blocks with the verified successful command(s).
2. **Preserve Context**: Do not change the surrounding text, headers, or explanations in the Markdown document unless they directly conflict with the new command logic.
3. **Markdown Integrity**: Ensure the final output is a valid Markdown document with correctly formatted code blocks.
4. **Minimal Disruption**: Only modify the commands that were identified as fixed. Successful original commands should remain untouched.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks like it successfully fixed errors and saved the corrected lab to the right place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;docs-validator diff labs/lab1.md labs/lab1_fixed.md
&lt;/span&gt;&lt;span class="gd"&gt;&amp;lt; kubectl create depolyment nginx-deployment --image=nginx:1.14.2 -n test
&lt;/span&gt;&lt;span class="p"&gt;---
&lt;/span&gt;&lt;span class="gi"&gt;&amp;gt; kubectl create namespace test &amp;amp;&amp;amp; kubectl create deployment nginx-deployment --image=nginx:1.14.2 -n test
&lt;/span&gt;&lt;span class="p"&gt;17,18c17,18
&lt;/span&gt;&lt;span class="gd"&gt;&amp;lt; kubectl get deployments nginx-deployment
&amp;lt; kubectl get pods -l app=nginx-deployment -o jsonpath='{.items[0].spec.containers[0].image}'
&lt;/span&gt;&lt;span class="p"&gt;---
&lt;/span&gt;&lt;span class="gi"&gt;&amp;gt; kubectl get deployments nginx-deployment -n test
&amp;gt; kubectl get pods -l app=nginx-deployment -n test -o jsonpath='{.items[0].spec.containers[0].image}'
&lt;/span&gt;&lt;span class="p"&gt;25c25
&lt;/span&gt;&lt;span class="gd"&gt;&amp;lt; kubectl sca.le deployment nginx-deployment --replicas=2
&lt;/span&gt;&lt;span class="p"&gt;---
&lt;/span&gt;&lt;span class="gi"&gt;&amp;gt; kubectl scale deployment nginx-deployment --replicas=2 -n test
&lt;/span&gt;&lt;span class="p"&gt;28,29c28,29
&lt;/span&gt;&lt;span class="gd"&gt;&amp;lt; kubectl get deployments nginx-deployment
&amp;lt; kubectl get pods -l app=nginx-deployment -o json_path='{.items[0].spec.containers[0].image}'
&lt;/span&gt;&lt;span class="p"&gt;---
&lt;/span&gt;&lt;span class="gi"&gt;&amp;gt; kubectl get deployments nginx-deployment -n test
&amp;gt; kubectl get pods -l app=nginx-deployment -n test -o jsonpath='{.items[0].spec.containers[0].image}'
&lt;/span&gt;&lt;span class="p"&gt;36c36
&lt;/span&gt;&lt;span class="gd"&gt;&amp;lt; kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
&lt;/span&gt;&lt;span class="p"&gt;---
&lt;/span&gt;&lt;span class="gi"&gt;&amp;gt; kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 -n test
&lt;/span&gt;&lt;span class="p"&gt;39,41c39,41
&lt;/span&gt;&lt;span class="gd"&gt;&amp;lt; kubectl rollout status deployment/nginx-deployment
&amp;lt; kubectl get deployments nginx-deployment
&amp;lt; kubectl get pods -l app=nginx-deployments -o jsonpath='{.items[0].spec.containers[0].image}'
&lt;/span&gt;&lt;span class="p"&gt;---
&lt;/span&gt;&lt;span class="gi"&gt;&amp;gt; kubectl rollout status deployment/nginx-deployment -n test
&amp;gt; kubectl get deployment nginx-deployment -n test
&amp;gt; kubectl get pods -l app=nginx-deployment -n test -o jsonpath='{.items[0].spec.containers[0].image}'
&lt;/span&gt;&lt;span class="p"&gt;49c49
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't a magic "fix everything" tool. But it's a working concept, at least for simple tasks. Those that don't need deep thinking, just someone (or something) to add -n test to every kubectl command. We don’t let agents commit directly to main, but there’s no reason they can’t open a merge request for a human to review.&lt;/p&gt;

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

&lt;p&gt;This isn’t a complete solution, but it proves the concept.&lt;/p&gt;

&lt;p&gt;After a few weekends of coding and testing, here’s my verdict. This "baby agent," built without heavy frameworks or complex graphs, can already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extract&lt;/strong&gt; commands from messy Markdown with high reliability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-fix&lt;/strong&gt; syntax errors on the fly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolve&lt;/strong&gt; logical/contextual issues (~80% success rate) by "remembering" the environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regenerate&lt;/strong&gt; corrected labs for human review, closing the feedback loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free up&lt;/strong&gt; engineer time for more interesting tasks (like building a better agent) instead of manual toil.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, the scenarios are simple for now, and there aren't many commands. We still have issues like 'Semantic Silence' and rate-limit errors to fix. And hitting the quota reminded me again: &lt;strong&gt;never unquestioningly trust an agent; always check its output&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But despite the "duct tape and rust" (as seen in my engine model), it actually works. It’s not about building a perfect machine from the start; it’s about making something that can fail, learn, and recover. And honestly, it’s just a lot of fun.&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://linkly.link/2hAxA" rel="noopener noreferrer"&gt;DataArt's Team blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ai</category>
      <category>devops</category>
      <category>python</category>
    </item>
    <item>
      <title>5 Beginner Python Books Worth Reading</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Wed, 15 Apr 2026 07:49:26 +0000</pubDate>
      <link>https://dev.to/nevpetda/5-beginner-python-books-worth-reading-4jeo</link>
      <guid>https://dev.to/nevpetda/5-beginner-python-books-worth-reading-4jeo</guid>
      <description>&lt;p&gt;Python is one of the most popular programming languages today, especially in the age of AI. Below are five highly rated Python books that offer strong fundamentals, practical experience, and clear explanations for anyone starting out or strengthening their grasp of the basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://www.amazon.com/Python-Programming-Absolute-Beginner-3rd/dp/1435455002" rel="noopener noreferrer"&gt;Python Programming for the Absolute Beginner&lt;/a&gt; by Michael Dawson
&lt;/h2&gt;

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

&lt;p&gt;As the title suggests, this book is built for readers with no previous programming experience. The third edition includes updated content and expanded coverage for modern Python features.&lt;/p&gt;

&lt;p&gt;It starts with core fundamentals and gradually introduces more complex topics, including data structures, file handling, exceptions, object-oriented programming, and graphics. Visual examples and step-by-step explanations keep the learning curve manageable. By the end, you'll be able to build your own games from scratch using Python!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; True beginners who want a structured, confidence-building introduction.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://www.amazon.com/Python-Crash-Course-2nd-Edition/dp/1593279280" rel="noopener noreferrer"&gt;Python Crash Course&lt;/a&gt; by Eric Matthes
&lt;/h2&gt;

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

&lt;p&gt;This book offers a hands-on introduction to Python for beginners eager to start writing useful code quickly.&lt;/p&gt;

&lt;p&gt;Along the way, you'll work with libraries and tools such as Pygame, Matplotlib, Plotly, and Django. Core concepts, including variables, lists, classes, and loops, are covered early through engaging exercises. Later chapters guide you through building interactive programs, testing code, and developing a 2D arcade-style Space Invaders game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Learners who want to move fast and learn through building.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://automatetheboringstuff.com/" rel="noopener noreferrer"&gt;Automate The Boring Stuff With Python&lt;/a&gt; by Al Sweigart
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft86c5uoz2fmm7gxpzm0w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft86c5uoz2fmm7gxpzm0w.jpg" alt="Automate The Boring Stuff With Python" width="800" height="1060"&gt;&lt;/a&gt;&lt;br&gt;
This best-selling book teaches Python 3 through practical examples, making it ideal for beginners.&lt;/p&gt;

&lt;p&gt;You'll learn how to write programs that automate repetitive tasks, saving hours of manual work like file processing, data manipulation, and basic web interactions. Once you grasp the basics, you'll be able to build scripts that handle useful automation jobs with ease.&lt;/p&gt;

&lt;p&gt;The book covers both basic and advanced data structures. Each chapter includes an introduction, a case study, tips, key library methods, and exercises to reinforce learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Beginners motivated by immediate, real-world use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://www.amazon.com/Head-First-Python-Brain-Friendly-Guide/dp/1492051292" rel="noopener noreferrer"&gt;Head-First Python&lt;/a&gt; by Paul Barry
&lt;/h2&gt;

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

&lt;p&gt;Known for its visual and interactive style, this book is a popular choice for quickly learning Python basics, including built-in functions and data structures. It covers the basics first, then builds toward more advanced topics, such as creating web applications, handling exceptions, and others.&lt;/p&gt;

&lt;p&gt;Author Paul Barry, a lecturer at the Institute of Technology in Carlow, Ireland, brings over a decade of IT industry experience to his teaching, which is evident in his clear explanations and approachable tone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Visual learners who prefer a less traditional textbook format.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://www.informit.com/store/learn-python-the-hard-way-9780138270575" rel="noopener noreferrer"&gt;Learn Python the Hard Way&lt;/a&gt; by Zed Shaw
&lt;/h2&gt;

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

&lt;p&gt;This book takes an exercise-driven approach, covering key topics like organizing code, math, variables, loops, logic, packaging, automated testing, and game development.&lt;/p&gt;

&lt;p&gt;Guided through 52 exercises designed to be typed out manually, you’ll learn by doing and correcting your own mistakes. You'll gain a solid understanding of how programs work, learn how to read and write code, and develop effective debugging skills.&lt;/p&gt;

&lt;p&gt;An additional &lt;a href="https://learncodethehardway.com/courses/free-support-course/" rel="noopener noreferrer"&gt;free support course&lt;/a&gt; is available through the author's website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Learners who prefer repetition and learning through trial and error.&lt;/p&gt;

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

&lt;p&gt;Each of these five books offers practical ways to learn Python, each from a different angle, whether through structured lessons, hands-on projects, automation tasks, or disciplined practice. Choosing the right one depends on how you learn best and what you want to build. Pick the one that fits your goals, stay consistent, and start coding!&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt's&lt;/a&gt; &lt;a href="https://linkly.link/2gWQI" rel="noopener noreferrer"&gt;Team blog&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>learning</category>
      <category>books</category>
    </item>
    <item>
      <title>Code Testing Fundamentals: How to Do It Right</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Mon, 09 Mar 2026 09:00:01 +0000</pubDate>
      <link>https://dev.to/nevpetda/code-testing-fundamentals-how-to-do-it-right-pef</link>
      <guid>https://dev.to/nevpetda/code-testing-fundamentals-how-to-do-it-right-pef</guid>
      <description>&lt;p&gt;&lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt's&lt;/a&gt; Senior Developer Alexey Klimenko explains why testing matters and how to approach it in practice. This guide covers core concepts, test types, working strategies, best practices, and a risk-based mindset to help teams make testing a natural part of engineering culture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do We Need Tests?
&lt;/h2&gt;

&lt;p&gt;Testing often gets buried under buzzwords: coverage, reports, pipelines, TDD debates. Strip that away, and the idea is simple. &lt;strong&gt;Tests exist to give us confidence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A clear testing strategy delivers tangible benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher product quality, with fewer production bugs and hidden issues&lt;/li&gt;
&lt;li&gt;Fewer regressions, reducing stress when shipping new features&lt;/li&gt;
&lt;li&gt;Lower long-term costs, since refactoring and fixes become safer and faster&lt;/li&gt;
&lt;li&gt;Reduced business risk from broken core flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In essence, tests create a safety net. They make growth possible without turning every change into a gamble.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Test Types:
&lt;/h3&gt;

&lt;p&gt;Instead of memorizing labels, it helps to look at testing from three perspectives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By &lt;strong&gt;level&lt;/strong&gt; — what exactly we're testing&lt;/li&gt;
&lt;li&gt;By &lt;strong&gt;approach&lt;/strong&gt; — how we write and run the tests&lt;/li&gt;
&lt;li&gt;By &lt;strong&gt;goal&lt;/strong&gt; — what this particular test is meant to cover&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  By Level: From Unit to E2E (End-to-End)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unit Tests
&lt;/h3&gt;

&lt;p&gt;Unit tests validate small, isolated pieces of logic: functions, utilities, methods.&lt;/p&gt;

&lt;p&gt;A good unit test is fast, independent of the database/network/timing, and focused on a specific behavior.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// utils/calcDiscount.js
export function calcDiscount(price, percent) {
  if (percent &amp;lt; 0 || percent &amp;gt; 100) {
    throw new Error('Invalid percent');
  }
  return price - (price * percent) / 100;
}

// calcDiscount.test.js (Jest)
import { calcDiscount } from './calcDiscount';

describe('calcDiscount', () =&amp;gt; {
  it('applies percentage discount', () =&amp;gt; {
    expect(calcDiscount(100, 10)).toBe(90);
  });

  it('throws on invalid percent', () =&amp;gt; {
    expect(() =&amp;gt; calcDiscount(100, 150)).toThrow('Invalid percent');
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Component Tests
&lt;/h2&gt;

&lt;p&gt;Component tests focus on UI components in isolation: different props, states, and events.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// components/Counter.jsx
export const Counter = ({ initial = 0 }) =&amp;gt; {
  const [value, setValue] = React.useState(initial);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;span aria-label="value"&amp;gt;{value}&amp;lt;/span&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setValue(value + 1)}&amp;gt;+&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

// Counter.test.jsx (React Testing Library + Jest)
import { render, screen, fireEvent } from '@testing-library/react';
import { Counter } from './Counter';

it('increments value when user clicks plus', () =&amp;gt; {
  render(&amp;lt;Counter initial={1} /&amp;gt;);

  const value = screen.getByLabelText('value');
  const button = screen.getByText('+');

  expect(value).toHaveTextContent('1');

  fireEvent.click(button);
  expect(value).toHaveTextContent('2');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Integration Tests
&lt;/h2&gt;

&lt;p&gt;Integration tests verify how multiple modules of the system work together: controller + validator, component + API(mocked).&lt;/p&gt;

&lt;p&gt;Example (a hypothetical service + external client):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// services/userService.js
export async function createUser(userData, { userRepo, emailService }) {
  const user = await userRepo.save(userData);
  await emailService.sendWelcome(user.email);
  return user;
}

// userService.integration.test.js
import { createUser } from './userService';

it('creates user and sends welcome email', async () =&amp;gt; {
  const savedUsers = [];
  const sentEmails = [];

  const userRepo = {
    save: async (userData) =&amp;gt; {
      savedUsers.push(userData);
      return { id: 1, ...userData };
    },
  };

  const emailService = {
    sendWelcome: async (email) =&amp;gt; {
      sentEmails.push(email);
    },
  };

  const result = await createUser(
    { email: 'test@example.com' },
    { userRepo, emailService }
  );

  expect(result.id).toBe(1);
  expect(savedUsers).toHaveLength(1);
  expect(sentEmails).toContain('test@example.com');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  E2E (End-to-End) Tests
&lt;/h2&gt;

&lt;p&gt;This is the whole user journey through the system: from the UI down to the database and back. E2E tests are more expensive and slower to maintain, but they give us tremendous confidence that real-world scenarios actually work.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// e2e/checkout.spec.js
import { test, expect } from '@playwright/test';

test('user can buy a product', async ({ page }) =&amp;gt; {
  await page.goto('https://my-shop.example');

  await page.getByText('Fancy Mug').click();
  await page.getByRole('button', { name: 'Add to cart' }).click();
  await page.getByRole('link', { name: 'Cart' }).click();

  await page.getByRole('button', { name: 'Checkout' }).click();
  await page.getByLabel('Card number').fill('4242 4242 4242 4242');
  await page.getByLabel('Expiry').fill('12/30');
  await page.getByLabel('CVC').fill('123');

  await page.getByRole('button', { name: 'Pay' }).click();

  await expect(page.getByText('Thank you for your purchase')).toBeVisible();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  By Approach: How Tests Are Created
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Manual Vs. Automated
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Manual&lt;/strong&gt; — a tester/developer goes through scenarios by hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated&lt;/strong&gt; — scenarios are written as code and run in CI.&lt;/p&gt;

&lt;p&gt;Manual testing isn't going anywhere, but as a project grows, having an automated "safety layer" becomes increasingly valuable.&lt;/p&gt;

&lt;h3&gt;
  
  
  TDD (Test-Driven Development)
&lt;/h3&gt;

&lt;p&gt;TDD follows a simple loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write a failing test (&lt;strong&gt;red&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Write the minimum amount of code to pass the test (&lt;strong&gt;green&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Remove duplication / clean up the code (&lt;strong&gt;refactor&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  BDD (Behavior-Driven Development)
&lt;/h3&gt;

&lt;p&gt;BDD focuses on a shared understanding of how the system should behave.&lt;/p&gt;

&lt;p&gt;BDD-style tests do not have to be a formal BDD process with lots of meetings and Gherkin files. You can use the approach partially, simply as a convenient way to keep your focus on behavior.&lt;/p&gt;

&lt;p&gt;Key ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We talk in terms of &lt;strong&gt;behavior&lt;/strong&gt;, not implementation details&lt;/li&gt;
&lt;li&gt;We use the &lt;strong&gt;Given/When/Then&lt;/strong&gt; structure&lt;/li&gt;
&lt;li&gt;Scenarios are understandable to developers, QA, analysts, and business people&lt;/li&gt;
&lt;li&gt;Tests become a form of &lt;strong&gt;living documentation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# cart.feature
Feature: Shopping cart
Scenario: User can add an item to the cart. Given the user is on the shop page and the cart is empty
    When the user adds an item to the cart
    Then the cart shows "1 item in cart"

import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from '@playwright/test';

Given('the user is on the shop page', async function () {
  await this.page.goto('https://my-shop.example');
});

Given('the cart is empty', async function () {
  // reset the basket state, e.g. ensure it's empty
});

When('the user adds an item to the cart', async function () {
  await this.page.getByText('Add to cart').click();
});

Then('the cart shows {string}', async function (text) {
  await expect(this.page.getByText(text)).toBeVisible();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exploratory Testing
&lt;/h3&gt;

&lt;p&gt;It relies on curiosity: &lt;em&gt;what happens if…?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rapidly switching between tabs to see if the UI breaks&lt;/li&gt;
&lt;li&gt;Clicking a button 10 times a second&lt;/li&gt;
&lt;li&gt;Entering unexpected values&lt;/li&gt;
&lt;li&gt;Killing the network&lt;/li&gt;
&lt;li&gt;Reloading the page in the middle of a request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exploratory testing often identifies bugs that formal test scenarios miss entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  By Goal: What Is Being Validated
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Functional Testing
&lt;/h3&gt;

&lt;p&gt;We check &lt;strong&gt;what&lt;/strong&gt; the system does. Common categories include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Boundary&lt;/strong&gt; — test edge cases and limits (e.g., min/max values, “just below/just above” a limit, Input limit is 10 characters → testing 9, 10, 11)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regression&lt;/strong&gt; — ensure existing functionality still works (e.g., new feature added → old flow still works)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smoke&lt;/strong&gt; — quick “does it run at all?” check (e.g., you fixed payment modal → check app loads, login works, basic flows still function)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sanity&lt;/strong&gt; — quick validation of a specific fix or feature (e.g., you fixed the payment modal → check only the payment modal behavior)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Non-Functional Testing
&lt;/h3&gt;

&lt;p&gt;Here, the focus is on &lt;strong&gt;how&lt;/strong&gt; the system behaves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt; — speed, load, response times&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt; — vulnerabilities, permissions, attacks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usability&lt;/strong&gt; — how easy it is to use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A11y (Accessibility)&lt;/strong&gt; — screen readers, keyboard navigation, contrast, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compatibility&lt;/strong&gt; — different browsers/devices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt; — stability over long runs, restarts, and network issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Specialized Test Types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Snapshot Testing
&lt;/h3&gt;

&lt;p&gt;Snapshot tests compare a saved version of the UI/DOM to the current one. They're handy for components.&lt;/p&gt;

&lt;p&gt;Example (Jest + React Testing Library):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Button.test.jsx
import { render } from '@testing-library/react';
import { Button } from './Button';

it('renders primary button', () =&amp;gt; {
  const { container } = render(&amp;lt;Button variant="primary"&amp;gt;Click me&amp;lt;/Button&amp;gt;);
  expect(container.firstChild).toMatchSnapshot();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Visual Regression/Screenshot Testing
&lt;/h3&gt;

&lt;p&gt;Tools like Playwright or Storybook can compare screenshots pixel-by-pixel. For example, you can see if a button moved after a CSS change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutation Testing
&lt;/h3&gt;

&lt;p&gt;Tools like Stryker deliberately “break” your code (e.g., change operators or conditions) and check whether your tests can catch it. The idea is simple: if you can break business logic and the tests are still green, the quality of your tests is low — even if coverage is high.&lt;/p&gt;

&lt;p&gt;Why so many classifications if, in the end, we are just checking that everything works? Separations are needed not for the sake of theory, but for the sake of risk, time, and cost management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why So Many Test Categories
&lt;/h2&gt;

&lt;p&gt;The goal is not theory. It is risk management.&lt;/p&gt;

&lt;p&gt;In real projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time is limited&lt;/li&gt;
&lt;li&gt;Money is limited&lt;/li&gt;
&lt;li&gt;Risks vary&lt;/li&gt;
&lt;li&gt;There are many changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, testing is divided into types to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What needs to be tested deeply&lt;/li&gt;
&lt;li&gt;What can be tested quickly&lt;/li&gt;
&lt;li&gt;What can be tested superficially&lt;/li&gt;
&lt;li&gt;What must be tested after changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reducing Flaky Tests
&lt;/h2&gt;

&lt;p&gt;Flaky tests (sometimes red, sometimes green with no code changes) destroy trust in your test suite.&lt;/p&gt;

&lt;p&gt;To reduce instability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use stable test environments&lt;/li&gt;
&lt;li&gt;Control your data (fixtures, factory functions)&lt;/li&gt;
&lt;li&gt;Isolate from unstable external services (mocks/fakes)&lt;/li&gt;
&lt;li&gt;Make tests deterministic (fake timers, control randomness)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FIRST Principles of Good Tests
&lt;/h2&gt;

&lt;p&gt;Strong tests usually follow the &lt;strong&gt;FIRST&lt;/strong&gt; model:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fast&lt;/strong&gt; — the test runs quickly&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independent&lt;/strong&gt; — doesn't depend on other tests&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repeatable&lt;/strong&gt; — gives the same result in any environment&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-checking&lt;/strong&gt; — validates itself (green/red) without manual log inspection&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timely&lt;/strong&gt; — written at the right time (not a year after the feature was implemented)&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Testing Realities
&lt;/h2&gt;

&lt;p&gt;⭐ &lt;strong&gt;Bugs are inevitable&lt;/strong&gt;&lt;br&gt;
The goal of testing is not to "prove there are no bugs", but to reduce the risk of serious problems. We test not because someone writes bad code, but because errors are a natural part of software development.&lt;/p&gt;

&lt;p&gt;⭐ &lt;strong&gt;You can't test everything&lt;/strong&gt;&lt;br&gt;
The space of possible inputs and scenarios is infinite. So, you have to make choices. We must choose what to test based on importance and risk, rather than attempting to cover everything.&lt;/p&gt;

&lt;p&gt;⭐ &lt;strong&gt;Adopt a risk-based mindset&lt;/strong&gt;&lt;br&gt;
Focus your testing effort on areas that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Break most often&lt;/li&gt;
&lt;li&gt;Are critical for the business&lt;/li&gt;
&lt;li&gt;Are complex and challenging to understand&lt;/li&gt;
&lt;li&gt;Have tricky integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Testing is an investment. We put more effort into areas where failure would be costly.&lt;/p&gt;

&lt;p&gt;⭐ &lt;strong&gt;The pesticide paradox&lt;/strong&gt;&lt;br&gt;
If you keep running the same set of tests, they eventually stop finding new bugs, like pests getting used to the same poison. Your test suite needs to be updated and expanded periodically. Tests must be reviewed and improved regularly; otherwise, they become noise and lose their value.&lt;/p&gt;

&lt;p&gt;⭐ &lt;strong&gt;Quality is a team responsibility&lt;/strong&gt;&lt;br&gt;
It's not "the QA’s job" or "whoever writes tests". Architecture decisions, deadlines, scope, and attitude to technical debt all affect quality. Everyone (Dev, QA, PM, DevOps) contributes to product quality, so testing decisions and responsibilities must be shared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coverage: What Do 80% Actually Mean?
&lt;/h2&gt;

&lt;p&gt;Coverage (line/function coverage) is often turned into a KPI. But it’s important to remember: &lt;strong&gt;Coverage ≠ test quality&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can have 90% coverage and still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never test boundary values&lt;/li&gt;
&lt;li&gt;Fail to catch real bugs&lt;/li&gt;
&lt;li&gt;Ignore important branches in conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use coverage to identify blind spots:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Untested modules&lt;/li&gt;
&lt;li&gt;Untouched code paths&lt;/li&gt;
&lt;li&gt;Rare scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For many projects, &lt;strong&gt;70–90%&lt;/strong&gt; is reasonable, but what really matters is what exactly is being tested, not the number itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing as Part of Engineering Culture
&lt;/h2&gt;

&lt;p&gt;Testing is not a luxury or a "nice-to-have if there's time left". It's part of the engineering discipline.&lt;/p&gt;

&lt;p&gt;When the team has a basic understanding of the types of tests available, what value they bring, and how to think about coverage and risk, you can start arguing about details like Jest/Vitest, Cypress/Playwright, and how many E2E tests are needed.&lt;/p&gt;

&lt;p&gt;But the foundation is the same: &lt;strong&gt;Testing = Engineering discipline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Treat testing as risk management, not bureaucracy. Teams that adopt this mindset ship faster, break less, and release with confidence.&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://linkly.link/2dXrD" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>engineeringculture</category>
      <category>softwaretesting</category>
      <category>testautomation</category>
    </item>
    <item>
      <title>RASP: The Silent Ninja Handling the Threats You Don’t See</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Mon, 23 Feb 2026 08:24:07 +0000</pubDate>
      <link>https://dev.to/nevpetda/rasp-the-silent-ninja-handling-the-threats-you-dont-see-42pg</link>
      <guid>https://dev.to/nevpetda/rasp-the-silent-ninja-handling-the-threats-you-dont-see-42pg</guid>
      <description>&lt;p&gt;&lt;em&gt;What is RASP, and why does it matter? &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt's&lt;/a&gt; Security Engineer, Kirill Chsheglov, explains this in-app security technology, compares leading commercial solutions, and examines what the open-source OpenRASP project brings to the table.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is RASP?
&lt;/h2&gt;

&lt;p&gt;RASP (Runtime Application Self-Protection) is a security technology that runs inside an application and protects it in real time. Think of it like a bodyguard that rides along with your app, monitoring activity and stepping in when something suspicious happens.&lt;/p&gt;

&lt;p&gt;Where a traditional WAF (Web Application Firewall) only sees incoming traffic; RASP has full visibility of the app’s internal activity, including function calls, database queries, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does it Matter?
&lt;/h2&gt;

&lt;p&gt;Many clients still depend on legacy systems that can't be easily patched. Perimeter tools help, but they often lack context, create noise, or miss threats that unfold within the application itself.&lt;/p&gt;

&lt;p&gt;RASP closes that gap, quietly monitoring and reacting right away when something goes wrong. Unlike WAFs that raise too many alerts, RASP works silently and effectively, like a ninja, calmly whispering: "&lt;em&gt;Relax. I see everything. I've already caught them.&lt;/em&gt;"&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should Clients Turn to RASP?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Don't touch the legacy code, it still works."&lt;/strong&gt; RASP can cover security holes without changing the code, which can be troublesome.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WAF screams, RASP acts.&lt;/strong&gt; Fewer false positives mean fewer alerts and no SOC meltdowns every Friday.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero-day? Stay calm.&lt;/strong&gt; Even without a CVE (Common Vulnerabilities and Exposures), RASP can spot suspicious behavior and stop attacks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attacks have gotten smarter.&lt;/strong&gt; Old perimeter defenses don't help much with microservices, APIs, or serverless—but that's where RASP works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RASP may seem expensive, but it can save millions&lt;/strong&gt; by stopping cyberattacks—for example, in &lt;a href="https://runsafesecurity.com/blog/how-runtime-application-self-protection-can-prevent-cyberattacks-in-oil-gas-environments/" rel="noopener noreferrer"&gt;oil and gas environments&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RASP works in production&lt;/strong&gt;, unlike SAST and DAST, which work before deployment.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, RASP is an in-app security layer that understands context and acts immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leading Commercial Solutions and an Open-Source Option
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.fastly.com/documentation/guides/next-gen-waf/getting-started/about-the-architecture/" rel="noopener noreferrer"&gt;Fastly&lt;/a&gt; employs a hybrid approach, combining edge-level protection with in-app agents. Malicious traffic is filtered globally before reaching your infrastructure. Agents inside the app runtime (Java, .NET, etc.) provide deeper inspection. A central cloud engine manages analytics and rule updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.imperva.com/products/application-security/" rel="noopener noreferrer"&gt;Imperva RASP&lt;/a&gt; offers a lightweight plugin that sits directly inside the application (JVM, .NET, Node.js). It utilizes grammar-based analysis to detect threats at runtime, including zero-day vulnerabilities. With no proxy or network dependencies, it works well for legacy apps or strict environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.contrastsecurity.com/en/contrast-concepts.html" rel="noopener noreferrer"&gt;Contrast&lt;/a&gt; instruments deep code to add security directly into the application flow. By hooking into core runtime APIs (like java.lang.instrumentation), it accesses full stack traces, queries, and execution data to accurately detect and block attacks. Designed for DevOps, it integrates via CI/CD pipelines, containers, and Kubernetes, providing accurate in-app protection with minimal false positives.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/baidu/openrasp" rel="noopener noreferrer"&gt;OpenRASP&lt;/a&gt; is a fully open-source, server-layer solution. It integrates seamlessly into key operations, such as database access, file I/O, and networking, in languages like Java and PHP. With taint-tracking and context analysis, it flags and logs malicious behavior. It's customizable, but requires solid internal development, management, and tuning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Impact
&lt;/h2&gt;

&lt;p&gt;The Fastly RASP engine is built for real-time decision-making, which reduces false positives and &lt;strong&gt;minimizes the impact on web performance&lt;/strong&gt; (See Fastly's &lt;a href="https://learn.fastly.com/rs/025-XKO-469/images/signal-sciences-10-key-capabilities-whitepaper.pdf" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for details).&lt;/p&gt;

&lt;p&gt;Imperva's grammar-based RASP uses formal language parsing to achieve &lt;strong&gt;high detection accuracy with low runtime impact&lt;/strong&gt;. End users won't notice it running (Read the &lt;a href="https://www.imperva.com/resources/datasheets/Runtime-Application-Self-Protection-RASP.pdf" rel="noopener noreferrer"&gt;datasheet&lt;/a&gt; for more information).&lt;/p&gt;

&lt;p&gt;Contrast Protect reports that &lt;strong&gt;80% of requests incur a latency of under 0.5ms&lt;/strong&gt;, with 96% processed within a few milliseconds, matching or outperforming similar WAF solutions (See more at Contrast Security's &lt;a href="https://www.contrastsecurity.com/glossary/waf-vs-rasp" rel="noopener noreferrer"&gt;glossary&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;What do these tools have in common? RASP doesn't just protect, it does so quietly, blending into production like it was always there.&lt;/p&gt;

&lt;h2&gt;
  
  
  When RASP Makes Sense?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You run &lt;strong&gt;high-value web apps or APIs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;runtime protection&lt;/strong&gt; while fixing complex issues.&lt;/li&gt;
&lt;li&gt;You want &lt;strong&gt;real visibility into production threats&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Reading
&lt;/h2&gt;

&lt;p&gt;Check out the following material to learn more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/resources/articles/what-is-rasp" rel="noopener noreferrer"&gt;What is runtime application self-protection (RASP)?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fastly.com/resources/datasheets/security/architecture-and-deployment-overview" rel="noopener noreferrer"&gt;Fastly: Unified web app and API security for any environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fintech.global/cybertechforum/wp-content/uploads/2020/11/Imperva-Guide-To-RASP_Whitepaper_202008.pdf" rel="noopener noreferrer"&gt;Imperva RASP white-paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.contrastsecurity.com/glossary/waf-vs-rasp" rel="noopener noreferrer"&gt;Contrast: WAF vs. RASP Security Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/baidu/openrasp" rel="noopener noreferrer"&gt;OpenRASP GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cyberpandit.org/runtime-application-self-protection-rasp/#google_vignette" rel="noopener noreferrer"&gt;The Power of RASP: Use Cases, Tools, and Benefits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RASP isn’t a silver bullet. But it delivers something traditional tools can’t: a view from inside the application, paired with the ability to act immediately. While WAFs’ perimeter defenses raise alarms, RASP stays focused on stopping the threat at the point where it matters. A silent hero in a noisy world.&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://linkly.link/2bO8Q" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>security</category>
      <category>programming</category>
      <category>fastly</category>
      <category>beginners</category>
    </item>
    <item>
      <title>5 Ancient Lists of Data That Changed the World</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Mon, 09 Feb 2026 10:21:48 +0000</pubDate>
      <link>https://dev.to/nevpetda/5-ancient-lists-of-data-that-changed-the-world-22ci</link>
      <guid>https://dev.to/nevpetda/5-ancient-lists-of-data-that-changed-the-world-22ci</guid>
      <description>&lt;p&gt;&lt;em&gt;The new &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt&lt;/a&gt; Museum project explores millennia of data mastery— from baboon bones to AI brains. For our blog, Alexey Pomigailov, DataArt Museum curator, selected from this remarkable online catalog 5 ancient lists of data that changed the world.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There’s a common myth that data is a 21st-century invention. In reality, data engineering has been around for thousands of years. Our need to record, calculate, and analyze information has always existed. Over the centuries, humans have used records, counts, and tracking to build something bigger than what came before: from notching a baboon bone with a fingernail, to creating the first lists of taxpayers to run ancient empires, to compiling cargo lists to track Viking goods. These early innovations eventually led to punch cards, Excel spreadsheets, online shopping, and even chatting with AI agents today.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Uruk Clay Tablet (Sumer, c. 3200 BCE)
&lt;/h2&gt;

&lt;p&gt;A clay tablet recording barley and malt deliveries for beer production was found in modern-day Iraq. It can be viewed as the birth of &lt;strong&gt;Tabular Data&lt;/strong&gt;. By separating the "label" (malt) from the "value" (quantity) using a grid, Sumerian administrators invented the row-and-column structure. It was the world's first spreadsheet, decoupling data types from data values.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  2. The Pinakes of Callimachus (Alexandria, c. 250 BCE)
&lt;/h2&gt;

&lt;p&gt;A bibliographic registry of the 500,000 scrolls in the Great Library of Alexandria was the invention of &lt;strong&gt;Metadata and Indexing&lt;/strong&gt;. Callimachus, an ancient Greek scholar and librarian, realized that data is useless if it isn't "addressable." He created a system that mapped a logical record (title/author) to a physical location (shelf), the ancient ancestor of the SQL index and the URL.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  3. Nuova Cronica by Giovanni Villani (Florence, c. 1348 CE)
&lt;/h2&gt;

&lt;p&gt;A chronicle of Florence tracked birth rates, grain prices, and mortality during the Black Death. It represents the shift from simple logging to &lt;strong&gt;Descriptive Analytics&lt;/strong&gt;. The Italian chronicler Giovanni Villani didn't just record history; he used statistical data to describe the economic and demographic health of the city, arguably creating the first Business Intelligence report.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  4. Liber Beneficiorum (Krakow, 1470–1480 CE)
&lt;/h2&gt;

&lt;p&gt;Jan Długosz’s "Book of Benefices" is a massive register of church assets and endowments in Poland. As a precursor to &lt;strong&gt;State Statistics and ERP&lt;/strong&gt; (Enterprise Resource Planning), it was a centralized database of decentralized assets, designed to give the "headquarters" (the Diocese) a unified view of geography, economics, and taxation across the region.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  5. The Computus (Medieval Europe, c. 222–1200 CE)
&lt;/h2&gt;

&lt;p&gt;Computus was a system of complex calculations used by the Church to synchronize lunar and solar cycles to determine the date of Easter. It can be viewed as the first &lt;strong&gt;Algorithm&lt;/strong&gt;. Unlike a static lookup table, the Computus required "loops" of logic and conditional processing. It proved that mathematics could govern social time, paving the way for the clock cycles inside every modern CPU.&lt;/p&gt;

&lt;p&gt;Our recent DataArt museum project, &lt;a href="https://retrospect.dataart.com/" rel="noopener noreferrer"&gt;Recount, Sort &amp;amp; Figure Out&lt;/a&gt;, traces the evolution of these concepts and highlights the massive role this technology played in shaping civilization.&lt;/p&gt;

&lt;p&gt;Seen through this lens, you realize that data engineering isn’t new — we just have faster tools. The logic of organizing the world into rows, columns, and addresses is one of humanity’s oldest survival skills. Explore this multi-millennial catalog to see how the art of handling data has shaped culture, technology, and imagination. to see how the art of handling data has shaped culture, technology, and imagination.&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://www.dataart.team/articles/history-of-data-engineering-ancient-data-lists" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>data</category>
      <category>history</category>
      <category>datascience</category>
      <category>dataengineering</category>
    </item>
    <item>
      <title>Preparing for the GCP ACE Exam: What You Should Know</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Mon, 02 Feb 2026 08:49:48 +0000</pubDate>
      <link>https://dev.to/nevpetda/preparing-for-the-gcp-ace-exam-what-you-should-know-52cg</link>
      <guid>https://dev.to/nevpetda/preparing-for-the-gcp-ace-exam-what-you-should-know-52cg</guid>
      <description>&lt;p&gt;&lt;em&gt;Thinking about the GCP Associate Cloud Engineer (ACE) certification? Eugene Kiselev, a seasoned engineer from &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt&lt;/a&gt; with over 13 years of experience in various cloud-related projects, walks you through his preparation process, exam experience, and key takeaways. Here’s what he learned and recommends to anyone planning to take the exam.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Took the ACE Exam
&lt;/h2&gt;

&lt;p&gt;Although I already hold the &lt;strong&gt;GCP Professional Cloud Architect&lt;/strong&gt; (PCA) certification, most of my recent work has focused on AWS or Azure. I still remember the core concepts; those are quite consistent across providers, but I’d lost touch with some of the practical nuances (like the color of some buttons) in the GCP console.&lt;/p&gt;

&lt;p&gt;To refresh that knowledge, I chose the ACE exam. According to the description, it’s a hands-on certification that tests your ability to &lt;strong&gt;manage infrastructure, debug issues&lt;/strong&gt;, and apply best practices, without diving into advanced topics like IoT or advanced ML pipelines. It sticks to the essentials: compute, storage, security, and high availability. It may not focus on GenAI, but it’s still a valuable skill set.&lt;/p&gt;

&lt;p&gt;You may still encounter ML-related scenarios in the questions, simply because that’s the current reality. Yet, the exam focuses on infrastructure, not ML algorithms or pandas code blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling Proctoring: What to Expect
&lt;/h2&gt;

&lt;p&gt;Scheduling the exam in Poland was simple and affordable. One thing I like about Google exams is that you book a specific &lt;strong&gt;time slot&lt;/strong&gt;, not a generic voucher. That suits my approach; by the time I schedule, I’m ready. This is a personal preference, of course. Some people prefer the flexibility of scheduling after payment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro TIP&lt;/strong&gt;: Pay close attention to &lt;strong&gt;AM/PM&lt;/strong&gt;, especially if you’re aiming for a 12:00 slot. Google/Kryterion lets you switch between 12-hour and 24-hour formats, which you can use to double-check your time.&lt;/p&gt;

&lt;p&gt;Google sends multiple email reminders confirming your exam time and date.&lt;/p&gt;

&lt;p&gt;I opted to take the exam &lt;strong&gt;at home&lt;/strong&gt;, but test centers are also available. Prices were identical in my case, so I went with convenience.&lt;/p&gt;

&lt;p&gt;One advantage of test centers is that you won’t risk interruptions due to unstable internet or power issues. Also, test centers tend to be &lt;strong&gt;less strict&lt;/strong&gt; about minor behavior, like briefly looking away from the screen. &lt;em&gt;Likely to wipe away tears — Just kidding, it's not that hard!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Home-based proctoring, on the other hand, is more rigorous. Proctors might ask you to show your surroundings or end a session if they consider your actions suspicious. Reddit is filled with stories of such experiences, so it’s best to be cautious.&lt;/p&gt;

&lt;p&gt;If you choose to take the exam at home:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Prepare a &lt;strong&gt;clean, quiet, private room&lt;/strong&gt; where no one will interrupt you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Before the exam, the proctor will ask you to show your &lt;strong&gt;room, desk, ID,&lt;/strong&gt; &lt;strong&gt;wrists&lt;/strong&gt;, and &lt;strong&gt;glasses&lt;/strong&gt; (if applicable). &lt;strong&gt;Watches&lt;/strong&gt;, &lt;strong&gt;smart glasses&lt;/strong&gt;, or &lt;strong&gt;headphones&lt;/strong&gt; are not allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kryterion now supports &lt;strong&gt;showing the room using your phone&lt;/strong&gt;, which is 100% more convenient than using a laptop camera. You just scan a QR code, and then remove the phone after inspection.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My experience went smoothly: no issues or interventions, no technical problems. I used macOS, installed the testing software, and it worked perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation Materials and Strategy
&lt;/h2&gt;

&lt;p&gt;The official &lt;a href="https://services.google.com/fh/files/misc/associate_cloud_engineer_exam_guide_english.pdf" rel="noopener noreferrer"&gt;exam guide&lt;/a&gt; accurately reflects the topics covered, so I used it as my primary resource. Carefully reading it helped me identify areas for improvement. I &lt;strong&gt;highly recommend&lt;/strong&gt; referring to it throughout your preparation.&lt;/p&gt;

&lt;p&gt;My main study platform was &lt;a href="https://www.skills.google/paths/11" rel="noopener noreferrer"&gt;Cloud Skills Boost&lt;/a&gt; due to the high quality of the lectures. These same lectures are likely available via Coursera as well. Cloud Skills Boost also includes &lt;strong&gt;hands-on labs&lt;/strong&gt;, which are &lt;strong&gt;super important&lt;/strong&gt;. Most labs give you a deep understanding of GCP services, how to operate/administer them, and how to answer tricky exam questions. They also teach best practices, which help you identify correct answers in scenario-based questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP&lt;/strong&gt;: Many questions include several technically correct answers, but only one works in the real world. Practical experience helps you eliminate nonsense quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Topics
&lt;/h2&gt;

&lt;p&gt;While every topic matters, I found certain areas more prominent in the exam:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Billing, Projects, Organizations, and Folders&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Engineers in large companies often don't deal with these directly (especially billing) since dedicated teams handle them. And due to security restrictions, you can't really practice billing on platforms like Cloud Skills Boost. So, I highly recommend &lt;strong&gt;creating your own GCP projects&lt;/strong&gt; and exploring billing configs. You don't need to spin up resources; just work with folders, projects, and IAM policies. It's extremely valuable.&lt;br&gt;
Google provides a nice architecture diagram, so you can try building something similar.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Kubernetes (GKE)
&lt;/h2&gt;

&lt;p&gt;My background includes CKA and CKS certifications and deep Kubernetes experience, so this section was familiar. But the exam questions go beyond the basics. They no longer ask, “What is a Pod?” but focus more on &lt;strong&gt;debugging real-world issues, understanding GKE setups, high availability&lt;/strong&gt;, and &lt;strong&gt;security&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Kubernetes course in the official learning path is a good start, but &lt;strong&gt;not enough on its own&lt;/strong&gt;. I suggest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying more than just a basic Nginx pod. For example, you can build something like the image below. Make sure it works, then update the nginx deployment with a different version of Nginx and finally delete pods and see what will happen. Try to break and fix things. This is extremely valuable for the exam and for everyday work.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Practicing debugging&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using &lt;strong&gt;Minikube&lt;/strong&gt; or &lt;a href="https://killercoda.com/" rel="noopener noreferrer"&gt;Killercoda&lt;/a&gt; for hands-on work. CKA labs in Killercoda is a good level, CKS probably too much&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cloud Run &amp;amp; Cloud Functions
&lt;/h2&gt;

&lt;p&gt;The official learning path didn't cover these extensively, but there are other dedicated courses on the platform.&lt;/p&gt;

&lt;p&gt;For additional preparation, I used the &lt;a href="https://www.linkedin.com/learning/google-cloud-associate-cloud-engineer-cert-prep/google-cloud-platform-associate-cloud-engineer-introduction?u=180332450" rel="noopener noreferrer"&gt;GCA Cloud Engineer Certification Prep course&lt;/a&gt; on LinkedIn Learning. It’s well-structured, comprehensive, and covers gaps in other resources. If you have access to it, it can serve as your main study resource.&lt;/p&gt;

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

&lt;p&gt;What’s great about GCP exams, even practical ones like ACE, is their focus on understanding &lt;strong&gt;concepts&lt;/strong&gt;, rather than memorizing UI details or CLI flags like AZ-104 (sorry, Microsoft). Some questions might seem like that at first, but if you read them carefully, you’ll realize they are testing your comprehension of how things work.&lt;/p&gt;

&lt;p&gt;This means your knowledge won’t become outdated with a UI redesign. Plus, the skills you develop can be easily &lt;strong&gt;transferred to other clouds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The ACE exam is a solid benchmark, if you are comfortable with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Building scalable infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debugging real issues&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analyzing logs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Applying good security and high availability practices&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a certification that rewards hands-on skills, and a worthwhile addition for anyone looking to prove their ability to &lt;strong&gt;solve real-world administrative tasks&lt;/strong&gt; in GCP.&lt;/p&gt;

&lt;p&gt;*This article was initially published on &lt;a href="https://www.dataart.team/articles/google-cloud-associate-cloud-engineer-certification-guide" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>certification</category>
      <category>career</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>From Idea to Prototype in 60 Minutes</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Mon, 26 Jan 2026 11:36:09 +0000</pubDate>
      <link>https://dev.to/nevpetda/from-idea-to-prototype-in-60-minutes-3m29</link>
      <guid>https://dev.to/nevpetda/from-idea-to-prototype-in-60-minutes-3m29</guid>
      <description>&lt;p&gt;&lt;em&gt;How does an idea evolve into a working prototype? Delivery Manager Andrey Sadakov and Product Owner Viktoriya Zinovyeva walk through the process in a recorded webinar and the text below. It’s a practical, step-by-step path from initial concept to prototype. They explain how to develop an MVP, utilizing effective coding practices that enhance development speed, recommend prototyping tools, and introduce semantic annotation.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prototyping Video Demo
&lt;/h2&gt;

&lt;p&gt;Watch the full webinar below or go through the article first.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/Z8k1y_Qp7ww?start=1452"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI Prototyping
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Before AI-assisted development, execution carried most of the weight. Today, AI code generation has lowered that barrier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI helps us generate many ideas quickly, but human judgment still determines which directions are worth exploring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI speeds up development and improves quality, shifting the balance between ideation and execution; close to “implementation is nothing”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prototyping with AI streamlines discovery, requirements gathering, stakeholder alignment, and getting buy-in much faster. You can quickly build and show a prototype to evaluate potential early.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Product Idea
&lt;/h2&gt;

&lt;p&gt;Imagine an app that helps diagnose pain and improve posture by analyzing user photos. It all started with Viktoriya's knee pain. A simple problem led to an idea: a posture analysis app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Shaping the Idea&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The goal is to challenge the initial idea and generate alternatives using different perspectives.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Recommended Model&lt;/strong&gt;: Use a reasoning-focused model for best results&lt;/p&gt;

&lt;p&gt;Instruct the AI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stay neutral and support recommendations with reasoning, pros, and cons for each option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ask about gaps or unclear points.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Present counterarguments when needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide the top three alternative strategies, including trade-offs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List 5-7 questions to answer before moving forward.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Market Research&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This step identifies both supporting and opposing arguments for your chosen option, as well as the assumptions underlying them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Recommended Model&lt;/strong&gt;: Deep research mode&lt;/p&gt;

&lt;p&gt;Include the results from step 1 for context. Then, instruct the LLM to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Offer multiple viewpoints, and flag uncertainty levels where relevant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collect the strongest available evidence for and against each point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identify the five most critical assumptions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the standard flow for market analysis: research competitors, look for signals from customer forums, social posts, and other customer insights. AI is suited to handle these exploratory tasks efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Defining the Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The goal is to design a clear specification for the AI prototyping tool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use the results from step 2 as input to give the full context. Ask for a Product Requirements Document (PRD) tailored to your specific tool (for example, Loveable). Adjust the PRD as needed, including elements such as personas, user stories, and functional requirements.&lt;/p&gt;

&lt;p&gt;Specify the results format:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use clear, simple language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cite pros and cons when suggesting alternatives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep paragraphs short (under 4 lines).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use bulleted lists where they clarify structure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How a Prototype Differs from an MVP
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Prototype&lt;/th&gt;
&lt;th&gt;MVP (Minimum Viable Product)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;To visualize and test ideas quickly, often used for concept validation or stakeholder buy-in&lt;/td&gt;
&lt;td&gt;To validate a product in the market with real users and gather feedback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Functionality&lt;/td&gt;
&lt;td&gt;Simulated or partial functionality; may not be fully operational&lt;/td&gt;
&lt;td&gt;Core, working functionality that delivers actual value to users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Goal&lt;/td&gt;
&lt;td&gt;Demonstrate feasibility, design, or workflow&lt;/td&gt;
&lt;td&gt;Test market demand, usability, and product-market fit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing&lt;/td&gt;
&lt;td&gt;Usability tests, concept validation, internal review&lt;/td&gt;
&lt;td&gt;Live testing with users, real-world data, and customer feedback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk Mitigation&lt;/td&gt;
&lt;td&gt;Reduces design/technical risks early&lt;/td&gt;
&lt;td&gt;Reduces market and business risks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iteration Speed&lt;/td&gt;
&lt;td&gt;Very fast, since it's not fully functional&lt;/td&gt;
&lt;td&gt;Slower than prototypes, but still faster than a full-scale product&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outcome&lt;/td&gt;
&lt;td&gt;Helps decide whether to move forward with building an MVP&lt;/td&gt;
&lt;td&gt;Provides insights for scaling or pivoting to a better product version&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Technical Comparison: Prototype vs MVP
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Prototype&lt;/th&gt;
&lt;th&gt;MVP (Minimum Viable Product)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Code Quality&lt;/td&gt;
&lt;td&gt;Often quick and dirty, may use throwaway code, mockups, or scripts. Not built to scale or maintain.&lt;/td&gt;
&lt;td&gt;Production-grade (even if minimal). Uses maintainable code that can be extended later.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Usually faked (e.g., mocked API responses, static JSON files, or stubs).&lt;/td&gt;
&lt;td&gt;Real backend services, even if basic—often with database, APIs, and authentication.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;May be static screens or interactive mockups with limited or no logic.&lt;/td&gt;
&lt;td&gt;Fully functional UI connected to backend, handling state and real interactions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Usually not deployed; runs locally, in a demo environment, or as design mockups.&lt;/td&gt;
&lt;td&gt;Deployed in production (cloud, app stores, or web), accessible by real users.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Longevity&lt;/td&gt;
&lt;td&gt;Disposable—meant to validate ideas before coding seriously.&lt;/td&gt;
&lt;td&gt;Foundation for future development—can evolve into the whole product.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Quality&lt;/td&gt;
&lt;td&gt;Usually faked (e.g., mocked API responses, static JSON file, or stubs).&lt;/td&gt;
&lt;td&gt;Production-grade (even if minimal). Uses maintainable code that can be extended later.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Vibe Coding Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build iteratively&lt;/strong&gt;. Don’t try to generate an app from a single prompt. Start simple and build up in steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose a standard tech stack&lt;/strong&gt;. LLMs can work with many frameworks, but JavaScript frameworks such as ReactJS, as well as Java or C#, are more reliable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Provide context&lt;/strong&gt;. Share relevant documentation, app functionality, business goals, and technical details. The more context the AI has, the better the results will be. Protocols like MCP help keep documentation up to date.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set coding rules&lt;/strong&gt;. Coding standards vary by language (e.g., JavaScript, NodeJS). Add these rules to prompts to help the AI produce better code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use semantic annotation&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Semantic Annotation
&lt;/h2&gt;

&lt;p&gt;Just as we comment on code and update documentation for others, we use the same principle for AI. Create a readme.md file in markdown to explain your app’s business logic. Add clear comments in the code to describe its purpose, inputs, outputs, and side effects. You can also use XML to annotate the code. This helps AI understand the code's intent, not just how to run it. Use semantic markup to make this easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Tools
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loveable&lt;/strong&gt;: A platform for quickly turning concepts into web applications. Best for creating clickable prototypes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Replit&lt;/strong&gt;: An online IDE with AI features. Balances automation with developer control. Suitable for both speed and functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Local Setup&lt;/strong&gt;: Use Cursor with the Caluse Sonnet model for a hands-on, developer-driven approach. Best for full-scale development.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What to Do Next
&lt;/h2&gt;

&lt;p&gt;With a clear structure and the right tools, anyone can create a prototype. Good documentation and small, well-defined steps make it easier to turn an initial idea into functional products quickly and easily. Start iterating and see where your ideas lead!&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://www.dataart.team/articles/how-to-build-a-prototype-in-an-hour" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>vibecoding</category>
      <category>prototyping</category>
      <category>mvp</category>
    </item>
    <item>
      <title>AI Coding Assistants: Helpful or Harmful?</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Mon, 19 Jan 2026 10:09:36 +0000</pubDate>
      <link>https://dev.to/nevpetda/ai-coding-assistants-helpful-or-harmful-1iol</link>
      <guid>https://dev.to/nevpetda/ai-coding-assistants-helpful-or-harmful-1iol</guid>
      <description>&lt;p&gt;&lt;em&gt;Denis Tsyplakov, Solutions Architect at &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt&lt;/a&gt;, explores the less-discussed side of AI coding agents. While they can boost productivity, they also introduce risks that are easy to underestimate.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a short experiment, Denis asked an AI code assistant to solve a simple task. The result was telling: without strong coding skills and a solid grasp of system architecture, AI-generated code can quickly become overcomplicated, inefficient, and challenging to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Current Situation
&lt;/h2&gt;

&lt;p&gt;People have mixed feelings about AI coding assistants. Some think they’re revolutionary, others don't trust them at all, and most engineers fall somewhere in between: cautious but curious.&lt;/p&gt;

&lt;p&gt;Success stories rarely help. Claims like “My 5-year-old built this in 15 minutes” are often dismissed as marketing exaggeration. This skepticism slows down adoption, but it also highlights an important point: both the benefits and the limits of these tools need a realistic understanding.&lt;/p&gt;

&lt;p&gt;Meanwhile, reputable vendors are forced to compete with hype-driven sellers, often leading to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Drop in quality.&lt;/strong&gt; Products ship with bugs or unstable features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Development decisions driven by hype,&lt;/strong&gt; not user needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unpredictable roadmaps.&lt;/strong&gt; What works today may break tomorrow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Experiment: How Deep Does AI Coding Go?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I ran a small experiment using three AI code assistants: GitHub Copilot, JetBrains Junie, and Windsurf.&lt;/p&gt;

&lt;p&gt;The task itself is simple. We use it in interviews to check candidates’ ability to elaborate on tech architecture. For a senior engineer, the correct approach usually takes about 3 to 5 seconds to give a solution. We’ve tested this repeatedly, and the result is always instant. (&lt;u&gt;&lt;strong&gt;We'll have to create another task for candidates after this article is published&lt;/strong&gt;&lt;/u&gt;.)&lt;/p&gt;

&lt;p&gt;Copilot-like tools are historically strong at algorithmic tasks. So, when you ask them to create an implementation of a simple class with well-defined and documented methods, you can expect a very good result. The problem starts when architectural decisions are required, i.e., on how exactly it should be implemented.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Junie: A Step-by-Step Breakdown
&lt;/h2&gt;

&lt;p&gt;Junie, GitHub Copilot, and Windsurf showed similar results. Here is a step-by-step breakdown for the Junie prompting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 1:&lt;/strong&gt; Implement class logic&lt;/p&gt;

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

&lt;p&gt;The result would not pass a code review. The logic was unnecessarily complex for the given task, but it is generally acceptable. Let’s assume I don't have skills in Java tech architecture and accept this solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 2:&lt;/strong&gt; Make this thread-safe&lt;/p&gt;

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

&lt;p&gt;The assistant produced a technically correct solution. Still, the task itself was trivial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 3:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implement method &lt;code&gt;List&amp;lt;String&amp;gt; getAllLabelsSorted()&lt;/code&gt; that should return all labels sorted by proximity to point [0,0].&lt;/p&gt;

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

&lt;p&gt;This is where things started to unravel. The code could be less wordy. As I mentioned, LLMs excel at algorithmic tasks, but not for a good reason. It unpacks a long into two ints and sorts them each time I use the method. At this point, I would expect it to use a TreeMap, simply because it stores all sorted entries and gives us &lt;strong&gt;O(log n)&lt;/strong&gt; complexity for both inserts and lookups.&lt;/p&gt;

&lt;p&gt;So I pushed further.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 4:&lt;/strong&gt; I do not want to re-sort labels each time the method is called.&lt;/p&gt;

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

&lt;p&gt;OMG!!! Cache!!! What could be worse!?&lt;/p&gt;

&lt;p&gt;From there, I tried multiple prompts, aiming for a canonical solution with a TreeMap-like structure and a record with a comparator (without mentioning TreeMap directly, let's assume I am not familiar with it).&lt;/p&gt;

&lt;p&gt;No luck. The more I asked, the hairier the solution became. I ended up with three screens of hardly readable code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution I was looking for is straightforward:&lt;/strong&gt; it uses specific classes, is thread-safe, and does not store excessive data.&lt;/p&gt;

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

&lt;p&gt;Yes, this approach is opinionated. It has (log(n)) complexity. But this is what I was going to achieve. The problem is that I can get this code from AI only if I know at least 50% of the solution and can explain it in technical terms. If you start using an AI agent without a clear understanding of the desired result, the output becomes effectively random.&lt;/p&gt;

&lt;p&gt;Can AI agents be instructed to use the right technical architecture? You can instruct them to use records, for instance, but you cannot instruct common sense. You can create a &lt;strong&gt;project.rules.md&lt;/strong&gt; file that covers specific rules, but you cannot reuse it as a universal solution for each project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem with AI-Assisted Code
&lt;/h2&gt;

&lt;p&gt;The biggest problem is supportability. The code might work, but its quality is often questionable. Code that’s hard to support is also hard to change. That’s a problem for production environments that need frequent updates.&lt;/p&gt;

&lt;p&gt;Some people expect that future tools will generate code from requirements alone, but that's still a long way off. For now, supportability is what matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Analysis Shows
&lt;/h2&gt;

&lt;p&gt;AI coding assistants can quickly turn your code into an unreadable mess if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instructions are vague.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Results aren’t checked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prompts aren’t finetuned.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That doesn’t mean you shouldn’t use AI. It just means you need to review every line of generated code, which takes strong code-reading skills. The problem is that many developers lack experience with this.&lt;/p&gt;

&lt;p&gt;From our experiments, there’s a limit to how much faster AI-assisted coding can make you. Depending on the language and framework, it can be up to 10-20 times faster, but you still need to read and review the code.&lt;/p&gt;

&lt;p&gt;Code assistants work well with stable, traditional, and compliant code in languages with strong structure, such as Java, C#, and TypeScript. But when you use them with code that doesn’t have strong compilation or verification, things get messy. In other parts of the software development life cycle, like code review, the code often breaks.&lt;/p&gt;

&lt;p&gt;When you build software, you should know in advance what you are creating. You should also be familiar with current best practices (not Java 11, not Angular 12). And you should read the code. Otherwise, even with a super simple task, you will have non-supportable code very fast.&lt;/p&gt;

&lt;p&gt;In my opinion, assistants are already useful for writing code, but they are not ready to replace code review. That may change, but not anytime soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Having all of these challenges in mind, here's what you should focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start using AI assistants where it makes sense.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If not in your main project, experiment elsewhere to stay relevant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review your language specifications thoroughly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improve technical architecture skills through practice.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Used thoughtfully, AI can speed you up. Used blindly, it will slow you down later.&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://www.dataart.team/articles/ai-coding-assistants-helpful-or-harmful" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>programming</category>
      <category>developers</category>
    </item>
    <item>
      <title>The Best and Worst of IT in 2025: Highlights, Scandals, Innovations</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Thu, 15 Jan 2026 14:57:20 +0000</pubDate>
      <link>https://dev.to/nevpetda/the-best-and-worst-of-it-in-2025-highlights-scandals-innovations-1fek</link>
      <guid>https://dev.to/nevpetda/the-best-and-worst-of-it-in-2025-highlights-scandals-innovations-1fek</guid>
      <description>&lt;p&gt;&lt;em&gt;As the new year begins, Andriy Silchuk, &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt’s&lt;/a&gt; Head of R&amp;amp;D Center and Delivery Director, looks back on a turbulent 2025. From defining trends and high-profile scandals to breakthrough innovations and rare bright spots, he recaps what shaped the IT and hi-tech world—and shares his outlook for 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ladies and gentlemen, we’re lucky once again to have made it to the end of the year, so let’s officially tally up the year-end results.&lt;/p&gt;

&lt;p&gt;As before, let’s follow a familiar route: we’ll briefly recall last year's forecasts, then look at the major trends, scandals, the good, and the bad that we all experienced in 2025. We’ll also examine the big names we lost this year, determine the heroes and villains, and recall 2025’s surprises. Then we’ll end the program with our 2026 forecasts.&lt;/p&gt;

&lt;p&gt;So, pour yourself your favorite drink – and let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Brief Look at Last Year’s Forecasts
&lt;/h2&gt;

&lt;p&gt;At the end of 2024, &lt;a href="https://www.dataart.team/articles/the-best-and-worst-of-it-in-2024" rel="noopener noreferrer"&gt;we predicted&lt;/a&gt; that we’d get real AI agents, turbulence in the US IT industry, changing requirements for engineers, "data as oil," and a growing lag between Europe and the United States in 2025.&lt;/p&gt;

&lt;p&gt;What we actually got:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI agents have truly made their way from being the subjects of presentations into full production: ChatGPT agents and a bunch of other tools are already walking around the sites themselves, pressing buttons, executing scripts, and the Linux Foundation is even launching an initiative based on agentic AI standards.&lt;/li&gt;
&lt;li&gt;Turbulence in the United States IT industry hasn’t gone anywhere: antitrust lawsuits against Google/Meta, content wars, regulation — it was all present again this year.&lt;/li&gt;
&lt;li&gt;The requirements for engineers have changed drastically: "I know how to work with AI tools" is now a basic required skill. Big Tech is introducing KPIs for using AI, and those who resist are told to look for a new job.&lt;/li&gt;
&lt;li&gt;Data and infrastructure are truly the "new oil." The problem is not even about data, but about servers, GPUs, memory, and energy — everything is becoming more expensive and scarce.&lt;/li&gt;
&lt;li&gt;Europe has cemented itself as the regulatory champion, with the EU AI Act, record DSA fines for X, etc. In the US, meanwhile, they’re more so debating how to regulate IT, rather than actually doing any regulating.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our predictions were right practically across the board. Not because we’re prophets, but because the trends were blatantly obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four Most popular trends of 2025 (they’re all about AI)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Agency AI: From "chats" to real assistants&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2025 was a turning point: the focus shifted from "generative AI" to agentic AI. ChatGPT agents and similar systems no longer just respond, but also perform tasks themselves—they open websites, monitor statuses, book, write, and edit documents. Businesses are churning out their own agents for support, sales, and back office, DevOps, and domain tasks, and at the same time, a whole zoo of multi-agent frameworks is growing. We've officially gone from "a chat who advises something" to "an assistant who does the job but still needs supervision."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. GEMINI, GPT, CLAUDE and others – a new level of "smartness"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google has finally shown that it’s still alive and very strong, with its Gemini 2.x and 3 models, Nano Banana, and other tools, and deep integration into Search, Android, and Workspace. OpenAI rolled GPT-5/5.1 out of "thinking mode" and made it the default in ChatGPT, effectively dragging a bunch of niche tools under it. Anthropic with Claude 4.5 is seriously putting the pressure on its competitors in coding and reasoning. Meta continues to pump Llama in open source. For the user, it is no longer "one model is better than another", but a whole forest of ecosystems that fight to be your main "superstructure in work." The high level of competition is always in our favor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Data centers as new "capitols" with Heroes 3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The capitol is an extremely necessary thing in Heroes III, but it costs a lot of money. It’s the same with data centers. The IEA and the European Commission predict that data centers already consume about 1.5% of all electricity on the planet, and could double this consumption by 2030, largely due to AI. Energy demand in the United States for data centers jumped 20% year over year, and AI servers are taking an increasing share of capacity. Big Tech is responding in its own style: it’s buying up solar/wind plants, it’s building gas and small nuclear projects, it’s turning old coal-fired power plants into data centers, and its signing contracts for building its own nuclear power plants. Nuclear power plants, Karl!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Regulations, courts, and "AI psychosis"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The EU AI Act has officially started, and DSA is starting to bite with real fines. In the United States, state attorneys general issue warnings to large AI companies about mental health risks. The first lawsuits have appeared where ChatGPT and other models appear in real tragedies — from suicides to murders, where AI allegedly added fuel to the paranoia. Regulation has traditionally lagged behind technology, but politicians and courts are already in play, and 2025 has clearly shown that "it's just a chat" no longer works as an excuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five most high-profile scandals of 2025
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. DeepSeek: China's "nightmare" for the market&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the beginning of 2025, DeepSeek released its models with an embarrassingly low price and pretentious claims about "ridiculous training costs." The market panicked, NVIDIA shares sagged. Then it turns out that everything is not so simple as "cheap" training. The quality of "supermodels" from China took a hit, too. But the shock of just how one release can collapse half the market remains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. X becomes DSA’s first major "patient"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The EU decided to demonstratively apply the Digital Services Act and issued X an estimated $140 million fine for manipulative blue ticking and refusal to provide data for research. This is the first major case DSA in action, and hardly the last. The signal is clear: playing "I do whatever I want" in Europe won’t work anymore, even if you really love freedom of speech in your own interpretation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. TikTok: Banned, then not banned, with an eternal "window for agreement"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The TikTok saga in the US was reminiscent of a soap opera. The law required that either TikTok sell itself to an American owner or leave the market. TikTok defiantly shut down its service in the United States before the deadline, the administration dragged out the time, and then Trump came. He extends the "window for agreements" several times (he’s the master of the “art of the deal,” let's not forget). As a result, bidding continues for a year, names of possible buyers are announced, but they never do get full control — formally everything has been signed, but in reality everyone just pretends to be very busy, and postpones the final steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Google: Antitrust wars and the shadow of selling Chrome&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google is simultaneously focused on several different fronts: dominance in advertising and search, abuse of its mobile platform, and the use of the web to train models. Against this background, there was even a lot of talk and rumors that the company could be forced to sell Chrome, and there was a long queue of those who wanted to buy it. Hyenas can sense blood from far away, as they say. The sale didn’t take place, but the very fact of discussing the sale of the #1 browser shows how tightly Google was squeezed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. OpenAI's exit from Microsoft's influence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenAI and Microsoft are officially "restarting" their partnership: Microsoft remains a large shareholder, but without total control. Azure's exclusivity is being diluted, and some OpenAI services are moving to other clouds. In the end, the companies declare friendship, but in fact they are preparing for a "civilized" departure: OpenAI wants to make decisions on its own and have freedom, while Microsoft wants the right to develop its own AI separately. At least, that's what they say. OpenAI gets certain advantages from separating, that's clear, but what Microsoft will get out of separation is still a question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three most positive events of 2025
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. AI in Medicine: From promises to real-world treatments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2025 was the year when AI in medicine finally showed something more serious and applicable than just promises on paper. Results of clinical trials of AI-developed drugs against cardiovascular and oncological diseases are emerging, and Rentosertib for the treatment of idiopathic pulmonary fibrosis has demonstrated safety and benefits. Furthermore, AI approaches to early diagnosis of cancer and liver diseases are actively developing. This is not yet "AI cured cancer," but real steps in this direction are already being taken.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Quantum Computers: Less hype, more benefit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After years of promises about how cool quantum technology can be, we are slowly but surely moving towards practical applications. New systems like Quantinuum, Helios, and Google Willow show progress in bug correction and stability. It's still expensive and niche, but it looks less and less like PR, and more and more like a long-term bet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Global IT demand comes to life&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;India's IT services exports grew by about 12.5% to $224 billion in fiscal year 2024-25 after several sluggish years. For the industry, this means a simple thing: enterprise money is again used not only for cost optimization, but also for new projects and digitalization. For Ukrainian outsourcing, this means not a direct contract, but a very positive indicator: customers are ready to buy again. If the money returns to India, then it will reach us. &lt;/p&gt;

&lt;h2&gt;
  
  
  Four worst IT news in 2025
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Massive declines in global services&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In October, there was a long-term crash in AWS us-east-1, which in turn “crashed" Slack, Atlassian, Snapchat, and a million more. In November and December there were two big Cloudflare failures, one of which knocked out up to 28% of the world's HTTP traffic. The conclusion is banal, but painful: the Internet is too dependent on several infrastructure players. The words "multi-region/multi-cloud" on presentation slides are not a guarantee of real sustainability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. AI-enhanced cyberattacks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cybercriminals are awake too: tools like PromptLock are emerging, which use generative AI to automate phishing and more complex attacks. The year 2025 saw a series of major leaks and ransomware attacks on energy, logistics, and other critical systems. AI increases the productivity not only of developers, but also of all the "bad guys".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Giant data breaks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Prosper Marketplace in the United States lost the data of 17.6 million people, and the South Korean company Coupang lost another 33.7 million accounts. In total, there are more than 50 million records with names, addresses, documents, and order histories. The reputation of fintech or e-commerce can now be lost in one bad year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Mass layoffs in tech&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;According to TrueUp and other trackers, in 2025, almost 700 waves of layoffs in tech companies took the jobs of more than 200,000 people — an average of 600+ dismissals every day. The headlines are the same again: Amazon, Microsoft, Google, Intel, Meta, etc all laying off employees. Increasingly, companies are saying bluntly: we are cutting people to invest in AI and automation. So either we learn to work with AI, or AI will replace us, little by little. Don't forget this simple rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six most interesting releases and announcements of 2025
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. ChatGPT Atlas and Comet — AI-browsers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenAI launched ChatGPT Atlas — a Chromium browser with ChatGPT at its heart: sidebar, summarizing articles, comparing products, working with documentation directly in a browser window. Perplexity rolled out Comet — also on Chromium, but with a focus on a personal agent who does its own research, deletes unnecessary tabs, and rakes mail. These are no longer add-ons on top of Chrome, but a new class of products: "a browser as a shell for an AI agent."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. AGENTS.md — README for agents&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In August, AGENTS.md appeared — a simple file at the root of the repository that explains to AI agents how to live in a project. How to collect and test code, where the entry points are, and what the rules are. In just a few months, tens of thousands of repositories pick it up, GitHub adds guides, and the Linux Foundation with OpenAI/Anthropic formalizes it as part of the standard for agentic AI. Starting this year, documentation is divided into human-made (README.md) and agent-made (AGENTS.md) — and it looks like it’s here to stay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Claude 4.5 is a "programming neighbor" for developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Anthropic updated its entire lineup: Opus 4.5, Sonnet 4.5, Haiku 4.5. Opus seriously improves reasoning, long contexts, and tool/agent handling. Sonnet has become a workhorse at an adequate price. Haiku has become an ultra-fast, high-volume option. In reviews, Claude 4.5 is often cited as one of the best dev assistants for real-world projects, not just for template tasks or pet projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Gemini — Google shows it can do it all again&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google rolled out Gemini 2.0 (Flash / Flash-Lite), then 2.5 Pro / Flash / Deep Think, and at the end of the year, Gemini 3 Pro. The models are getting faster, smarter, and are heavily tied to the Google ecosystem. The most important thing is total integration: Gemini lives in the search, Gmail, Docs, Android, and Google AI Studio. This is no longer an attempt to catch up with competitors, but a separate ecosystem that can really be used on its own. Many note that this is one of the best AI releases of the year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Starlink Direct-to-Cell and Ukraine&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SpaceX launches commercial Starlink Direct-to-Cell: satellites work as base stations, SMS texts are sent from ordinary smartphones through space without special devices! And then Kyivstar becomes the first operator in Europe to launch D2C together with Starlink: first for SMS and basic messages, then they plan to add voice and mobile Internet. For Ukraine, this is not just another feature, but an important element of resilience during blackouts and shelling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Bonus: Sora and the first step to a "dead internet"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenAI released Sora 2 for video generation and a separate application — a conditional "Instagram," purely for AI videos, called Sora. Feeds are clogged with synthetic video, people are delighted, and at the same time, many are wondering: if social networks begin to massively switch to generated content, how much "live" Internet will we have left? On my side, I can admit I myself sometimes get caught up in this content. And yes, sometimes I can't even distinguish it from real content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five "most" interesting hardware inventions of 2025 — once again it’s all about the metal
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Most innovative device: the Meta Ray-Ban Display&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first AR computer to be really similar to a daily device, in the form of normal glasses. Meta AI's messages, navigation, translations, and replies are all right in sight. Special attention should be paid to the Neural Band, a bracelet that reads muscle impulses and allows you to control the interface with gestures. There are still plenty of questions about the product, but as far as a direction of innovation goes, it’s very interesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Hobby of the Year – Logitech MX Master 4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, it's "just a mouse," but the MX Master 4 with the new Haptic Sense Panel and Actions Ring was one of the most pleasant changes to the working day. Ergonomics, multi-device, and a bunch of custom shortcuts that really save time. As the owner of the previous version, I can honestly say: this is a device that’s difficult to pass up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Disappointment of the Year – iPhone 17 Pro&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On paper, there’s the A19 Pro, a new camera, Apple Intelligence, and marketing bull shit. In practice, there’s a controversial design, aluminum instead of titanium, and the main AI features arrived late to Europe and in a stripped-down form. If you’re looking for an Apple, then check out either the iPhone 17 Air, albeit with questions, but at least it’s something new, or the regular iPhone 17, which turned out to be much more successful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. An Interesting Niche Product – Oura Ring 4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Although Oura Ring 4 was released last year, it received a cool ceramic version this year, and looks like the king of niche devices: tracking sleep, stress, and activity in the format of a beautiful piece of jewelry, not just another screen on your arm. Not for everyone, but for those who bother, wellness is a very nice gadget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Garbage of the Year – Samsung Galaxy XR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Formally, it’s the first Android XR device and flagship in cooperation with Samsung, Google and Qualcomm. In fact, it’s a rather expensive demo. Albeit lighter than Vision Pro, it’s not very ergonomic, with an external battery, damp software (very raw), unstable tracking, and a poor catalog of applications. Against this background, even the already-mentioned, not very successful Vision Pro looks cooler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big IT names we lost in 2025
&lt;/h2&gt;

&lt;p&gt;The traditional block where you want to press F and cry.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bill Atkinson&lt;/strong&gt; was a legendary Apple engineer, creator of MacPaint and HyperCard, and the man who shaped the look of early GUI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steve Shirley&lt;/strong&gt; is a pioneer of outsourcing and remote work, the founder of Freelance Programmers, who built an outsourcing business long before it became mainstream.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Margaret Boden&lt;/strong&gt; is one of the founders of cognitive science and AI research, and the author of classic works on the interaction of artificial and human intelligence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;David Benaron&lt;/strong&gt; is a doctor and entrepreneur whose developments formed the basis for the sensors of modern fitness trackers and smartwatches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Udo Kier&lt;/strong&gt; is an actor, but for us he is forever Yuri from Command &amp;amp; Conquer: Red Alert 2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is only a small cross-section of the people whose work "lies quietly under the hood" of the things we use every day, and that we have lost this year.&lt;/p&gt;

&lt;p&gt;And separately — R.I.P. Skype, a piece of our everyday life, to which time still said "that’s it" and left.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other 2025 Highlights
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;IT Hero of 2025 — Jensen Huang, CEO of NVIDIA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Under his leadership, NVIDIA briefly touches the $5 trillion capitalization bar on October 29, becoming the most valuable company in the world. The demand for their chips is rewriting records, and NVIDIA itself has finally turned from a "company for gamers" into a monopolist of infrastructure for generative AI. The man in the black leather jacket became the face of the era – more than anyone else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2025 IT Villain — Astronomer CEO Andy Byron&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We could easily give the statuette to one famous billionaire again, but this year the anti-hero award goes to Astronomer CEO Andy Byron. He became famous not for his products, but for his very loud personal story and the memes around it. Sometimes the villain of the year is not the one who breaks the market, but the one who coolly spoils his reputation because of an affair at a Coldplay concert. The story will go away, but the memes will stay with us forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IT anecdote of 2025&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On the one hand, there’s Ilya Sutskever and Mira Murati, who collected billions for a startup based on a "bare name," without a product. It's very cool, but I would believe in such a joke only in an anecdote.&lt;/p&gt;

&lt;p&gt;On the other hand, there’s a wave of madness around the new image generation model in GPT-4o: the Internet is turning into an anime carnival, Sam Altman complains that there’s not enough power, and users can’t stop. True surrealism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IT Surprise of 2025 — Oracle and Media Triples&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oracle suddenly becomes an AI cloud star: its shares soar more than 40% in a day after news of giant contracts and OpenAI connections, its capitalization approaches a trillion, and Larry Ellison overtakes Musk in the ranking of the richest people in the world by several hours.&lt;/p&gt;

&lt;p&gt;In parallel, Netflix, Paramount, and Warner Bros. Discovery play out a complex love triangle with purchase claims and political overtones. The content market is shrinking, and we are gradually approaching the world of "one app for all videos." Jobs willing, one day it will be so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mobile 2025: Liquid glass and Epic vs Apple&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This year I decided to add such a nomination. Apple is importing a complete redesign of iOS in the style of liquid glass - beautiful, loud, uncomfortable in places, but definitely hype.&lt;/p&gt;

&lt;p&gt;And Epic is finally winning a small but important victory in the fight against Apple. It was definitely a pebble that, albeit a little, changed the issue of commissions in mobile stores. Not a revolution, but it is from such microcracks that large monopolies begin to gradually rethink their behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five predictions for 2026
&lt;/h2&gt;

&lt;p&gt;Alright, let's move on to the forecasts!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. AI agents will become the new daily software, and the hype will continue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In 2026, the average engineer will have not one chat or tool, but several AI agents who will do the routine: walk through Jira/Confluence, rake mail, and write drafts. The item "experience in building and managing AI agents" will increasingly appear in vacancies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Energy will be the main limitation on the AI boom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ll see the first cases when the construction of data centers is directly limited by access to energy and water. Investments in energy, especially nuclear energy, will become a part of Big Tech's AI strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Regulators will move from chaotic fines to a system of rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first real AI certification frameworks for medicine, finance, and education will appear in 2026. They will still be bureaucratic, but they won’t look like chaotic steps any longer. At the same time, we can expect high-profile court cases against AI platforms for damage to health, people’s wallets, or their reputations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Fake AI profiles and content will become commonplace&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What now looks like "strange Insta accounts" and individual cases will become a massive buzz in 2026. Generated faces, stories, news, bloggers, individual content will become the new normal. The question of the year will be "is there anything real here?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Internal AI platforms will become the standard for companies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If in 2025 proprietary LLMs or internal AI platforms were a feature of a few, then in 2026 an internal AI platform with access to documents, code, and processes will become a new "corporate standard." Someone will buy ready-made solutions, someone will assemble it themselves, but "enterprise AI" will cease to be a pilot, and will become an obligatory part of the infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing 2025
&lt;/h2&gt;

&lt;p&gt;This year was difficult. At times it was extremely difficult. For many people it became the most difficult year in their entire career and life. But from the point of view of IT, this year turned out to be incredibly rich. AI became smarter, data centers became hungrier, regulators got angrier, Big Tech got fatter, and Ukrainian IT got even more inventive.&lt;/p&gt;

&lt;p&gt;*The article was initially published on &lt;a href="https://www.dataart.team/articles/it-industry-2025-highlights-scandals-innovations" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>techtrends</category>
      <category>innovation</category>
      <category>hitech</category>
      <category>yearinreview</category>
    </item>
    <item>
      <title>Modern Java: Why Old Rules No Longer Apply</title>
      <dc:creator>Nevena</dc:creator>
      <pubDate>Tue, 23 Dec 2025 11:35:32 +0000</pubDate>
      <link>https://dev.to/nevpetda/modern-java-why-old-rules-no-longer-apply-1mbm</link>
      <guid>https://dev.to/nevpetda/modern-java-why-old-rules-no-longer-apply-1mbm</guid>
      <description>&lt;p&gt;&lt;em&gt;Is Java no longer relevant? Denis Tsyplakov, Solutions Architect at &lt;a href="https://linkly.link/2a88W" rel="noopener noreferrer"&gt;DataArt&lt;/a&gt;, doesn’t think so. Java's reputation issues stem less from the language itself and more from outdated practices. This article revisits long-standing Java dogmas, identifies shortcomings, and offers modern alternatives to improve our development workflows.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Note: Code review standards vary by company and project. Apply these ideas thoughtfully; abrupt changes to enterprise projects can disrupt teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setters and Getters
&lt;/h2&gt;

&lt;p&gt;One common complaint is that Java code gets cluttered with setters and getters. They were initially popularized in the 1990s due to the influence of The Gang of Four (GoF) Design Patterns, which promoted implicit behavior in classes. However, implicit behavior is now seen as bad practice: data and functions should be separate. Most times, setters and getters aren't required unless you're using specific libraries like JPA. &lt;/p&gt;

&lt;p&gt;Alternatives: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Class with Fields&lt;/strong&gt;: Suitable when transporting 3-5 fields between methods.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Records&lt;/strong&gt;: A standard solution for storing data in Java, creating immutable data classes equipped with hashCode, equal and getters. However, they enforce a "stateless state" paradigm, which is fine in 95% of cases. Unless you have a 10 MB+ data structure requiring modification of individual data class fields in real-time, then use a DTO. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced Future Solution&lt;/strong&gt;: Project Valhalla for lightweight data structures.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  One Class, One File Rule
&lt;/h2&gt;

&lt;p&gt;The "one class per file" rule has been a golden standard since Java's early days. While this structure made sense when IDEs were less advanced, it's become less relevant today. Modern development environments offer robust search and navigation capabilities, allowing for more flexible file organization. &lt;/p&gt;

&lt;p&gt;Problems with the rule: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Decreased Readability&lt;/strong&gt;: Jumping between multiple files to follow a single logic flow.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broken Nesting Logic&lt;/strong&gt;: Classes like DTOs or callbacks make sense only within the context of their parent class. However, the project structure does not show that relationship.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Block Scope&lt;/strong&gt;: Exposing classes outside the method spoils the class structure. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain Leaks&lt;/strong&gt;: Moving non-sharable classes outside their natural context introduces fragility.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alternatives: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Place dependent classes/interfaces within their parent class where they belong.
&lt;/li&gt;
&lt;li&gt;Group tightly coupled DTO records under a single parent class. For example, serialize the main class BookingDTO to JSON and put nested classes InvoiceDTO, ItemDTO, etc, inside BookingDTO. &lt;/li&gt;
&lt;li&gt;If you need a data structure inside the code block, declare the class and do not expose it. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, make sure your code does not make you jump between classes too often and does not make you scroll for too long. Your code will be easier to read if you have 20 files with 20 lines of code instead of 80 files with 5 lines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
`public record DBDataInfo( 
    int documentsCount, 

    int documentsUnProcessedCount, 

    String dbSize, 

    int docProcessingErrors, 

    int archivedDocCount, 

    List&amp;lt;SourceInfo&amp;gt; sourceInfo 
) { 
    public record SourceInfo( 

        String name, 

        int raw, 

        int digest 

    ) {} 
} `
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom Exceptions
&lt;/h2&gt;

&lt;p&gt;The Java exception system is one of its strengths, and one of the reasons why I started using it over 20 years ago. The primary purpose of the exception mechanism is the ability to handle unique scenarios. In this paradigm, we usually have one exception for each scenario that can be compensated for.  &lt;/p&gt;

&lt;p&gt;However, in microservice architectures, compensation becomes less relevant and is often streamlined to the service level. It usually involves cognitive complexity that exceeds the average. For example, in a medium-sized system, you may compensate for 2-3 types and nothing more.  &lt;/p&gt;

&lt;p&gt;Java (and frameworks like Spring) offer many standard exception classes that cover 95% of cases, such as IllegalArgumentExceptions and IllegalState exceptions. Most often, developers are unaware of the standard exceptions and declare a class structure that's hardly digestible and can ruin your code.  &lt;/p&gt;

&lt;p&gt;Alternatives: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consider scenarios that can be compensated and stick with standard exceptions otherwise. &lt;/li&gt;
&lt;li&gt;Design an exception hierarchy around those cases. &lt;/li&gt;
&lt;li&gt;In a microservice architecture, 80% of sync call exception handling cases fall under two patterns: retry and circuit breaker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember: Creating a new class can add some cognitive load. Think about how it might affect different situations. If you don't plan to use it, it might be best to skip it. &lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker( 

    name = "weather",  

    fallbackMethod = "offlineWeather" 

) 

public WeatherDto current(String city) { 

    return restTemplate.getForObject( 

        "https://api.example.com/weather?city={}",  

        WeatherDto.class,  

        city 

    ); 

} 

  

/**  

 * Fallback when circuit is OPEN or the call itself fails.  

 */ 

public WeatherDto offlineWeather(String city, Throwable ex) { 

    return new WeatherDto(city, "???", "service-unavailable (cached/default)"); 

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mapping
&lt;/h2&gt;

&lt;p&gt;In a classic enterprise app structure, you map controller parameters to a DTO, which maps them to an entity. Then, the entity passes to a repository (DB or REST), and you receive another entity in exchange, return to the service, map it to a DTO, and return to the controller. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Real-life example&lt;/strong&gt;: In a microservice, we receive a 1MB+ flight search XML reply from NDC, map it to a data structure, extract the airline code, add it to the response header, and pass the reply along. But parsing the reply and serializing it takes several seconds (10+ seconds in the worst case). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Read the reply as a byte stream, parse it with a NanoSAX parser, set the header, and return the bytes as the body. This would take less than 10 milliseconds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, a more critical problem is creating mappings for hundreds of fields when your code only needs a dozen. This makes simple microservices hard to read and digest.  &lt;/p&gt;

&lt;p&gt;Alternatives: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Unnecessary Mapping&lt;/strong&gt;: If you only need a few fields from a JSON object with 100+ fields, read it as a JSONNode and extract fields to a clean DTO. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Declarative Transformers&lt;/strong&gt;: Wherever it’s applicable, use XSLT(c) for XML, use libs like JSLT, Jolt, JSONata-for-Java, etc. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize Hierarchies&lt;/strong&gt;: If one is enough, avoid creating both entity and DTO layers. Just use a DTO, but track any data leakage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dependency Hell
&lt;/h2&gt;

&lt;p&gt;Java engineers like mapping data structures and frequently create system-name-dto.jar, using it as a library in all services. All incoming data is mapped to one of the library DTOs and serialized back to JSON/XML when sending HTTP with RESTTemplate/Feign. This approach creates problems such as decreased performance and changes in the library when the DTO library is used in 30 different services deployed to prod 24/7.  &lt;/p&gt;

&lt;p&gt;There is no universal solution to this, but you can try a few of these guidelines: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If more than two services use a big DTO, you probably need to rethink the service design.
&lt;/li&gt;
&lt;li&gt;If you just pass through a big data structure, stick to that and don't mutate or inspect it. &lt;/li&gt;
&lt;li&gt;Make the mutated part a separate DTO if you need to mutate it. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Separation of Interface and Implementation
&lt;/h2&gt;

&lt;p&gt;Theoretically, it seems like a good idea. You define the interface of a service or class and then create an implementation. If you need more, you make more. This practice results in writing more code than needed.  &lt;/p&gt;

&lt;p&gt;The typical explanation for this was: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enforce Class Contract&lt;/strong&gt;: Even though Java classes have public contract methods.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit Testing and Mocking&lt;/strong&gt;: If your code needs to be changed to facilitate unit testing, you should probably rethink your test strategy. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prepare for Future Extension&lt;/strong&gt;: Do it when needed, not in advance. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Implementations&lt;/strong&gt;: Nowadays, we usually don't have more than one implementation of an interface.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, how to deal with it? Just don't do it, that's it. If you'd like to explore this topic in more detail, read this &lt;a href="https://www.baeldung.com/java-interface-single-implementation" rel="noopener noreferrer"&gt;article&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive Code
&lt;/h2&gt;

&lt;p&gt;The main argument is that all reactive frameworks for Java are dead. There are several reasons for this:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Virtual Threads (Project Loom, GA in Java 21) make the classic "one-thread-per-request" model memory-right and massively scalable, eliminating the core performance reason for adopting reactive I/O. &lt;/li&gt;
&lt;li&gt;Structured Concurrency and scoped values give you simple, imperative flow control and tracing without the cognitive load of reactive streams, but with equal or better throughput.
&lt;/li&gt;
&lt;li&gt;Mainstream HTTP Frameworks: Spring MVC, JAX-RS/Jakarta REST, Micronaut HTTP, Quarkus RESTEasy run unchanged on virtual threads and now match WebFlux/Vert.x-style stacks in latency and QPS, but with cleaner code and easier debugging. &lt;/li&gt;
&lt;li&gt;Blocking JDBC Sudden Scales: A single JVM can spawn hundreds of thousands of virtual threads that wait on the same java.sql calls. So, you no longer need reactive drivers (R2DBC, jasync-sql) just to keep database I/O from becoming a bottleneck.
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reactive Frameworks bring complexity:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Non-linear control flow &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Back-pressure plumbing &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tricky error handling: yet their performance edge has vanished &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copilot-like tools better digest the sequential blocking flow of operations. Post Java 21, the cost/benefit equation flips in favor of simple blocking APIs. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2Spring and Beyond
&lt;/h2&gt;

&lt;p&gt;Another typical dogma is, "Java is not always Spring." While Spring is one of humanity's most advanced and remarkable frameworks, it still has some flaws; it requires you to write your application in a certain way and increases memory consumption.  &lt;/p&gt;

&lt;p&gt;There were some attempts to create something better. Quarkus, for example, was quite popular a few years ago, but is not a buzzword now. There is no comparative framework to replace Spring, except for some niche tasks.  &lt;/p&gt;

&lt;p&gt;So, the main points here are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java has frameworks for everything. &lt;/li&gt;
&lt;li&gt;Don't avoid Spring; use it if you can. &lt;/li&gt;
&lt;li&gt;If you have a specialized task, do your research: most likely, there is a Java framework/library for it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enterprise-class app hierarchy
&lt;/h2&gt;

&lt;p&gt;The classic Java class hierarchy goes like this: Controller&amp;gt;DTO&amp;gt;Service&amp;gt;Entity&amp;gt;Repository &lt;/p&gt;

&lt;p&gt;The main goal of a standard class hierarchy is to make the class layout predictable. It's useful for applications with over 200,000 lines of code, enabling developers to quickly find a class with specific business logic. &lt;/p&gt;

&lt;p&gt;But if you have a small microservice, you don't need to follow the same pattern. You will probably have just 5 controllers with 10+ methods.  &lt;/p&gt;

&lt;p&gt;Ask yourself: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can a controller go directly to the repository? &lt;/li&gt;
&lt;li&gt;Do you need to remap an entity to a DTO? &lt;/li&gt;
&lt;li&gt;If a service needs one SQL query, can it be done directly inline?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Granularity matters, but oversplitting small services can create unnecessary bloat. Sometimes fewer layers mean clearer, more maintainable code.  &lt;/p&gt;

&lt;p&gt;Let's test the limits and see how far we can distance ourselves from the dogma.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@PostMapping(🌐“/api/booking”) 

public void saveBooking (@RequestBody BookingDTO bookingDTO) { 

record BookingReply( 

UUID uuid, 

String transactionId) { 

{ 

jdbcTpl.update(sql… 

update booking set transaction_id = :transactionId where uuid = :uuid 

…, Map.of( 

k1: "uuid", bookingDTO.uuid, 

k2: "transactionId", restTpl.postForObject( 

url: http://booking.api/booking , 

bookingDTO 

BookingReply.class).transactionId) 

); 

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

&lt;/div&gt;



&lt;p&gt;This code is functional, with 17 LOC that shows all the logic end-to-end. Nonfunctional aspects, such as error handling and validations, are handled at the service level. Would this be fine as a part of a 200 LOC microservice? I'm not brave enough to try.  &lt;/p&gt;

&lt;p&gt;So, one controller that does the rest call and saves the results to the database in just a few lines of code. The reply is in line with everything. Is this legal? Probably not. If I see this in production code, I will probably ask to separate work with the database and HTTP into two different classes due to a mix of concerns.  &lt;/p&gt;

&lt;p&gt;This would be acceptable on other platforms and languages. Imagine writing 17 lines of code in one file or 5 times more lines for the same logic. The latter sounds better. But don't take this as advice; we were only testing the limits here.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Myths
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;“Java is Slow”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many people say Java is slow, but that's not really the case! This perception comes from needing to switch to other frameworks or languages to make things faster. If you check out some performance tests, you'll find that Java actually performs well. Indeed, it may not be as fast as C or Rust, but it still holds its own.  &lt;/p&gt;

&lt;p&gt;If you're looking to speed things up, consider using the GraalVM Compiler! It's simple to set up with Spring—just add one line to your configuration, and you'll see a boost in performance. You can test it by checking out these links: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.graalvm.org/" rel="noopener noreferrer"&gt;GraalVM official website&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.spring.io/spring-boot/reference/packaging/native-image/index.html" rel="noopener noreferrer"&gt;GraalVM Native Images documentation&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;“Java Slow Startup”&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;25 years ago, it might have taken a few seconds to start. But nowadays, numerous ways of speeding things up are essential when designing a microservice architecture in a Kubernetes cluster. A good solution for this is called the &lt;strong&gt;Coordinated Restore Checkpoint&lt;/strong&gt;. It allows you to capture the state of an already started container and deploy it into production. If you follow this link, you'll see how to speed up your application's startup 100 times.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Change How We Write Java
&lt;/h2&gt;

&lt;p&gt;There are several reasons for this: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code Assistants&lt;/strong&gt;: Copilot and similar assistants work best with linear text. You can have one file with data objects; Copilot will know which to include. So, you should write your code to be more readable for assistants since they are our future.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language Evolution&lt;/strong&gt; (Java and Spring have changed significantly): Design patterns from 20 years ago simply don't work anymore. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New Generation Pressure&lt;/strong&gt;: You should adapt and embrace new approaches. Others don't see a reason to follow old practices. &lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;To keep Java relevant, we must rethink old conventions. &lt;/p&gt;

&lt;p&gt;Action points: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stay updated with Java 11, 17, and 21. &lt;/li&gt;
&lt;li&gt;Study the latest Spring Framework documentation. &lt;/li&gt;
&lt;li&gt;Explore the broader Spring ecosystem: Spring Data JDBC, Spring Cloud, etc.
&lt;/li&gt;
&lt;li&gt;Question current best practices: Are they relevant today? &lt;/li&gt;
&lt;li&gt;Experiment with TypeScript or other languages to broaden your programming perspective.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Java isn’t outdated; it’s evolving. The real challenge is ensuring our coding habits evolve with it.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;*Originally published on &lt;a href="https://www.dataart.team/articles/modern-java-best-practices-tips-and-insights" rel="noopener noreferrer"&gt;DataArt Team blog&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>java</category>
      <category>modernjava</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
