<?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: David Dominguez</title>
    <description>The latest articles on DEV Community by David Dominguez (@davdomin).</description>
    <link>https://dev.to/davdomin</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%2F171140%2F1ff61e51-b150-4bad-afec-0daa1d9620ba.png</url>
      <title>DEV Community: David Dominguez</title>
      <link>https://dev.to/davdomin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davdomin"/>
    <language>en</language>
    <item>
      <title>The experiment: Reviving 90s Paratrooper without writing a single line of code</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Mon, 11 May 2026 03:19:38 +0000</pubDate>
      <link>https://dev.to/davdomin/the-experiment-reviving-90s-paratrooper-without-writing-a-single-line-of-code-1pli</link>
      <guid>https://dev.to/davdomin/the-experiment-reviving-90s-paratrooper-without-writing-a-single-line-of-code-1pli</guid>
      <description>&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%2Fj3nnhrvdjyoh76g2d1lj.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%2Fj3nnhrvdjyoh76g2d1lj.png" alt=" " width="800" height="632"&gt;&lt;/a&gt;&lt;br&gt;
A few days ago, I wanted to play the mythical DOS game &lt;em&gt;Paratrooper&lt;/em&gt; – the one where you control an anti-aircraft gun and shoot down enemy paratroopers. But I didn't want to download an emulator or code it myself. I wanted to see if &lt;strong&gt;two different AIs could do it for me&lt;/strong&gt;, each with a distinct role.&lt;/p&gt;

&lt;p&gt;The result was &lt;strong&gt;functional, yes, but very basic&lt;/strong&gt;. No advanced physics, no sound, no helicopters. But the cannon shoots, enemies fall, lives decrease, and you can lose. Just enough to feel nostalgic for five minutes.&lt;/p&gt;

&lt;p&gt;How did I do it? Let me walk you through the process, the tools, and the lessons learned.&lt;/p&gt;




&lt;h2&gt;
  
  
  The two AIs and their roles
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;AI&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;What it did&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;DeepSeek&lt;/strong&gt; (me, the assistant)&lt;/td&gt;
&lt;td&gt;Architect / Planner&lt;/td&gt;
&lt;td&gt;Designed the project structure (TS, CSS, HTML files), wrote the detailed prompts that would later be sent to the other AI.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nemotron 3 Super Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Coder&lt;/td&gt;
&lt;td&gt;Received DeepSeek's prompts and generated the actual game source code (TypeScript, CSS, HTML).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; I did &lt;em&gt;not&lt;/em&gt; use OpenCode with the Nemotron model. I simply copied the prompts that DeepSeek gave me and pasted them into the &lt;strong&gt;Nemotron 3 Super Free&lt;/strong&gt; interface (a free model that claims to understand legacy code and retro languages, available on several AI platforms).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 1: DeepSeek plans the structure
&lt;/h2&gt;

&lt;p&gt;I asked DeepSeek to help me create a Paratrooper game in TypeScript, with CSS and HTML, but with one condition: &lt;strong&gt;the code had to be generated by another AI&lt;/strong&gt;. So DeepSeek didn't write the game – instead, it generated a series of ready-to-copy-paste prompts.&lt;/p&gt;

&lt;p&gt;These prompts included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;tsconfig.json&lt;/code&gt; to compile TypeScript.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;index.html&lt;/code&gt; with canvas, life counter, and restart button.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;styles.css&lt;/code&gt; with a retro look.&lt;/li&gt;
&lt;li&gt;A full &lt;code&gt;game.ts&lt;/code&gt; with the game logic: mouse-controlled cannon, click-to-shoot, falling paratroopers, collisions, lives, game over, and restart.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DeepSeek also warned me that the result would probably be &lt;strong&gt;very basic&lt;/strong&gt; if I didn't iterate much. It was right.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Nemotron 3 Super Free writes the code
&lt;/h2&gt;

&lt;p&gt;I copied the longest prompt (the one for &lt;code&gt;game.ts&lt;/code&gt;) and pasted it into &lt;strong&gt;Nemotron 3 Super Free&lt;/strong&gt;. In less than a minute, the AI returned complete code. Then I did the same for the other prompts.&lt;/p&gt;

&lt;p&gt;When I opened &lt;code&gt;index.html&lt;/code&gt; in my browser… &lt;strong&gt;it worked on the first try!&lt;/strong&gt; The cannon moved with the mouse, paratroopers fell from the top, shots eliminated them, and lives decreased when they hit the ground.&lt;/p&gt;

&lt;p&gt;But I also noticed &lt;strong&gt;clear limitations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imprecise collisions&lt;/strong&gt; – Sometimes a bullet passed near an enemy and still killed it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No fire rate limit&lt;/strong&gt; – I could shoot like a machine gun.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No animations&lt;/strong&gt; – Paratroopers were just brown rectangles with a white square on top (the parachute). No sprites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No helicopters&lt;/strong&gt; – Just basic paratroopers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restart sometimes left "ghost bullets"&lt;/strong&gt; in the array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: it delivers the core mechanics, but &lt;strong&gt;without any refinement&lt;/strong&gt;. It's a functional prototype, not a polished game.&lt;/p&gt;




&lt;h2&gt;
  
  
  Can you improve it with more prompts?
&lt;/h2&gt;

