<?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>Forem: André Luiz Lunelli</title>
    <description>The latest articles on Forem by André Luiz Lunelli (@andreluizlunelli).</description>
    <link>https://forem.com/andreluizlunelli</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%2F344626%2F81d47878-59b6-4c14-9a3a-f019e94456a3.jpeg</url>
      <title>Forem: André Luiz Lunelli</title>
      <link>https://forem.com/andreluizlunelli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andreluizlunelli"/>
    <language>en</language>
    <item>
      <title>DRY vs RUG — When Repeating Code Is Actually the Better Design</title>
      <dc:creator>André Luiz Lunelli</dc:creator>
      <pubDate>Tue, 10 Mar 2026 16:00:00 +0000</pubDate>
      <link>https://forem.com/andreluizlunelli/dry-vs-rug-when-repeating-code-is-actually-the-better-design-59hb</link>
      <guid>https://forem.com/andreluizlunelli/dry-vs-rug-when-repeating-code-is-actually-the-better-design-59hb</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;DRY is great when duplication creates maintenance risk. Like duplicating a domain logic, like a discount.&lt;br&gt;&lt;br&gt;
But sometimes repetition is the better design.&lt;/p&gt;

&lt;p&gt;A useful mental model is &lt;strong&gt;RUG — Repeat Until Good.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of prematurely extracting abstractions, allow small duplication until the design becomes obvious.&lt;/p&gt;

&lt;p&gt;Blindly chasing DRY can lead to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fragile abstractions.
&lt;/li&gt;
&lt;li&gt;Hidden intent.
&lt;/li&gt;
&lt;li&gt;Tight coupling between unrelated parts of the system.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sometimes, &lt;strong&gt;explicit repetition makes the code clearer and more resilient.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Read the Full Thing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DRY — Don't Repeat Yourself&lt;/strong&gt; — is one of the most widely taught principles in software engineering.&lt;/p&gt;

&lt;p&gt;And for good reason.&lt;/p&gt;

&lt;p&gt;When the same logic is duplicated in multiple places, changing behavior becomes risky. One fix may require updates across several locations, increasing the chance of bugs and inconsistencies. That’s where DRY shines.&lt;/p&gt;

&lt;p&gt;But there's a less discussed idea that appears in some engineering discussions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RUG — Repeat Until Good.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s not a formally established principle like DRY, and you won’t find tons of articles about it. But the idea is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sometimes repetition is the safest way to let a design evolve.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of abstracting too early, you allow the code to repeat until the correct abstraction &lt;strong&gt;naturally emerges.&lt;/strong&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  The risk of blindly applying DRY
&lt;/h3&gt;

&lt;p&gt;When we try too hard to eliminate duplication, we often end up creating &lt;em&gt;fragile abstractions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You may have seen nested method calls like this:&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="nc"&gt;Controller&lt;/span&gt;
  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt;
      &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nc"&gt;Manager&lt;/span&gt;
          &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nc"&gt;Helper&lt;/span&gt;
              &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nc"&gt;Interface&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine trying to assemble all the parts in order to understand a simple behavior. And to be honest, frequently when I'm making maintenance in legacy codebases, I often find myself asking Claude to explain the whole feature—what it’s about—because the code is more of a puzzle than explicit logic.&lt;/p&gt;

&lt;p&gt;Sometimes those abstractions exist only to remove a few repeated lines of code.&lt;/p&gt;

&lt;p&gt;They don’t add real value to the product.&lt;br&gt;&lt;br&gt;
They just &lt;strong&gt;hide the intent somewhere else.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And in many cases, they introduce something worse:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tight coupling.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suddenly, multiple parts of the system depend on the same abstraction — and changing it can create unintended side effects.&lt;/p&gt;


&lt;h3&gt;
  
  
  When repetition is actually safer
&lt;/h3&gt;

&lt;p&gt;A good example appears in request validation.&lt;/p&gt;

