<?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: Benjamin Savoy</title>
    <description>The latest articles on DEV Community by Benjamin Savoy (@benjaminsavoy).</description>
    <link>https://dev.to/benjaminsavoy</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%2F3709493%2F7b7cf7f8-b14e-4740-8639-6b8a22dc28c9.jpg</url>
      <title>DEV Community: Benjamin Savoy</title>
      <link>https://dev.to/benjaminsavoy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/benjaminsavoy"/>
    <language>en</language>
    <item>
      <title>#2 - Going to second base: know your boundaries</title>
      <dc:creator>Benjamin Savoy</dc:creator>
      <pubDate>Tue, 10 Feb 2026 17:38:38 +0000</pubDate>
      <link>https://dev.to/benjaminsavoy/2-going-to-second-base-know-your-boundaries-4ea7</link>
      <guid>https://dev.to/benjaminsavoy/2-going-to-second-base-know-your-boundaries-4ea7</guid>
      <description>&lt;p&gt;... or you'll end up with a monkey patching your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, we've got to get intimate...
&lt;/h2&gt;

&lt;p&gt;For today's cautionary tale, let me draw a parallel. You've gone on a few dates, all is going well, but you're not sure if you should go home with your date. After all, you hardly know them. How do you navigate that?&lt;/p&gt;

&lt;p&gt;Over the last couple of articles, we've gotten acquainted with the code that the LLM wrote, but we haven't read a single line yet. If there were huge red flags, maybe we've spotted some already, but could there be something more sinister hiding in plain sight? Is it time to open up the files and look at actual code?&lt;/p&gt;

&lt;p&gt;Well, hopefully you've sorted out the structural issues with your project, so let's go and ask a few probing questions...&lt;/p&gt;

&lt;h2&gt;
  
  
  What was your name again?
&lt;/h2&gt;

&lt;p&gt;Ouch. If I had a dollar for every time I forgot the name of someone that I should know... But naming things turns out to be quite important for us too. Let's grab a poorly written Python method signature as an example:&lt;br&gt;
&lt;/p&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_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What was his name again... Jim, Jeff, Geoff, Jean? Well... you get what I mean, hopefully, and I wouldn't fault you for not knowing what this method does, either.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Customer&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;discount_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DiscountCode&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt; 
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProcessedOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;shipping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;processed_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
    &lt;span class="n"&gt;discount_applied&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DiscountCode&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;inventory_reserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderProcessor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;discount_rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DiscountRules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;shipping_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ShippingPolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;InventoryService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&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;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ProcessedOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without even writing any of the implementation, I've already given you enough data to have a plausible opinion about what it should do. You could then likely test it without really looking at what's inside, and that's what matters. If you know the business logic, and have detailed signatures  like we have above, then you're ready to move on to the next step!&lt;/p&gt;

&lt;h2&gt;
  
  
  Size matters
&lt;/h2&gt;

&lt;p&gt;Well, we've got a &lt;code&gt;process&lt;/code&gt; method with some boundaries now, but we're still not looking at instructions. Let's assume &lt;code&gt;process&lt;/code&gt; is a large method. Inevitably... it might well be if it's trying to do too much at the same time.&lt;/p&gt;

&lt;p&gt;So we've got to put some limits too, and maybe we don't want the process method to worry about too many things at once. Maybe just calling different methods that worry about individual elements like discounts, shipping, and so on.&lt;br&gt;
&lt;/p&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;_calculate_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_apply_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DiscountCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_determine_shipping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_reserve_inventory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phew. Now everything's settled. That's a much better structure to see in your generated code. If it feels like a method is a bit long, or doing more than one clear thing, it probably needs looking at. Even without reading any of the code, I can tell you that I'd expect something looking roughly like the above for such an order processing class.&lt;/p&gt;

&lt;h2&gt;
  
  
  It pays to have taste
&lt;/h2&gt;

&lt;p&gt;Also, did I mention how nested loops and &lt;code&gt;continue&lt;/code&gt; / &lt;code&gt;break&lt;/code&gt; keywords are a pet peeve of mine? Yeah, that's a red flag too. You don't want to be nesting too many things at once. In code, or dating. Believe me.&lt;/p&gt;