&lt;p&gt;Absolutely. I asked DeepSeek to generate &lt;strong&gt;correction prompts&lt;/strong&gt;: limit shots, adjust collisions, clean the array on restart. I copied those new prompts to Nemotron, and after two or three iterations the game improved noticeably.&lt;/p&gt;

&lt;p&gt;But even after several rounds, the result was still &lt;strong&gt;"very basic"&lt;/strong&gt; compared to the original DOS Paratrooper. The reason? Nemotron 3 Super Free seems optimized for &lt;strong&gt;simple, straightforward code&lt;/strong&gt;, not complex simulations or games with delicate state.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I promised vs. what I got
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Final state&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cannon follows mouse&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Click to shoot&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paratroopers fall&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bullet-enemy collisions&lt;/td&gt;
&lt;td&gt;✅ Yes, but somewhat imprecise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lives (3) and game over&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restart button&lt;/td&gt;
&lt;td&gt;✅ Yes, though sometimes buggy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fire rate limit&lt;/td&gt;
&lt;td&gt;❌ Not initially, yes after correction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sound&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explosions&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Helicopters&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High scores&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;In one word: basic.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons learned (if you want to try this yourself)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AIs don't replace human judgment&lt;/strong&gt; – Without my corrections (the extra prompts from DeepSeek), the game would have been almost unplayable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nemotron 3 Super Free is great for rapid prototypes&lt;/strong&gt;, but don't expect a commercial game.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepSeek (or any conversational assistant) is ideal for designing architecture and prompts&lt;/strong&gt;, because it understands the overall project context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iteration is key&lt;/strong&gt; – With each correction prompt, the game gets a little better. Three or four iterations already give a decent result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Very basic" isn't bad&lt;/strong&gt; – Sometimes we just want to revive a memory, not create the next indie hit. And for that, these tools are perfect.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Final reflection: was it worth it?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Absolutely.&lt;/strong&gt; In less than an hour, without writing a single line of manual code, I had a &lt;strong&gt;playable game in the browser&lt;/strong&gt;. My 10-year-old nephew tried it and had fun shooting at the paratroopers. Sure, after five minutes he said &lt;em&gt;"it's too easy"&lt;/em&gt; and went back to Roblox. But for me, seeing that cannon move clumsily on screen was like traveling back to 1992.&lt;/p&gt;

&lt;p&gt;If you also want to revive a DOS classic without the hassle, I recommend this method: &lt;strong&gt;use one AI to plan (DeepSeek, ChatGPT, Claude) and another to code (Nemotron, Copilot, Codeium)&lt;/strong&gt;. The result will be basic, but functional. And the fun is in the process.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus: the (very basic) final code generated by Nemotron
&lt;/h2&gt;

&lt;p&gt;In case you want to try it or improve it, here's the link to my repository:&lt;br&gt;&lt;br&gt;
➡️ &lt;strong&gt;&lt;a href="https://github.com/davdomin/paratrooper" rel="noopener noreferrer"&gt;https://github.com/davdomin/paratrooper&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;It's not pretty, but &lt;strong&gt;it works&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried building games with two different AIs? Share your experience in the comments!&lt;/em&gt; 🕹️&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gamedev</category>
      <category>nocode</category>
      <category>showdev</category>
    </item>
    <item>
      <title>AI Coliseum: Building a Python Chess Engine for LLM Benchmarking</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Sun, 03 May 2026 00:44:40 +0000</pubDate>
      <link>https://dev.to/davdomin/ai-coliseum-building-a-python-chess-engine-for-llm-benchmarking-2ba</link>
      <guid>https://dev.to/davdomin/ai-coliseum-building-a-python-chess-engine-for-llm-benchmarking-2ba</guid>
      <description>&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%2F0aya242qfjfib9gtihcc.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%2F0aya242qfjfib9gtihcc.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
What happens when you pit two different programming logics against each other in an environment of strict rules? To answer this, I developed a Python project that functions as an &lt;strong&gt;execution environment (Engine)&lt;/strong&gt; where different AI scripts can compete.&lt;/p&gt;

&lt;p&gt;In this post, I’ll explain how I designed the board, the rules, and the experiment of facing &lt;code&gt;white.py&lt;/code&gt; against &lt;code&gt;black.py&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Referee: A Pure Rules Engine
&lt;/h2&gt;

&lt;p&gt;Unlike other projects, here the "engine" is not the player. Its sole mission is to be the board's operating system. It is programmed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Validate Legal Moves:&lt;/strong&gt; Ensuring no AI attempts to bypass the rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage State:&lt;/strong&gt; Controlling castling, en passant captures, and promotions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detect Game End:&lt;/strong&gt; Applying rules for insufficient material, threefold repetition, and the 50-move rule.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. The Experiment: &lt;code&gt;white.py&lt;/code&gt; vs. &lt;code&gt;black.py&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The real magic happens in external files. The engine acts as a "Coliseum" that delivers the current board state to each script and waits for a response.&lt;/p&gt;

&lt;p&gt;This allows for &lt;strong&gt;AI Benchmarking&lt;/strong&gt; experiments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search Logic:&lt;/strong&gt; Who calculates better: a Minimax-based script or one based on experimental heuristics?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization:&lt;/strong&gt; How response time (&lt;code&gt;time.time()&lt;/code&gt;) affects the quality of the move returned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation Heuristics:&lt;/strong&gt; Comparing how different algorithms value piece positioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Anatomy of the Engine (The Backbone)
&lt;/h2&gt;