&lt;p&gt;In Laravel, it's common to use Form Request classes.&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StoreUserRequest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FormRequest&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;rules&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&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="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'birth_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'before:today'&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;Now imagine you have another request with a &lt;em&gt;very similar validation.&lt;/em&gt;&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdateUserProfileRequest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FormRequest&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;rules&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&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="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'birth_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'before:today'&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;Yes — there is duplication.&lt;/p&gt;

&lt;p&gt;But extracting a shared abstraction for this might actually &lt;strong&gt;increase coupling between unrelated requests.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you change validation in one request, you probably don’t want to affect all the others.&lt;/p&gt;

&lt;p&gt;Keeping them separate means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changes stay &lt;strong&gt;localized&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Behavior is &lt;strong&gt;explicit&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The system becomes more &lt;strong&gt;resilient&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes &lt;strong&gt;repetition protects isolation.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A practical rule of thumb
&lt;/h3&gt;

&lt;p&gt;Use &lt;strong&gt;DRY&lt;/strong&gt; when dealing with &lt;strong&gt;domain or business logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;RUG&lt;/strong&gt; in &lt;strong&gt;scaffolding code&lt;/strong&gt; when repetition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps logic explicit&lt;/li&gt;
&lt;li&gt;Avoids unnecessary coupling&lt;/li&gt;
&lt;li&gt;Makes the code easier to understand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is recognizing that &lt;strong&gt;not all duplication is bad.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes the best abstraction is the one that doesn’t exist yet.&lt;/p&gt;




&lt;p&gt;To finish this thought, I always remember an idea that stuck with me while I was growing as a decision-maker in my roles:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good code is the code that is easy to throw away.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not because we want to delete it. But when code is simple, explicit, and loosely coupled, it becomes safe to change, safe to replace, and safe to evolve.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>architecture</category>
      <category>software</category>
      <category>coding</category>
    </item>
    <item>
      <title>Why Passing Eloquent Models to Queued Jobs Can Be Problematic</title>
      <dc:creator>André Luiz Lunelli</dc:creator>
      <pubDate>Fri, 06 Mar 2026 01:35:52 +0000</pubDate>
      <link>https://forem.com/andreluizlunelli/why-passing-eloquent-models-to-queued-jobs-can-be-problematic-26m7</link>
      <guid>https://forem.com/andreluizlunelli/why-passing-eloquent-models-to-queued-jobs-can-be-problematic-26m7</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;Avoid dispatching jobs with full Eloquent models.&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="nc"&gt;SendOrderConfirmation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&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;Instead, pass only what the job actually needs.&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="nc"&gt;SendOrderConfirmation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing models can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Increase queue payload size&lt;/li&gt;
&lt;li&gt;Break jobs after deployments&lt;/li&gt;
&lt;li&gt;Expose sensitive data in logs or failed jobs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Smaller payloads make your system more resilient, predictable, and safer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read the Full Thing
&lt;/h3&gt;

&lt;p&gt;I still see this pattern frequently in PRs. And to be clear — I'm not trying to turn this into a big issue. It works.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;But it can also introduce surprisingly large problems for such a small decision.&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Your queue payload may grow unexpectedly&lt;/strong&gt;&lt;br&gt;
And most of the time, this isn't intentional. In larger systems, it's easy to forget that a model may already have relationships loaded. Sometimes those relationships were loaded earlier in the request lifecycle — possibly by code you didn't even write.&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="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that user has 50 products loaded, those relationships may end up serialized as part of the job payload when the job is pushed to the queue — whether you're using Amazon SQS, Redis.&lt;/p&gt;

&lt;p&gt;Now the queue message contains far more data than the job actually needs.&lt;/p&gt;

&lt;p&gt;In many cases, the job only requires something simple like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the user id&lt;/li&gt;
&lt;li&gt;the order id&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Deployments can break queued jobs&lt;/strong&gt;&lt;br&gt;
Now imagine this sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A job is dispatched with a serialized model&lt;/li&gt;
&lt;li&gt;A new deployment happens&lt;/li&gt;
&lt;li&gt;The model structure changes&lt;/li&gt;
&lt;li&gt;The job retries and attempts to deserialize the old payload&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Suddenly, the worker cannot reconstruct the object correctly.&lt;/p&gt;