&lt;p&gt;I did mention above that I'd expect a few methods to be present to break the flow, but in the end it's experience talking. You have to read and write code a fair bit to get there, but that's part of the beauty of this job. However, when you do refactor or write code, there's a few constraints you can put on yourself, which may be helpful in getting to a better state and therefore learn as you do.&lt;br&gt;
&lt;/p&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;get_eligible_totals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;totals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;orders&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;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;discount_code&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;continue&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_discount_rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;discount_code&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;qty&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;qty&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&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="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;totals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;totals&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's going on there? Well, you tell me. But if that hurts your brain, don't spend too much time on the above and read what follows:&lt;br&gt;
&lt;/p&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;get_eligible_totals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;eligible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_has_valid_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;totals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_calculate_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;eligible&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;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;totals&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&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="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_has_valid_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_calculate_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did you notice the bug in the first method, too? In the original, &lt;code&gt;break&lt;/code&gt; exits the inner item loop entirely. So if the third item has a negative price, items four, five, and six never get counted. Knowing what your language allows (in this case list comprehensions) and avoiding smelly keywords (global, break, continue, etc...) will get you there, at least some of the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;datetime.now()&lt;/code&gt;, I hardly knew thee
&lt;/h2&gt;

&lt;p&gt;So now that we've got a feel for structure and taste, let's talk about the things hiding deeper. The places where your code reaches out and touches the real world.&lt;/p&gt;

&lt;p&gt;Time is the classic offender. A &lt;code&gt;datetime.now()&lt;/code&gt; buried three layers deep means your code behaves differently every time you run it. Randomness is the same problem wearing a different hat. Configuration is a bit more predictable but can still sneak up on you. Then your tests start to break because it's January and someone decided to compare the months in a date object. I wish I was making this up.&lt;/p&gt;

&lt;p&gt;IO, filesystem, network calls, external services, mutable state, user input, build environment... they're all boundaries too. Some obvious, some less so. But they all reduce to one question: can I control this from a test? If you can't swap it out, it's not a boundary, it's a leak. And would you trust a monkey with a wrench to fix it? Well, I wouldn't, and I wouldn't monkey patch it either.&lt;/p&gt;

&lt;p&gt;Oh, and keep your eyes open for those red flags: nested loops, giant methods, untyped data, hardcoded values, hidden dependencies. They're the crumbs which feed the little bugs...&lt;/p&gt;

&lt;h2&gt;
  
  
  Robots have no taste... or if they did they'd be brutalists.
&lt;/h2&gt;

&lt;p&gt;Someone else did it wrong at least once in the training data, and therefore, you must now suffer the consequences.&lt;/p&gt;

&lt;p&gt;And hey, if you can explain those key common problems to your LLM and configure a competent software engineer AI agent as a result, you'll probably save yourself some time. But agents are a topic in and of their own which is better addressed in its own post.&lt;/p&gt;

&lt;p&gt;Oh, did you notice how I didn't address the missing Clock in the &lt;code&gt;OrderProcessor&lt;/code&gt; class? Well, that's something you'd want to inject in C# or other languages, but sometimes, no matter how much you think a particular Dutch person is wrong, there's no need to get angry and the best course of action is just let them drive slowly on the motorway. They're on holidays, and you can't worry about every time someone else is wrong.&lt;/p&gt;

&lt;p&gt;Same goes for (some) Python conventions. So relax, chill out, and go along with &lt;code&gt;freezegun&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Until next time...&lt;/p&gt;

&lt;p&gt;~ Ben&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>software</category>
      <category>productivity</category>
    </item>
    <item>
      <title>#1 - Spot problems before reading any code</title>
      <dc:creator>Benjamin Savoy</dc:creator>
      <pubDate>Wed, 21 Jan 2026 20:06:21 +0000</pubDate>
      <link>https://dev.to/benjaminsavoy/1-spot-problems-before-reading-any-code-ce3</link>
      <guid>https://dev.to/benjaminsavoy/1-spot-problems-before-reading-any-code-ce3</guid>
      <description>&lt;p&gt;Last week we started with a strong claim: You don't need to read every line. But now we've got to substantiate it. So, today, I'll show you a few ways to spot issues without even looking at the code. That's particularly interesting with LLMs as you might want to try coding in a language that you don't even know yet. I do believe that it's entirely possible, as long as you have an adequate amount of software engineering experience. I have myself experimented with game development in Rust (assisted by Claude), but more on that later with a practical example...&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure is documentation