&lt;p&gt;The code is designed to be modular and transparent. Key implementation points include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Board Cloning:&lt;/strong&gt; The engine allows AIs to clone the state to simulate future moves without affecting the live game.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PGN Builder:&lt;/strong&gt; Automatic generation of standard notation so games can be analyzed in external viewers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Console Visualization:&lt;/strong&gt; An ASCII rendering system to follow the "fight" in real-time from the terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Why Separate the Board from the Logic?
&lt;/h2&gt;

&lt;p&gt;Separating the engine from the players (&lt;code&gt;white.py&lt;/code&gt; and &lt;code&gt;black.py&lt;/code&gt;) offers critical software development advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Modularity:&lt;/strong&gt; You can change an AI's logic without touching a single line of chess rule code.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Impartiality:&lt;/strong&gt; Both scripts receive the exact same state information (&lt;code&gt;get_state()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Scalability:&lt;/strong&gt; It's easy to add new "players" and face them in a Round Robin tournament.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Experiment: A Chronicle of Algorithmic Slaughter
&lt;/h2&gt;

&lt;p&gt;Developing this Coliseum wasn't linear; it was an evolution of "survival of the fittest." In early tests, &lt;strong&gt;GPT&lt;/strong&gt;—using an optimized initial prompt—completely swept basic versions of &lt;strong&gt;Gemini&lt;/strong&gt; and clearly outperformed &lt;strong&gt;DeepSeek&lt;/strong&gt;. The throne seemed set.&lt;/p&gt;

&lt;p&gt;However, the landscape shifted when &lt;strong&gt;Claude&lt;/strong&gt; entered the scene. With much deeper calculation logic and superior decision-tree management, Claude dethroned GPT and mercilessly "destroyed" the other competitors.&lt;/p&gt;

&lt;p&gt;The most interesting part followed: by applying the optimization principles and code structure used by Claude to the other AIs, the field leveled. While still playing with less precision, these improved versions began &lt;strong&gt;forcing draws by repetition&lt;/strong&gt;. They evolved from tactical suicides to a defense solid enough to hold the line.&lt;/p&gt;




&lt;h2&gt;
  
  
  From Code to Board: Generating PGN
&lt;/h2&gt;

&lt;p&gt;To ensure these games don't just live as terminal logs, the software implements a &lt;strong&gt;PGN Builder&lt;/strong&gt;. PGN (Portable Game Notation) is the universal standard for recording chess games.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the Data Flows:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Move Capture:&lt;/strong&gt; Every time &lt;code&gt;white.py&lt;/code&gt; or &lt;code&gt;black.py&lt;/code&gt; makes a move, the engine logs the origin, destination, captures, and promotions.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Algebraic Translation:&lt;/strong&gt; The engine converts internal array coordinates (e.g., &lt;code&gt;[7, 4]&lt;/code&gt;) into standard notation (e.g., &lt;code&gt;e1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Special State Detection:&lt;/strong&gt; The software checks if the move resulted in &lt;strong&gt;check (+)&lt;/strong&gt;, &lt;strong&gt;checkmate (#)&lt;/strong&gt;, or &lt;strong&gt;castling (O-O)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Export:&lt;/strong&gt; At the end of the game, these strings are concatenated: &lt;code&gt;1. e4 e5 2. Nf3 Nc6...&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Visualizing on Chess.com or Lichess
&lt;/h3&gt;

&lt;p&gt;The final result is a block of text you can paste into tools like the &lt;strong&gt;Chess.com Analysis&lt;/strong&gt; board. These platforms read the PGN, reconstruct the game visually, and let you use engines like Stockfish to see exactly where Claude gained the upper hand.&lt;/p&gt;




&lt;h2&gt;
  
  
  Open Source Challenge
&lt;/h2&gt;

&lt;p&gt;I have uploaded this competition environment to my repository. If you are a developer and want to test your own chess logic, just create your script and pit it against the board.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project Repository:&lt;/strong&gt; &lt;a href="https://github.com/davdomin/chess_motor" rel="noopener noreferrer"&gt;https://github.com/davdomin/chess_motor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What strategy would you use to win: an aggressive material-based attack or a solid positional defense? Let me know in the comments!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Keep Code Left: The Art of Readable Logic</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Fri, 01 May 2026 22:08:18 +0000</pubDate>
      <link>https://dev.to/davdomin/keep-code-left-the-art-of-readable-logic-28o3</link>
      <guid>https://dev.to/davdomin/keep-code-left-the-art-of-readable-logic-28o3</guid>
      <description>&lt;p&gt;In 2015, while working at Software Andina, I had the privilege of attending a session that changed the way I look at a source file. At the time, we were frequently visited by developers from the United States who shared their expertise to help us sharpen our craft.&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%2Fy0l8fz5dt6elkdysoi45.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%2Fy0l8fz5dt6elkdysoi45.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of those visitors was Mick Andrew, a seasoned developer and Director of Development at Sage. He was a close friend of my boss at the time, John Rutherfurd, and he brought with him a presentation titled &lt;strong&gt;"Keep Code Left" (KCL)&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;The title was deceptively simple, but the philosophy behind it was profound. As developers, we often focus on making code work, but we frequently forget that code is read far more often than it is written. Mick taught us that by following a few "cookbook" rules, we could transform convoluted, deeply nested logic into something clean, linear, and remarkably easy to maintain.&lt;br&gt;&lt;br&gt;