&lt;p&gt;This creates fragile jobs and reduces fault tolerance.&lt;br&gt;
Jobs should remain as independent and version-resilient as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Sensitive data may end up in queue logs&lt;/strong&gt;&lt;br&gt;
When a model is serialized, its attributes may appear inside the queue payload.&lt;/p&gt;

&lt;p&gt;That means information could show up in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;failed job logs&lt;/li&gt;
&lt;li&gt;queue dashboards (like &lt;a href="https://laravel.com/docs/master/horizon#main-content" rel="noopener noreferrer"&gt;Horizon&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;debugging tools&lt;/li&gt;
&lt;li&gt;dead-letter queues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In regulated environments like &lt;strong&gt;healthcare or finance&lt;/strong&gt;, this can become a compliance risk.&lt;/p&gt;

&lt;p&gt;Even if passwords are hashed, other fields may still contain &lt;strong&gt;personally identifiable information (PII)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Minimizing the data you send to queues helps protect your system.&lt;/p&gt;


&lt;h4&gt;
  
  
  A safer pattern
&lt;/h4&gt;

&lt;p&gt;Dispatch jobs with only the identifiers they need:&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="nc"&gt;SendOrderConfirmation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then resolve the model inside the job:&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&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="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&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;userId&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;This keeps your jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lighter&lt;/li&gt;
&lt;li&gt;safer&lt;/li&gt;
&lt;li&gt;easier to retry&lt;/li&gt;
&lt;li&gt;more resilient to change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes the best PR feedback is simply:&lt;/p&gt;

&lt;p&gt;“Do we really need to pass the whole model here?”&lt;/p&gt;

&lt;p&gt;Most of the time, the answer is no.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>redis</category>
      <category>php</category>
      <category>backend</category>
    </item>
    <item>
      <title>Stop Mixing UI Components With Business Logic</title>
      <dc:creator>André Luiz Lunelli</dc:creator>
      <pubDate>Wed, 04 Mar 2026 19:58:54 +0000</pubDate>
      <link>https://forem.com/andreluizlunelli/stop-mixing-ui-components-with-business-logic-9fj</link>
      <guid>https://forem.com/andreluizlunelli/stop-mixing-ui-components-with-business-logic-9fj</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;Separate your frontend components into two clear groups:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;components/
│
├── app/ → // components that encapsulate business logic
│   ├── AppliesCoupons.vue
│   └── SearchUserInput.vue
│
└── ui/  → // purely visual components
    ├── Badge.vue
    ├── Button.vue
    └── Input.vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fosters a clean architecture, and it works whether you're using Blade, Livewire, Vue, React, or anything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read the Full Thing
&lt;/h3&gt;

&lt;p&gt;At some point, I noticed something was bothering me in my projects.&lt;/p&gt;

&lt;p&gt;I was already using components everywhere. Buttons were components. Inputs were components. Modals were components.&lt;br&gt;
Don't get me wrong, that part was good.&lt;/p&gt;

&lt;p&gt;But I often found myself doing things like building a registration page where I had an input field that checked whether the email already existed in the database.&lt;/p&gt;

&lt;p&gt;So I would create something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RegisterEmailInput.vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside it, I'll add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debounce logic&lt;/li&gt;
&lt;li&gt;An API call&lt;/li&gt;
&lt;li&gt;Domain validation&lt;/li&gt;
&lt;li&gt;Error interpretation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This would definitely work. But something felt off.&lt;/p&gt;

&lt;p&gt;Was that really just an "input"? Or was it part of the application logic?&lt;/p&gt;

&lt;h4&gt;
  
  
  The Problem
&lt;/h4&gt;

&lt;p&gt;When everything lives inside the same &lt;code&gt;components/&lt;/code&gt; folder, you start losing clarity.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Button.vue&lt;/code&gt; and a &lt;code&gt;SearchUserInput.vue&lt;/code&gt; don’t belong to the same category of responsibility.&lt;/p&gt;

&lt;p&gt;One is visual. The other represents domain behavior.&lt;/p&gt;

&lt;p&gt;That’s when I made a structural change to the structure I use now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;components/
│
├── app/
│   ├── AppliesCoupons.vue
│   └── SearchUserInput.vue
│
└── ui/
    ├── Badge.vue
    ├── Button.vue
    └── Input.vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ui/&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Purely visual&lt;/li&gt;
&lt;li&gt;Reusable anywhere&lt;/li&gt;
&lt;li&gt;No API calls&lt;/li&gt;
&lt;li&gt;No domain knowledge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could copy them to another project and they would still work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app/&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Talks to APIs&lt;/li&gt;
&lt;li&gt;Applies business rules&lt;/li&gt;
&lt;li&gt;Knows about the domain&lt;/li&gt;
&lt;li&gt;Controls behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These components are not just UI.&lt;br&gt;
They represent application logic.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why This Matters
&lt;/h4&gt;

&lt;p&gt;This separation changes how you think.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Where do I put this component?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You start asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this visual, or does it represent domain behavior?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question alone improves architectural clarity.&lt;/p&gt;

&lt;p&gt;It also makes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactoring easier&lt;/li&gt;
&lt;li&gt;Testing more predictable&lt;/li&gt;
&lt;li&gt;Responsibilities clearer&lt;/li&gt;
&lt;li&gt;Code reviews more objective&lt;/li&gt;
&lt;li&gt;The codebase easier to navigate&lt;/li&gt;
&lt;li&gt;Feature responsibilities easier to understand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the best part?&lt;/p&gt;

&lt;p&gt;This approach works in: Laravel (Blade / Livewire), Vue, React or any other component-based frontend. Because this isn’t about framework.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>architecture</category>
      <category>cleancode</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Keep Code References Out of Your Migrations</title>
      <dc:creator>André Luiz Lunelli</dc:creator>
      <pubDate>Fri, 30 Jan 2026 15:30:28 +0000</pubDate>
      <link>https://forem.com/andreluizlunelli/keep-code-references-out-of-your-migrations-3pd</link>
      <guid>https://forem.com/andreluizlunelli/keep-code-references-out-of-your-migrations-3pd</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;Long story short, don't reference your business layer within migration files.&lt;/p&gt;

&lt;p&gt;Migrations should be immutable snapshots of your database history, never dependent on evolving application code.&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="err"&gt;❌&lt;/span&gt; &lt;span class="nf"&gt;Bad&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;breaks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;changes&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;removed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'role'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;array_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Can&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cases&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="nf"&gt;Good&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;explicitly&lt;/span&gt; &lt;span class="n"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stable&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;independent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'role'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'access_admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'can_impersonate'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Read the Full Thing
&lt;/h3&gt;

&lt;p&gt;Often, when we define enum values in a model, like a role property or a status for something, and we want to provide an input where the user can choose an option, it's a good practice to reference the enum class by using &lt;code&gt;foreach&lt;/code&gt; logic to iterate over these values to display them for the user. &lt;/p&gt;

&lt;p&gt;Something like:&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;// app/Enums/Role.php&lt;/span&gt;
&lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'access_admin'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Moderator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'can_impersonate'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'regular_user'&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{{-- resources/views/users/form.blade.php --}}
&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"role"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    @foreach(Role::cases() as $role)
        &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{ $role-&amp;gt;value }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            {{ str_replace('_', ' ', ucfirst($role-&amp;gt;value)) }}
        &lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    @endforeach
&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a good practice, isn't it? Can you imagine if, instead of iterating over an enum to get those values, you chose to rewrite the same occurrences in the whole project (backend, frontend)? Not cool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Migrations Are Different
&lt;/h3&gt;

&lt;p&gt;Migrations aren't like your application code - they're historical records of how your database evolved over time. Once a migration runs in production, it should never need to change.&lt;/p&gt;

&lt;h4&gt;
  
  
  Migrations should be your database changelog
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;They document every schema change over time&lt;/li&gt;
&lt;li&gt;With dynamic references, you lose that documentation&lt;/li&gt;
&lt;li&gt;You can't look at migrations and understand how the schema evolved &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Fragility
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Today: Your &lt;code&gt;Role&lt;/code&gt; enum has &lt;code&gt;admin&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt; values&lt;/li&gt;
&lt;li&gt;Migration runs: Creates column with those values, everything ok ✓&lt;/li&gt;
&lt;li&gt;6 months later: You rename &lt;code&gt;Role&lt;/code&gt; enum to &lt;code&gt;UserRole&lt;/code&gt;, or delete it entirely&lt;/li&gt;
&lt;li&gt;New developer runs migrations: 💥 Fatal error - Role class not found&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  As a result
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Forces us to edit old migrations&lt;/li&gt;
&lt;li&gt;Creates extra work&lt;/li&gt;
&lt;li&gt;Increases the risk of errors&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;Also, I'd avoid using &lt;a href="https://laravel.com/docs/master/migrations#column-method-foreignIdFor" rel="noopener noreferrer"&gt;foreignIdFor()&lt;/a&gt; because it couples the migration directly to a model. If that model is deleted or renamed, the migration becomes invalid.&lt;/p&gt;

&lt;p&gt;Well, that's all, folks.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>database</category>
      <category>software</category>
      <category>programming</category>
    </item>
    <item>
      <title>Cleaning up dates within Laravel Blade</title>
      <dc:creator>André Luiz Lunelli</dc:creator>
      <pubDate>Fri, 20 Jun 2025 02:57:23 +0000</pubDate>
      <link>https://forem.com/andreluizlunelli/cleaning-up-dates-within-laravel-blade-16hn</link>
      <guid>https://forem.com/andreluizlunelli/cleaning-up-dates-within-laravel-blade-16hn</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;So basically, you can use a &lt;a href="https://laravel.com/docs/12.x/blade#custom-echo-handlers" rel="noopener noreferrer"&gt;Custom Echo Handler&lt;/a&gt; to apply the same datetime format when printing &lt;a href="https://carbon.nesbot.com/docs/#api-formatting" rel="noopener noreferrer"&gt;Carbon&lt;/a&gt; instances within blade files.&lt;/p&gt;

&lt;p&gt;Instead of have something like this:&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;tr&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;created_at-&amp;gt;format('m/d/Y H:i') }}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;updated_at-&amp;gt;format('m/d/Y H:i') }}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;deleted_at-&amp;gt;format('m/d/Y H:i') }}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;email_verified_at-&amp;gt;format('m/d/Y H:i') }}&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can have this:&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;tr&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;created_at }}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;updated_at }}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;deleted_at }}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{{ $user-&amp;gt;email_verified_at }}&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// AppServiceProvider.php

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Blade;