&lt;/h2&gt;

&lt;p&gt;You've probably already heard of MVC (model, view, controller) which is a popular way to organise web applications. It does separate the concerns in three distinct buckets. There are of course many more approaches, all with different advantages for different kinds of software. The goal here isn't for me to preach what the best approach is, but that whatever approach is used should be obvious from looking at the file tree.&lt;/p&gt;

&lt;p&gt;For example, let's take a basic MVC webapp filetree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MyApp/
├── src/
│   └── MyApp.Web/
│       ├── Controllers/
│       │   ├── HomeController.cs
│       │   ├── OrdersController.cs
│       │   └── UsersController.cs
│       ├── Models/
│       │   ├── Order.cs
│       │   ├── User.cs
│       │   └── ViewModels/
│       │       ├── OrderSummaryViewModel.cs
│       │       └── UserProfileViewModel.cs
│       ├── Views/
│       │   ├── Home/
│       │   │   └── Index.cshtml
│       │   ├── Orders/
│       │   │   ├── Index.cshtml
│       │   │   └── Details.cshtml
│       │   ├── Users/
│       │   │   └── Profile.cshtml
│       │   └── Shared/
│       │       ├── _Layout.cshtml
│       │       └── _ValidationScripts.cshtml
│       ├── Services/
│       │   ├── IOrderService.cs
│       │   ├── OrderService.cs
│       │   ├── IUserService.cs
│       │   └── UserService.cs
│       ├── Data/
│       │   ├── AppDbContext.cs
│       │   └── Repositories/
│       │       ├── IOrderRepository.cs
│       │       └── OrderRepository.cs
│       ├── wwwroot/
│       │   ├── css/
│       │   ├── js/
│       │   └── images/
│       ├── Program.cs
│       ├── appsettings.json
│       └── MyApp.Web.csproj
├── tests/
│   └── MyApp.Tests/
│       ├── Controllers/
│       ├── Services/
│       └── MyApp.Tests.csproj
├── README.md
├── Makefile
├── docker-compose.yml
└── MyApp.sln
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How much can you infer from just the file tree? Hopefully a fair bit already. Requests likely come from &lt;code&gt;Controllers&lt;/code&gt;. The state should hopefully be self-contained in &lt;code&gt;Data&lt;/code&gt;. &lt;code&gt;Services&lt;/code&gt; handle the business logic - hopefully in a stateless manner since we have a separate &lt;code&gt;Data&lt;/code&gt; directory. &lt;code&gt;Views&lt;/code&gt; are the glue between the &lt;code&gt;Controllers&lt;/code&gt; and the rest, indeed they map 1:1 so it's easy to track what goes where.&lt;/p&gt;

&lt;p&gt;Now you could decide that things that map 1:1 with each other should be in the same folder, and you wouldn't be wrong. The main point here is that structure should make it obvious where to look at the very least.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, it runs on your machine, but what about mine?
&lt;/h2&gt;

&lt;p&gt;You may have noticed a few more things at the root of this folder, which are quite helpful here.&lt;/p&gt;

&lt;p&gt;Seeing a Makefile makes me hope that I might find a way to build, test, and deploy this application. And hopefully the README.md file would provide the rest of the context needed for those tasks. It gives me hope that this repository might be self-contained and have all the instructions that I need to run it. However, remove the Makefile, and it's starting to look dicey. At best it seems like I'd have to read the whole README and copy paste commands from there. It does seem like a bit of a hassle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure is documentation, but what about documentation?
&lt;/h2&gt;

&lt;p&gt;Okay - I have a chip on my shoulder here. I hate to repeat myself. However, some people (including most LLMs) love to write a lot of documentation, and there might even be some people who enjoy reading it! Reality is, though, that if your file tree doesn't make sense, and then you have to look at documentation, you've already lost a fair chunk of time figuring how things are supposed to work. You're losing a lot of clarity about where you should store new code. And that does compound quite quickly, every new hire, every time you forget about an old legacy repository, the process repeats itself.&lt;/p&gt;

&lt;p&gt;Moving and restructuring files around is usually the first step I take when faced with a complex legacy codebase, because it lets me tackle self-contained problems one by one. You're then no longer dealing with spaghetti, but small self-contained problems. And if you're not, the (hopefully) few files that really don't fit might well be the main problem you've got to tackle... leaving the rest mostly as-is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging without reading, really?
&lt;/h2&gt;