What is Keep Code Left?&lt;/p&gt;

&lt;p&gt;At its core, Keep Code Left is a coding style designed to maximize readability. The name refers to the visual structure of the code: the more your logic is indented (pushed to the right), the harder it becomes for a human brain to track the "state" and the flow of the program.  &lt;/p&gt;

&lt;p&gt;The goals of KCL are straightforward:&lt;/p&gt;

&lt;p&gt;**    Simplify Logic**: Create code that flows linearly rather than branching out.  &lt;/p&gt;

&lt;p&gt;**    Enhance Readability**: Allow developers to "see the flow" and grasp the goal of a method at a glance.  &lt;/p&gt;

&lt;p&gt;**    Reduce Maintenance Bugs**: Simple code is harder to break during future updates.  &lt;/p&gt;

&lt;p&gt;**    Streamline Reviews**: It provides a standard that can be verified during code reviews without needing deep domain knowledge.  &lt;/p&gt;

&lt;p&gt;Since that day in 2015, I have applied these rules to nearly every project I’ve touched. In this post, I’ll break down exactly how to "Keep Code Left" and why your future self (and your team) will thank you for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why “Keep Code Left” Matters&lt;/strong&gt;&lt;br&gt;
When code becomes deeply nested, several problems appear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Harder to read line-by-line&lt;/li&gt;
&lt;li&gt;Logic becomes difficult to follow&lt;/li&gt;
&lt;li&gt;Increased risk of bugs&lt;/li&gt;
&lt;li&gt;Slower code reviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;KCL aims to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplify logic&lt;/li&gt;
&lt;li&gt;Reduce indentation&lt;/li&gt;
&lt;li&gt;Make flow visible at a glance&lt;/li&gt;
&lt;li&gt;Enable faster and more reliable reviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Core Principle&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Avoid unnecessary nesting. Prefer early exits and linear flow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of wrapping logic inside multiple if blocks, you &lt;strong&gt;handle edge cases early and return immediately.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Nested Code (Bad)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;IsValid&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Process order&lt;/span&gt;
                &lt;span class="nc"&gt;Save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 levels of nesting&lt;/li&gt;
&lt;li&gt;Hard to scan quickly&lt;/li&gt;
&lt;li&gt;Main logic is buried&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Keep Code Left (Better)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;IsValid&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Process order&lt;/span&gt;
    &lt;span class="nc"&gt;Save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flat structure&lt;/li&gt;
&lt;li&gt;Easy to read top-to-bottom&lt;/li&gt;
&lt;li&gt;Main logic is immediately visible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example 2: Conditional Complexity&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Bad Approach&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isBlocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;KCL Approach&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isBlocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**Key Techniques of Keep Code Left&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Early Returns
**
Handle invalid cases first:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Guard Clauses&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Protect your logic from bad inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasPermission&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Reduce Indentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every level of indentation increases cognitive load.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;DoSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;DoSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Focus on the “Happy Path”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The main logic should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Straightforward&lt;/li&gt;
&lt;li&gt;Easy to locate&lt;/li&gt;
&lt;li&gt;Not buried inside conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Impact on Code Reviews&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;KCL is extremely effective in reviews because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patterns are easy to detect&lt;/li&gt;
&lt;li&gt;Less domain knowledge is required&lt;/li&gt;
&lt;li&gt;Reviewers can quickly spot:&lt;/li&gt;
&lt;li&gt;Missing checks&lt;/li&gt;
&lt;li&gt;Logical errors&lt;/li&gt;
&lt;li&gt;Anti-patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mental Model&lt;/strong&gt;&lt;br&gt;
When writing code, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can I exit earlier?&lt;/li&gt;
&lt;li&gt;Can I reduce one level of indentation?&lt;/li&gt;
&lt;li&gt;Is the main logic immediately visible?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-World Benefit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Over time, applying KCL leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fewer bugs&lt;/li&gt;
&lt;li&gt;Faster onboarding of new developers&lt;/li&gt;
&lt;li&gt;Cleaner diffs in pull requests&lt;/li&gt;
&lt;li&gt;More maintainable systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep Code Left (KCL) Guidelines for AI&lt;/strong&gt;&lt;br&gt;
Applying Keep Code Left (KCL) principles when working with AI assistants is important because, by default, they tend to generate code that is correct but unnecessarily nested. This makes the code harder to read, review, and maintain over time. By explicitly enforcing simple rules like early returns and minimal indentation, you guide the AI to produce cleaner, more linear code that aligns better with how humans understand logic. This reduces cognitive load, speeds up code reviews, and improves long-term maintainability.&lt;/p&gt;

&lt;p&gt;Claude.MD Example:&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Claude &lt;code&gt;.md&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;md
&lt;span class="gu"&gt;## KCL Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use early returns
&lt;span class="p"&gt;-&lt;/span&gt; Avoid nested if statements
&lt;span class="p"&gt;-&lt;/span&gt; Keep code flat and readable

&lt;span class="gu"&gt;### Example&lt;/span&gt;

