<?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: Eduardo Lázaro</title>
    <description>The latest articles on DEV Community by Eduardo Lázaro (@edulazaro).</description>
    <link>https://dev.to/edulazaro</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%2F540695%2F639d4891-8285-493b-8426-9ecec00f527f.png</url>
      <title>DEV Community: Eduardo Lázaro</title>
      <link>https://dev.to/edulazaro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/edulazaro"/>
    <language>en</language>
    <item>
      <title>Stop Building Features: Start Building Patterns</title>
      <dc:creator>Eduardo Lázaro</dc:creator>
      <pubDate>Sun, 18 Jan 2026 01:48:44 +0000</pubDate>
      <link>https://dev.to/edulazaro/stop-building-features-start-building-patterns-2efl</link>
      <guid>https://dev.to/edulazaro/stop-building-features-start-building-patterns-2efl</guid>
      <description>&lt;p&gt;You know the feeling; you've integrated three payment providers, and each one has its own special snowflake implementation. Copy-paste, tweak and repeat. After six months, you're debugging the same bug in three different places, which is not funny.&lt;/p&gt;

&lt;p&gt;This is what happens when you optimize for speed without optimizing for coherence. Now, with AI generating code 10x faster than you, the problem is worse. AI doesn't know your patterns. It just generates what you ask for, three times, three different ways... if it's not in the context, it does not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern I Wish I'd Known Earlier
&lt;/h2&gt;

&lt;p&gt;Here's a real example from a property management system I built. The requirement was to sync properties across Airbnb, Booking.com and VRBO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before: The Spaghetti Pattern
&lt;/h3&gt;

&lt;p&gt;If you work on a team using Agile which is not quite well organized or used the first response AI provided, you might end up with this spaghetti approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Airbnb integration&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AirbnbService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$propertyId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AirbnbClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/listings/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$propertyId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'price_per_night'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="c1"&gt;// 50 lines of error handling...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Booking.com integration (completely different structure)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookingService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;syncPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$booking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BookingAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;rooms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'base_rate'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'currency'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'EUR'&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="c1"&gt;// Another 50 lines of error handling...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// VRBO integration (yet another approach)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VrboManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setPropertyPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$vrboId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$priceData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// You get the idea...&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;We have three integrations, with three patterns and three new places to fix bugs on. And when the PM asks "can we add Expedia?", you enter rage mode.&lt;/p&gt;

&lt;p&gt;This is what happens when you optimize for speed without optimizing for coherence.&lt;/p&gt;

&lt;h3&gt;
  
  
  After: The Pattern Approach
&lt;/h3&gt;

&lt;p&gt;The alternative is to build a pattern so the same logic or pattern can be followed for all platforms&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// One interface to rule them all&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Origin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;mixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Clean, consistent usage&lt;/span&gt;
&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'airbnb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'booking'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'vrbo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Or batch update&lt;/span&gt;
&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'airbnb'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'booking'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'vrbo'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Adding Expedia? Just implement the interface&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExpediaOrigin&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Origin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Done in 2 hours, not 2 weeks&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is the same, However we used just a single pattern., so there's also a single place to fix bugs on, except when they are aspecific for each platform. Your coding Agent can now generate new integrations that &lt;em&gt;actually follow your architecture&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ARC Methodology
&lt;/h2&gt;

&lt;p&gt;Agile does not work anymore in the ear of AI. It fixed velocity, but not consistency, so in the era of AI you can create a compelte mess using Agile while coding with AI at your company.&lt;/p&gt;

&lt;p&gt;To force the team to follow, we use a simple cycle called &lt;strong&gt;ARC&lt;/strong&gt;, which is composed of three stages:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Align: before coding
&lt;/h3&gt;