&lt;p&gt;I've tried some game development in Rust, without knowing anything about the language. Claude Code did most of the work and as I troubleshoot things, I kept noticing that my previous engineering experience was applicable even if I didn't read any code. I was merely looking at the file tree, Claude Code, and launching the game every now and then.&lt;/p&gt;

&lt;p&gt;But what I found out is that most bugs that arose as the game became a bit more complex were simply due to a lack of separation of concerns. &lt;/p&gt;

&lt;p&gt;Every iteration, I'm adding a new UI element, a new kind of object in the game, a new mechanic, but it seems that LLMs are not that great at designing things iteratively like that with an eye for the future. And then, boom, I could click on things in game but the map would jitter all around the place, pop ups wouldn't be displayed, and some buttons I just implemented were not working anymore. It was a nightmare, but then I looked at the file structure.&lt;/p&gt;

&lt;p&gt;Odd, I have a new file for the game settings panel I just added. I have a file for the map generation... but it's all in the same folder and there's no UI module. Let alone multiple UI modules. Every file was trying to define a bit of the UI and ultimately ended up being inconsistent.&lt;/p&gt;

&lt;p&gt;A simple prompt to modularise the game, including a UI module with several files each dealing with a separate part of the UI and a reminder to check for inconsistencies quickly dealt with the buggy UI and Claude went on implementing many more features with way fewer bugs from that point on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure is your map (and a few red flags)
&lt;/h2&gt;