Bad:
if (user) {
    if (user.isActive) {
        process(user);
    }
}

Good:
if (!user) return;
if (!user.isActive) return;

process(user);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>codequality</category>
      <category>coding</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Remade the 1991 Classic "Gorillas" in Python—and Survived the Snapcraft Journey</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Sat, 25 Apr 2026 06:06:15 +0000</pubDate>
      <link>https://dev.to/davdomin/remade-the-1991-classic-gorillas-in-python-and-survived-the-snapcraft-journey-2nfp</link>
      <guid>https://dev.to/davdomin/remade-the-1991-classic-gorillas-in-python-and-survived-the-snapcraft-journey-2nfp</guid>
      <description>&lt;p&gt;The Nostalgia Hit 🍌&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%2Fdj8kknlxkzj5r3yrtlf4.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%2Fdj8kknlxkzj5r3yrtlf4.png" alt=" " width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember the two gorillas standing on a skyline, tossing exploding bananas at each other? I decided to bring that back. I built a remake of the classic QBasic Gorillas using Python and Pygame.&lt;/p&gt;

&lt;p&gt;It has everything:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Randomly generated city skylines.

Parabolic physics (gravity is a beast).

The classic sun that reacts when hit.

Screen shake for that "modern" retro feel.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Tech Stack&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Language: Python 3.12

Library: Pygame (for the heavy lifting of 2D rendering)

Distribution: Snapcraft (Ubuntu Snaps)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The "Snap" Struggle is Real 🛠️&lt;/p&gt;

&lt;p&gt;Packaging this for Linux was an adventure. I wanted to make it easy for anyone to install without messing with virtual environments.&lt;/p&gt;

&lt;p&gt;I hit every wall possible:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The Python Plugin: Getting the interpreter to behave inside a clean container was tricky.

Confinement: Switching to classic confinement was the key to getting audio and video drivers working smoothly across different distros.

The "Destructive" Fix: Learning to use --destructive-mode when my local container felt like being stubborn.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;How to Play&lt;/p&gt;

&lt;p&gt;If you are on Linux, you can try it out right now (waiting for store approval, but you can build from source!):&lt;br&gt;
Bash&lt;/p&gt;

&lt;h1&gt;
  
  
  Clone the repo
&lt;/h1&gt;

&lt;p&gt;git clone &lt;a href="https://github.com/davdomin/gorillas-retro-remake" rel="noopener noreferrer"&gt;https://github.com/davdomin/gorillas-retro-remake&lt;/a&gt;&lt;br&gt;
cd gorillas-retro-remake&lt;/p&gt;

&lt;h1&gt;
  
  
  Run it
&lt;/h1&gt;

&lt;p&gt;python3 src/main.py&lt;/p&gt;

&lt;p&gt;What’s Next? 🚀&lt;/p&gt;

&lt;p&gt;I'm currently thinking about adding a multiplayer mode via IP connection. Is it overkill for a 1991 remake? Maybe. Is it going to be fun to code? Absolutely.&lt;/p&gt;

&lt;p&gt;Check out the code here: &lt;a href="https://github.com/davdomin/gorillas" rel="noopener noreferrer"&gt;https://github.com/davdomin/gorillas&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>pygame</category>
      <category>linux</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Cómo consumir un API REST en C++ utilizando la biblioteca cURL.</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Sun, 22 Oct 2023 03:22:07 +0000</pubDate>
      <link>https://dev.to/davdomin/como-consumir-un-api-rest-en-c-utilizando-la-biblioteca-curl-415p</link>
      <guid>https://dev.to/davdomin/como-consumir-un-api-rest-en-c-utilizando-la-biblioteca-curl-415p</guid>
      <description>&lt;p&gt;La programación en C++ es versátil y poderosa, y una de las tareas comunes es interactuar con servicios web a través de API REST. ¡Hoy te mostraré cómo hacerlo en unos pocos pasos!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 1: Preparando el Entorno&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Primero, asegúrate de tener la biblioteca cURL instalada. Puedes hacerlo utilizando tu administrador de paquetes favorito. Luego, incluye los encabezados necesarios en tu código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 2: Escribiendo el Código&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Diseña tu programa C++ para realizar solicitudes HTTP utilizando cURL. Debes configurar la solicitud, incluyendo la URL del servicio web y definir una función de devolución de llamada para procesar la respuesta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 3: Haciendo la Solicitud&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Utiliza cURL para realizar la solicitud HTTP al servicio REST. Maneja la respuesta y procesa los datos según tus necesidades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 4: Limpieza y Cierre&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No olvides liberar los recursos una vez que hayas terminado de usar cURL.&lt;/p&gt;

&lt;p&gt;✨ ¡Y eso es todo! Ahora puedes interactuar con servicios web en C++ y trabajar con los datos que obtengas. La programación en C++ abre un mundo de posibilidades.&lt;/p&gt;

&lt;h1&gt;
  
  
  Programación #CPlusPlus #RESTAPI #DesarrolloWeb
&lt;/h1&gt;