&lt;p&gt;Spent some time mapping the problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What do all these platforms have in common?&lt;/li&gt;
&lt;li&gt;What's different?&lt;/li&gt;
&lt;li&gt;What will we need in 6 months?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output a diagram showing &lt;code&gt;Source&lt;/code&gt; (the platform) -&amp;gt; &lt;code&gt;Origin&lt;/code&gt; (how we connect) -&amp;gt; Model (our data).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Realize: build the pattern + the feature together
&lt;/h3&gt;

&lt;p&gt;I didn't build the pattern first, then the features. I built them together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First I built the Airbnb integration + extracted the &lt;code&gt;Source&lt;/code&gt; interface.
2, Then built the booking integration using the interface and validated it worked.&lt;/li&gt;
&lt;li&gt;Refactored, as the interface wasn't quite right.&lt;/li&gt;
&lt;li&gt;Built the VRBO integration in 10 minutes suing the pattern I created.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key insight is that you discover the &lt;strong&gt;right abstraction&lt;/strong&gt; by building &lt;strong&gt;concrete things&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Consolidate: validate it scales
&lt;/h3&gt;

&lt;p&gt;After shipping, I validated the pattern against three criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether it handled edge cases I hadn't anticipated.&lt;/li&gt;
&lt;li&gt;Whether a new developer could understand it without asking me questions.&lt;/li&gt;
&lt;li&gt;Whether AI could generate new Origins correctly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrote a &lt;code&gt;.md&lt;/code&gt; file explaining the pattern, and now when I prompt Claude or Copilot with &lt;em&gt;"create a new Origin for X following this interface"&lt;/em&gt;, it works 95% of the time as I expected. Documentation is not just for humans, but for AI context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Multiplier
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. Without using this methodology, each new integration takes a lot fo time of custom code, and when using AI generated code, it can be inconsistent. My AI generated code usually needs a full rewrite unless I specify exactly what I want. The integration of these paltorms can takes around 2 weeks.&lt;/p&gt;

&lt;p&gt;Using a pattern, you first create the pattern assited wiht AI, integrating each platform in hours.&lt;/p&gt;

&lt;p&gt;The pattern becomes an instruction manual for AI. Instead of just saying a vague:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Jut build me an Airbnb integration bro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You say in more precise way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Implement the Origin interface for Airbnb.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if the &lt;code&gt;.claude&lt;/code&gt; file or the documentation is up to date you will not even need to specify that.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Extract a Pattern
&lt;/h2&gt;

&lt;p&gt;Not everything needs a pattern. Here's my rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First time&lt;/strong&gt;: Build it concrete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second time&lt;/strong&gt;: Notice the repetition, and if you foresee another one, extract the pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third time&lt;/strong&gt;: If you're still copy-pasting, extract the pattern 100% sure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are not over-engineering or building patterns &lt;em&gt;just in case&lt;/em&gt;. You build them when the duplication hurts.&lt;/p&gt;

&lt;h2&gt;
  
  
  To try this on the next sprint
&lt;/h2&gt;

&lt;p&gt;You don't need to adopt a whole new methodology. Just just need try this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Before coding&lt;/strong&gt;, spend some time mapping: what connects to what? What's the shape of this feature?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;While building&lt;/strong&gt;, ask: have I written this before? Is there a pattern emerging?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;After shipping&lt;/strong&gt;, check: could a new developer, or AI Agent, extend this without asking me questions?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That said, as opposed as it happens with Agile, new features, pure architectural features, can spawn at any point in time when needed. Coherence is the thing to maintain here, as speed is assumed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The outcome
&lt;/h2&gt;

&lt;p&gt;It's not a rigid process, and AI-generated code will actually fit the architecture more and more with each new feature, as opposed as most developers and fans of "clean code" and "do not comment your code" usually say. In addition, new team members will productive in days, not weeks.&lt;/p&gt;

&lt;p&gt;Do you think that Agile is already a thing of the past?&lt;/p&gt;

&lt;p&gt;*More on this approach: &lt;a href="https://thearcmethodology.com" rel="noopener noreferrer"&gt;The ARC Methodology&lt;/a&gt;, a framework about building coherent systems in the AI era.&lt;/p&gt;

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