&lt;p&gt;Before I leave you for today, let me give you a few red flags that you can quickly check and apply to your output, and see if it helps you iterate faster with LLMs! Here's what could be a sign for concern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No clear separation of concerns&lt;/li&gt;
&lt;li&gt;Inconsistent names&lt;/li&gt;
&lt;li&gt;Large files (500+ lines)&lt;/li&gt;
&lt;li&gt;Missing/mismatched directories (for tests and others)&lt;/li&gt;
&lt;li&gt;Lack of build/run automation and instructions&lt;/li&gt;
&lt;li&gt;No clear entry points (APIs, CLI, DBs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can't see the architecture from the file tree, something's wrong! Until next week...&lt;/p&gt;

&lt;p&gt;~ Ben&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>software</category>
      <category>productivity</category>
    </item>
    <item>
      <title>#0 - You don't have to read every line</title>
      <dc:creator>Benjamin Savoy</dc:creator>
      <pubDate>Tue, 13 Jan 2026 18:03:03 +0000</pubDate>
      <link>https://dev.to/benjaminsavoy/you-dont-have-to-read-every-line-4e5b</link>
      <guid>https://dev.to/benjaminsavoy/you-dont-have-to-read-every-line-4e5b</guid>
      <description>&lt;h2&gt;
  
  
  Every day is your first day
&lt;/h2&gt;

&lt;p&gt;Allow me to use your mind for a second for a thought experiment. &lt;/p&gt;

&lt;p&gt;If you're starting a new job contributing to a codebase, would you read every line in existence before pushing a change? Or every line in the module you are changing? Or every line of the function that you're supposed to alter?&lt;/p&gt;

&lt;p&gt;The degree of precision required will vary depending on your task, of course, but I don't think many of us have the luxury of reading every line that exists in the project before getting started on a change.&lt;/p&gt;

&lt;p&gt;Now, what if I told you that the code was written by the best software engineer in existence, would it ease your mind? What if it was all written by an intern - or what if it was all AI-generated?&lt;/p&gt;

&lt;p&gt;Hopefully, by now, you're starting to catch my drift... We've all seen horrible legacy codebases, intern code, and things that we wish we'd be able to forget. But that's not the end of the world, because...&lt;/p&gt;

&lt;h2&gt;
  
  
  Legacy Code Runs the World
&lt;/h2&gt;

&lt;p&gt;Legacy code is a good problem to have. That may not resonate with many of you, but having legacy code means that the company has survived long enough to deal with code that has fallen apart over time. And if you're tasked with migrating it or altering it, it probably means that there's still value to be extracted. &lt;/p&gt;

&lt;p&gt;We've all heard the tales of COBOL running on a mainframe to this day in many banks and Fortune 500 companies... and while one could speculate about their eventual downfall, the size of their revenue is undeniable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Self-Driving Car Problem
&lt;/h2&gt;

&lt;p&gt;Let's hop into another parallel for a second to illustrate a perception problem we might face. If you were given a fully autonomous car that you knew was just as safe as your driving, would you let it drive you around? What if it was ten times safer, or even a hundred times? &lt;/p&gt;

&lt;p&gt;For contrast, what if I proposed to replace all other cars on the road, with self-driving cars that are proven to be 25% safer than the average driver. Would you accept to drive in such conditions?&lt;/p&gt;

&lt;p&gt;I don't know what your answers are, and they might be very rational... but we have a human bias to overestimate how much control we have on the risks that we can affect through our behaviour. Therefore, it's quite possible that most people would refuse to be driven by an autonomous vehicle, even if they were rationally convinced that it would drive as safely as they personally would.&lt;/p&gt;

&lt;p&gt;So... the question is then, would you let a LLM code for you?&lt;/p&gt;

&lt;h2&gt;
  
  
  LLM Code Is Just Code You Didn't Write
&lt;/h2&gt;

&lt;p&gt;That brings us to my first real proposal. And if you're on the fence about LLMs, maybe you'll just have to try it out for yourself. Give one of the best and latest coding models a self-contained task in your codebase. Plan with it, and work with it to clarify the requirements. Then, once it produced a first version of the code, explain your coding standards and test requirements, and ask it to review itself. And finally, let it open a pull request, and see for yourself. Would you be mad if an intern wrote this? A junior engineer? One of your peers?&lt;/p&gt;

&lt;p&gt;You'd be right if you felt that this was a bit mechanical, after all you had to have a conversation about requirements, and also needed to explain coding and test standards. But don't worry, that can also be automated later on, and I'll explain how in later articles.&lt;/p&gt;

&lt;p&gt;So far we've just covered common thought experiments about legacy code and AI... but if you're having trouble letting go of controlling every line of code you're writing, you're not alone. I refused to use code generation much, until a very tight deadline came across my desk, and in a last ditch effort, I spun up Claude Sonnet 4.5 and worked a few late nights... and the backlog disappeared.&lt;/p&gt;

&lt;p&gt;Reviewing it, I realised I wouldn't be terribly disappointed if a junior or mid-level engineer wrote a PR like Claude Code did. Realistically, it was not too bad of an effort compared to what I could do at 9pm. And thus, the project was back on track, and I was a convert.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Questions
&lt;/h2&gt;

&lt;p&gt;After this experiment, hopefully you'll have seen some passable code being generated, like I did, and you're wondering what's next. After all, this might have just been an easy task, and the code is not as good as what you'd have written anyway.&lt;/p&gt;

&lt;p&gt;Then we have to ask, could the output be as good as yours or mine? Well, probably, given an unlimited amount of time iterating over the code and gathering feedback. &lt;/p&gt;

&lt;p&gt;But then, can we go much faster with those new tools, without losing much quality? &lt;/p&gt;

&lt;p&gt;I think so: It's just that you don't have to read every line.&lt;/p&gt;

&lt;p&gt;You'll have to ask yourself some difficult questions. For example, if you're dealing with legacy code, would you always rewrite the entirety of the solution for each migration? That would often be a waste of time. Therefore, that new tooling requires us to be a bit more creative in the way we validate the output. &lt;/p&gt;

&lt;p&gt;Fundamentally, at some point, it doesn't matter who wrote it. It matters that it works. But how do we know that it works? Well, that's where I will share with you some of my experience dealing with legacy code... but that will be for another post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's coming
&lt;/h2&gt;

&lt;p&gt;I hope that this has been a pleasant introduction to the challenges that one might face when coding with LLMs. It may be a bit basic for some, and I'm sure you've thought some of those things, but now that we're all on the same page, here are a few things you can expect to see in the next few weeks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spot problems before reading any code&lt;/li&gt;
&lt;li&gt;Read code faster and catch more issues&lt;/li&gt;
&lt;li&gt;Write tests that verify behaviour&lt;/li&gt;
&lt;li&gt;Automate the feedback loop so the LLM reviews itself&lt;/li&gt;
&lt;li&gt;Remove yourself as the bottleneck&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See you next week for more.&lt;/p&gt;

&lt;p&gt;~ Ben&lt;/p&gt;

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