public function boot(): void
{
    Blade::stringable(function (Carbon $carbon) {
        return $carbon-&amp;gt;format('m/d/Y H:i');
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read the Full Thing
&lt;/h3&gt;

&lt;p&gt;I went to review some pull requests, and there was one that had many carbon dates repeating the output format to display in the right US format.&lt;/p&gt;

&lt;p&gt;There isn't a real problem doing it that way; it's very straightforward. But it's boring. Can it be simpler? Let's give it a try.&lt;/p&gt;

&lt;p&gt;First, I tried to create a class that would inherit from the Carbon instance and override the &lt;code&gt;__toString&lt;/code&gt; method. You can do it in the &lt;code&gt;DateFactory&lt;/code&gt; by informing which class you want to use as concrete.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\Illuminate\Support\DateFactory::useClass(MyCarbonDate::class);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't like the idea of ending with a new class just to prevent me from typing the format of the datetimes. Seems like overengineering, so I decided to move on.&lt;/p&gt;

&lt;p&gt;Also, sniffing a little bit, I found that you can set a "toString" strategy using the Date facade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\Illuminate\Support\Facades\Date::setToStringFormat('m/d/Y H:i')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But who can say that it won't break anything else in the future, like, I don't know, some inner Laravel hydration thing. &lt;/p&gt;

&lt;p&gt;I need a simpler solution and don't want to reinvent the wheel. So  I remember about &lt;a href="https://laravel.com/docs/12.x/eloquent-mutators#main-content" rel="noopener noreferrer"&gt;Laravel Eloquent Casting&lt;/a&gt; and I saw the &lt;a href="https://laravel.com/docs/12.x/eloquent-mutators#date-casting" rel="noopener noreferrer"&gt;Date Casting&lt;/a&gt;. That is what I want!&lt;/p&gt;

&lt;p&gt;Eventually the code didn't work, and I went back to the docs to figure it why, and that was the reason:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This format will be used when the model is serialized to an array or JSON&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In summary, this is going to work through &lt;a href="https://laravel.com/docs/12.x/eloquent-resources#main-content" rel="noopener noreferrer"&gt;API Resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ok, maybe I'm overthinking this. Forget about it, let's move on. I started to do another daily task. But my brain still didn't give up; I was intrigued. How it's possible that anyone wanted to do this in their blade files?&lt;/p&gt;

&lt;p&gt;Ok, let's take only 5 minutes to look again at the docs, maybe I miss something. And I did :D &lt;/p&gt;

&lt;p&gt;At the blade section I could find the &lt;a href="https://laravel.com/docs/12.x/blade#custom-echo-handlers" rel="noopener noreferrer"&gt;Custom Echo Handlers&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This closure should type-hint the type of object that it is responsible for rendering.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But wait, it isn't working. Well, clearing the cache sometimes solves things. So I did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan view:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it works!&lt;/p&gt;

&lt;p&gt;It's nice to only type the variable that you wanna print, without always having to type the format every time, and with a chance to misspell the format. Additionally, if in the future I support another locale, I could even provide different formats based on this, something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Blade::stringable(function (Carbon $carbon) {
    if (app()-&amp;gt;getLocale() !== 'en') {
        return $carbon-&amp;gt;locale(app()-&amp;gt;getLocale())-&amp;gt;format('Y-m-d H:i');
    }

    return $carbon-&amp;gt;format('m/d/Y H:i');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all, folks.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>datetime</category>
      <category>carbon</category>
      <category>laravelblade</category>
    </item>
    <item>
      <title>whoami</title>
      <dc:creator>André Luiz Lunelli</dc:creator>
      <pubDate>Mon, 26 May 2025 00:42:41 +0000</pubDate>
      <link>https://forem.com/andreluizlunelli/whoami-2i9p</link>
      <guid>https://forem.com/andreluizlunelli/whoami-2i9p</guid>
      <description>&lt;p&gt;So, it's been a while since I wanna write/share some nice tips and I thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;why don't I start talking about myself?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Uh, ok, I'm not the kind who enjoys the exposure, but who knows what can happen when I start? At least I can see two good things from this start:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I'm pushing to write/think in English, which isn't my mother language.&lt;/li&gt;
&lt;li&gt;When someone asks me about it, I can send it back and save time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Let's start&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm André Luiz Lunelli, I'm 33 years old, I'm Brazilian, and have a bachelor’s degree in computer science from the Regional University of Blumenau. I've been a software developer since 2012, but I've been acting as tech lead since 2023. In 2022, I was promoted to husband and in 2024 to father.&lt;/p&gt;

&lt;p&gt;Guiding principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity over Complexity&lt;/li&gt;
&lt;li&gt;Composition over Inheritance&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/bliki/Yagni.html" rel="noopener noreferrer"&gt;YAGNI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>whoami</category>
      <category>webdev</category>
      <category>careerdevelopment</category>
      <category>php</category>
    </item>
  </channel>
</rss>