&lt;p&gt;Sigue el enlace para mas detalles y obtener el codigo fuente&lt;br&gt;
&lt;a href="https://davdomin.blogspot.com/2023/10/como-consumir-un-api-rest-en-c.html"&gt;davdomin.blogspot.com/2023/10/como-consumir-un-api-rest-en-c.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/davdomin/RestApiCpp"&gt;https://github.com/davdomin/RestApiCpp&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Crear una Extensión para Chrome en 10 Sencillos Pasos</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Sat, 21 Oct 2023 02:21:20 +0000</pubDate>
      <link>https://dev.to/davdomin/crear-una-extension-para-chrome-en-10-sencillos-pasos-1f29</link>
      <guid>https://dev.to/davdomin/crear-una-extension-para-chrome-en-10-sencillos-pasos-1f29</guid>
      <description>&lt;p&gt;Las extensiones de Chrome son pequeños programas que amplían las funcionalidades del navegador Google Chrome. En esta guía, aprenderás a crear una extensión básica desde cero. No se requiere experiencia previa en programación.&lt;/p&gt;

&lt;p&gt;Configuración del Entorno de Desarrollo&lt;/p&gt;

&lt;p&gt;Instalar Google Chrome: Si aún no tienes Google Chrome instalado, descárgalo e instálalo en tu computadora. Debes utilizar Chrome como navegador principal para probar tus extensiones.&lt;/p&gt;

&lt;p&gt;Editor de Código: Utiliza un editor de código de tu elección. Recomiendo Visual Studio Code, que es gratuito y fácil de usar.&lt;/p&gt;

&lt;p&gt;Crear la Estructura de Carpetas 3. Crea una Carpeta: En tu computadora, crea una carpeta para tu extensión. Nombremos esta carpeta "MiPrimeraExtension."&lt;/p&gt;

&lt;p&gt;Archivo de Manifiesto 4. Crear el Archivo de Manifiesto: En la carpeta "MiPrimeraExtension," crea un archivo llamado "manifest.json". El manifiesto es un archivo importante que define la extensión y sus propiedades.&lt;/p&gt;

&lt;p&gt;Editar el Manifiesto: Abre "manifest.json" en tu editor de código y agrega el siguiente código básico:&lt;/p&gt;

&lt;p&gt;json&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "manifest_version": 3,
  "name": "Mi Primera Extensión",
  "version": "1.0",
  "description": "Una extensión simple de Chrome",
  "permissions": [
    "activeTab"
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "images/icon16.png",
      "48": "images/icon48.png",
      "128": "images/icon128.png"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código define información básica sobre la extensión, como su nombre y descripción, así como los íconos y la página emergente.&lt;/p&gt;

&lt;p&gt;Archivo HTML para la Página Emergente 6. Crear la Página Emergente: En la misma carpeta, crea un archivo llamado "popup.html." Esta será la página que aparecerá cuando hagas clic en el ícono de la extensión.&lt;/p&gt;

&lt;p&gt;Editar la Página Emergente: Abre "popup.html" y agrega el siguiente código HTML simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Mi Extensión&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Hola, esta es tu primera extensión de Chrome.&amp;lt;/h1&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Íconos para la Extensión 8. Preparar Íconos: Crea tres imágenes PNG para los íconos de la extensión con tamaños de 16x16, 48x48 y 128x128 píxeles. Guárdalas en una carpeta llamada "images" dentro de tu carpeta "MiPrimeraExtension."&lt;/p&gt;

&lt;p&gt;Cargar la Extensión 9. Acceder a Chrome: Abre Google Chrome y visita "chrome://extensions/". Asegúrate de que la casilla de "Modo de desarrollador" esté marcada en la esquina superior derecha.&lt;/p&gt;

&lt;p&gt;Cargar la Extensión: Haz clic en "Cargar extensión no empaquetada" y selecciona la carpeta "MiPrimeraExtension."&lt;/p&gt;

&lt;p&gt;Enlace de la entrada: &lt;a href="https://davdomin.blogspot.com/2023/10/como-crear-una-extension-para-chrome-en.html"&gt;davdomin.blogspot.com/2023/10/como-crear-una-extension-para-chrome-en.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Historia del "DLL Hell" a principios de los 90</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Wed, 18 Oct 2023 22:16:21 +0000</pubDate>
      <link>https://dev.to/davdomin/historia-del-dll-hell-a-principios-de-los-90-g8k</link>
      <guid>https://dev.to/davdomin/historia-del-dll-hell-a-principios-de-los-90-g8k</guid>
      <description>&lt;p&gt;Las DLLs se introdujeron por primera vez en Windows 3.1 en 1992. Las DLLs permiten a los desarrolladores compartir código entre diferentes aplicaciones, lo que reduce la cantidad de código que debe escribirse y mantener.&lt;/p&gt;

&lt;p&gt;En los primeros años de Windows, el infierno de las DLLs era un problema relativamente común. Esto se debía a que los desarrolladores no estaban familiarizados con las DLLs y no siempre tomaban las medidas necesarias para evitar conflictos.&lt;/p&gt;

&lt;p&gt;Por ejemplo, un desarrollador podría instalar una DLL que proporciona una nueva función para una aplicación. Sin embargo, si otra aplicación ya está utilizando una DLL que proporciona la misma función, podría producirse un conflicto.&lt;br&gt;
**&lt;br&gt;
La introducción del Windows DLL Manager**&lt;/p&gt;

&lt;p&gt;Microsoft ha tomado medidas para abordar el problema del infierno de las DLLs. En Windows 95, se introdujo el sistema de administración de DLLs de Windows (Windows DLL Manager). Este sistema ayuda a evitar conflictos al resolver automáticamente qué DLL se debe cargar en caso de conflicto.&lt;/p&gt;

&lt;p&gt;El Windows DLL Manager funciona asignando un número de versión a cada DLL. Cuando un programa intenta cargar una DLL, el Windows DLL Manager busca la DLL con el número de versión más alto.&lt;/p&gt;

&lt;p&gt;Si hay varias DLLs con el mismo número de versión, el Windows DLL Manager intentará resolver el conflicto utilizando un algoritmo de resolución de conflictos.&lt;/p&gt;

&lt;p&gt;El infierno de las DLLs sigue siendo un problema potencial en los sistemas operativos de Microsoft. Esto se debe a que los desarrolladores aún pueden instalar DLLs que tienen el mismo nombre o versión.&lt;/p&gt;

&lt;p&gt;Además, el Windows DLL Manager no siempre es capaz de resolver todos los conflictos de DLLs.&lt;/p&gt;

&lt;p&gt;Aquí hay algunos ejemplos de cómo el infierno de las DLLs puede causar problemas:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Una aplicación puede dejar de funcionar o incluso bloquearse.
El sistema operativo puede mostrar un error o una pantalla azul de la muerte.
El sistema operativo puede ralentizarse o incluso dejar de responder.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Post completo: &lt;a href="https://davdomin.blogspot.com/2023/10/historia-del-dll-hell-principios-de-los.html"&gt;davdomin.blogspot.com/2023/10/historia-del-dll-hell-principios-de-los.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dll</category>
      <category>gestion</category>
      <category>dependencias</category>
    </item>
    <item>
      <title>Nuevas características y correcciones en la documentación y componentes de Quasar</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Wed, 18 Oct 2023 02:19:28 +0000</pubDate>
      <link>https://dev.to/davdomin/nuevas-caracteristicas-y-correcciones-en-la-documentacion-y-componentes-de-quasar-4oeh</link>
      <guid>https://dev.to/davdomin/nuevas-caracteristicas-y-correcciones-en-la-documentacion-y-componentes-de-quasar-4oeh</guid>
      <description>&lt;p&gt;&lt;strong&gt;Quasar&lt;/strong&gt; es un framework de desarrollo web y móvil de código abierto que utiliza Vue.js. Es conocido por su facilidad de uso, su rendimiento y su amplia gama de características.&lt;/p&gt;

&lt;p&gt;El equipo de Quasar ha estado trabajando en algunas nuevas características y correcciones para la documentación y los componentes del framework. Algunas de estas novedades ya están disponibles, mientras que otras se lanzarán con futuras versiones de Quasar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nuevas características&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**    Nuevos idiomas:** La documentación ahora admite alemán (Suiza) y alemán (Alemania).&lt;br&gt;
**    Prop rawSort de QTable**: El componente QTable ahora tiene una nueva prop rawSort que se puede utilizar para ordenar filas con valores null o undefined.&lt;/p&gt;

&lt;p&gt;Fuente:&lt;a href="https://davdomin.blogspot.com/2023/10/novedades-quasar-framework-v2130.html"&gt;https://davdomin.blogspot.com/2023/10/novedades-quasar-framework-v2130.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>quasarframework</category>
      <category>update</category>
    </item>
    <item>
      <title>Ubuntu Desktop 23.10 en la Mira: Lo que Necesitas Saber sobre las Traducciones Ofensivas</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Mon, 16 Oct 2023 03:06:52 +0000</pubDate>
      <link>https://dev.to/davdomin/ubuntu-desktop-2310-en-la-mira-lo-que-necesitas-saber-sobre-las-traducciones-ofensivas-4n41</link>
      <guid>https://dev.to/davdomin/ubuntu-desktop-2310-en-la-mira-lo-que-necesitas-saber-sobre-las-traducciones-ofensivas-4n41</guid>
      <description>&lt;p&gt;El mundo de la tecnología a menudo nos sorprende con desafíos inesperados, y la comunidad de Ubuntu Desktop no ha sido la excepción. En una reciente actualización, se ha detectado un incidente de traducción maliciosa que afecta a la versión 23.10 de Ubuntu Desktop. A continuación, te proporcionamos detalles clave sobre este incidente y las medidas tomadas para abordarlo.&lt;/p&gt;

&lt;p&gt;Un colaborador de la comunidad envió traducciones ofensivas en ucraniano a un servicio en línea de terceros que se utiliza para brindar soporte de idioma para el instalador de Ubuntu Desktop. Apenas tres horas después del lanzamiento de Ubuntu 23.10, este hecho llamó la atención de la comunidad, y se tomaron medidas inmediatas para eliminar las imágenes afectadas.&lt;/p&gt;

&lt;p&gt;Seguir leyendo: &lt;a href="https://davdomin.blogspot.com/2023/10/nuevo-ubuntu-2310-mantic-minotaur.html"&gt;https://davdomin.blogspot.com/2023/10/nuevo-ubuntu-2310-mantic-minotaur.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>El Operador ternario en programación: Historia, ventajas y usos en diferentes lenguajes</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Thu, 12 Oct 2023 23:11:38 +0000</pubDate>
      <link>https://dev.to/davdomin/el-operador-ternario-en-programacion-historia-ventajas-y-usos-en-diferentes-lenguajes-2oe0</link>
      <guid>https://dev.to/davdomin/el-operador-ternario-en-programacion-historia-ventajas-y-usos-en-diferentes-lenguajes-2oe0</guid>
      <description>&lt;p&gt;En el mundo de la programación, los operadores son herramientas esenciales para tomar decisiones y simplificar el código. Uno de los operadores más interesantes es el llamado "operador ternario". Personalmente, descubrí su existencia en 2012 mientras trabajaba en Yarkan, gracias a mi amigo Angel Ybarbhuen, quien me enseñó cómo usarlo. Desde entonces, el operador ternario se ha convertido en una parte fundamental de mi arsenal de programación. En este artículo, exploraremos su historia, ventajas y cómo se utiliza en diferentes lenguajes de programación.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Historia del Operador Ternario:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;El operador ternario tiene una historia fascinante que se remonta a los primeros lenguajes de programación. Su origen se encuentra en el lenguaje de programación C, donde se introdujo por primera vez. A medida que los lenguajes evolucionaron, el operador ternario se incorporó a muchos de ellos debido a su eficacia en la escritura de código conciso y legible.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;¿Qué es el Operador Ternario?:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nota completa: &lt;a href="https://davdomin.blogspot.com/2023/10/el-operador-ternario-en-programacion.html"&gt;davdomin.blogspot.com/2023/10/el-operador-ternario-en-programacion.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>El Anuncio de Microsoft: Microsoft Build for OpenJDK 21</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Thu, 12 Oct 2023 18:55:07 +0000</pubDate>
      <link>https://dev.to/davdomin/el-anuncio-de-microsoft-microsoft-build-for-openjdk-21-1o8p</link>
      <guid>https://dev.to/davdomin/el-anuncio-de-microsoft-microsoft-build-for-openjdk-21-1o8p</guid>
      <description>&lt;p&gt;La industria tecnológica nunca deja de sorprendernos, y una de las últimas noticias emocionantes es el anuncio de Microsoft sobre la disponibilidad de su propia versión de OpenJDK 21, conocida como "Microsoft Build for OpenJDK 21". En este artículo, exploraremos esta noticia y lo que significa para la comunidad de desarrolladores.&lt;/p&gt;

&lt;p&gt;Microsoft se une a la fiebre de Java 21:&lt;br&gt;
Justo después del lanzamiento de la plataforma Java 21 por parte de Oracle, Microsoft ha dado un paso al frente al ofrecer su propia versión de OpenJDK 21 de forma gratuita. Esta noticia es un hito importante, ya que Microsoft está brindando a la comunidad de desarrolladores acceso gratuito a esta tecnología.&lt;/p&gt;

&lt;p&gt;Características destacadas:&lt;br&gt;
La versión de Microsoft Build for OpenJDK 21 trae consigo algunas características emocionantes que la diferencian de las versiones anteriores de Java. Algunas de las novedades incluyen:&lt;/p&gt;

&lt;p&gt;Articulo completo &lt;a href="https://davdomin.blogspot.com/2023/10/microsoft-ofrece-descarga-gratuita-de.html"&gt;davdomin.blogspot.com/2023/10/microsoft-ofrece-descarga-gratuita-de.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jdk</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Mi Viaje como Programador: Desde QBasic hasta la Era de la Inteligencia Artificial</title>
      <dc:creator>David Dominguez</dc:creator>
      <pubDate>Thu, 12 Oct 2023 03:29:40 +0000</pubDate>
      <link>https://dev.to/davdomin/mi-viaje-como-programador-desde-qbasic-hasta-la-era-de-la-inteligencia-artificial-5279</link>
      <guid>https://dev.to/davdomin/mi-viaje-como-programador-desde-qbasic-hasta-la-era-de-la-inteligencia-artificial-5279</guid>
      <description>&lt;p&gt;Mi viaje como programador comenzó en un momento muy diferente al que vivimos hoy en día. En los primeros días, no había tutoriales en línea ni la capacidad de buscar instantáneamente soluciones en la web. Todo lo que teníamos eran libros y la curiosidad para aprender. En esta entrada, compartiré mi emocionante y enriquecedor viaje desde mis humildes comienzos en QBasic hasta la emocionante era de la programación en Internet. A lo largo de los años, he experimentado cambios radicales en la tecnología y en la forma en que abordo la programación, y quiero compartir cómo esto ha moldeado mi carrera.&lt;/p&gt;

&lt;p&gt;Los Primeros Pasos con QBasic:&lt;br&gt;
Recuerdo con cariño mis primeros pasos en la programación con QBasic. Fue una época en la que pasaba horas escribiendo líneas de código y experimentando con programas sencillos. Fue mi padre quien me introdujo en el mundo de la programación. Me enseñó cómo crear un programa que solicitaba tu año de nacimiento y calculaba automáticamente tu edad. Este fue mi primer proyecto real, y me enseñó las bases de la lógica de programación.&lt;/p&gt;

&lt;p&gt;Sigue leyendo : &lt;a href="https://davdomin.blogspot.com/2023/10/de-qbasic-la-era-de-internet-mi-viaje.html"&gt;davdomin.blogspot.com/2023/10/de-qbasic-la-era-de-internet-mi-viaje.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
