<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Code Like a Woman]]></title><description><![CDATA[Code, learnings, and experiences from a Latina in tech.]]></description><link>https://codelikeawoman.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 05 Jul 2026 03:31:41 GMT</lastBuildDate><atom:link href="https://codelikeawoman.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Customer-Facing MCP Server: What Do You Actually Need?]]></title><description><![CDATA[In the previous article, we looked at how MCP works behind the scenes and the role played by clients, servers, tools, resources, and prompts.
This time, let's look at a specific use case: building a c]]></description><link>https://codelikeawoman.com/building-a-customer-facing-mcp-server-what-do-you-actually-need</link><guid isPermaLink="true">https://codelikeawoman.com/building-a-customer-facing-mcp-server-what-do-you-actually-need</guid><category><![CDATA[APIs]]></category><category><![CDATA[mcp]]></category><category><![CDATA[API Design]]></category><category><![CDATA[AI]]></category><category><![CDATA[ai agents]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Fri, 03 Jul 2026 17:20:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/67c0bd8498b78e6abd0ca1ae/49bc3b8d-9940-488a-aeb8-7c7ccc74579a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the previous article, we looked at how MCP works behind the scenes and the role played by clients, servers, tools, resources, and prompts.</p>
<p>This time, let's look at a specific use case: building a customer-facing MCP server.</p>
<p>If your goal is to allow customers to interact with your product through AI clients such as Claude, ChatGPT, Cursor, or Claude Code, what do you actually need?</p>
<p>The good news is that if you already have APIs or services, you're often closer than you think.</p>
<h2>The Essentials</h2>
<p>If you're building a first version, I'd focus on these first.</p>
<h3>1. Existing Functionality to Expose</h3>
<p>Most MCP servers sit on top of functionality that already exists.</p>
<p>That functionality might come from:</p>
<ul>
<li><p>REST APIs</p>
</li>
<li><p>GraphQL APIs</p>
</li>
<li><p>Databases</p>
</li>
<li><p>Internal services</p>
</li>
</ul>
<p>The MCP server becomes a layer that exposes that functionality to AI agents.</p>
<p>One thing you'll quickly discover is that not every API endpoint necessarily deserves to become a tool.</p>
<p>The goal isn't to mirror your API one-to-one. Instead, think in terms of capabilities that would be useful to an AI assistant.</p>
<p>For example, instead of exposing:</p>
<pre><code class="language-text">GET /projects
GET /projects/{id}
POST /projects/{id}/tickets
</code></pre>
<p>You might expose higher-level tools such as:</p>
<pre><code class="language-text">search_projects
create_ticket
</code></pre>
<p>The MCP server can orchestrate one or multiple API calls behind the scenes. What matters is not how your API is structured internally, but what actions are useful for the AI assistant to expose to the user.</p>
<p>One thing that surprised me was how capable modern AI clients are once they have access to well-defined tools.</p>
<p>My initial instinct was to think through every possible workflow a user might need. In practice, I found that the AI client could often orchestrate much of that on its own.</p>
<p>For example, imagine an MCP server exposes:</p>
<ul>
<li><p><code>search_projects</code></p>
</li>
<li><p><code>create_ticket</code></p>
</li>
<li><p><code>get_ticket_status</code></p>
</li>
</ul>
<p>A user might ask:</p>
<blockquote>
<p>Create a ticket for the login issue in the Mobile App project and let me know when it's done.</p>
</blockquote>
<p>The AI client can determine which tools to invoke, chain multiple calls together, provide the appropriate inputs, and even check back for updates if the workflow requires it.</p>
<p>This changed how I thought about tool design. Rather than exposing a tool for every workflow, I found it more useful to expose clear capabilities with good names and descriptions, allowing the AI client to orchestrate them as needed.</p>
<h3>2. An MCP SDK</h3>
<p>The easiest way to get started is with an MCP SDK.</p>
<p>SDKs are available for several languages, including:</p>
<ul>
<li><p>TypeScript</p>
</li>
<li><p>Python</p>
</li>
<li><p>Java</p>
</li>
</ul>
<p>The SDK handles much of the underlying protocol and transport details, allowing you to focus on defining the tools, resources, and prompts you want to expose.</p>
<h3>3. Choose a Transport</h3>
<p>One of the first architectural decisions is how clients will communicate with your MCP server.</p>
<p>The two most common options are:</p>
<ul>
<li><p><code>stdio</code></p>
</li>
<li><p><code>HTTP</code></p>
</li>
</ul>
<p>For my first implementation, I started with <code>stdio</code>.</p>
<p>It was a great way to get a prototype working quickly and test the integration in my local development environment. Since the MCP client launches the server as a local process, getting started was relatively straightforward.</p>
<p>Within a short time, I had my existing APIs connected to Claude and was able to interact with them conversationally. Instead of manually calling endpoints or testing requests, I could simply ask Claude to perform actions using the tools exposed by my MCP server.</p>
<p>It didn't take long, however, to realize that our end goal wasn't a local integration—it was allowing multiple customers to connect to the same MCP server. At that point, an HTTP-based server became the more appropriate choice.</p>
<p>If your goal is simply to get a feel for MCP and validate an integration quickly, starting with <code>stdio</code> can be a good option. It lets you connect your APIs to an AI client with minimal setup and experiment locally.</p>
<p>However, if you already know you'll need a hosted, multi-user solution, you may prefer to go straight to an HTTP-based server.</p>
<h3>4. Decide What to Expose</h3>
<p>One of the most important design decisions is deciding what functionality should be available to AI agents.</p>
<p>A common mistake is trying to expose everything.</p>
<p>For a first version, focus on the handful of actions that provide the most value.</p>
<p>Ask yourself:</p>
<blockquote>
<p>If a customer connected this MCP server today, what are the top five things they would want an AI assistant to do?</p>
</blockquote>
<p>Start there.</p>
<p>You can always expose additional functionality later.</p>
<h3>5. Decide How Users Will Authenticate</h3>
<p>If your MCP server exposes customer data or performs actions on behalf of users, you'll need a way to authenticate them.</p>
<p>Authentication becomes especially important once multiple customers start connecting to the same MCP server.</p>
<p>The AI assistant isn't acting on its own behalf—it is acting on behalf of a specific user.</p>
<p>That means the MCP server needs a way to identify who the user is and what data they are allowed to access.</p>
<p>Common approaches include:</p>
<ul>
<li><p>API Keys</p>
</li>
<li><p>OAuth</p>
</li>
</ul>
<p>We'll explore authentication in more detail in a future article.</p>
<h2>Start With the Smallest Useful Integration</h2>
<p>One thing I found useful was focusing on getting a single end-to-end workflow working first.</p>
<p>For example:</p>
<ol>
<li><p>Connect an MCP client to the server.</p>
</li>
<li><p>Authenticate a user.</p>
</li>
<li><p>Expose a small set of useful tools.</p>
</li>
<li><p>Successfully invoke those tools from the AI assistant.</p>
</li>
</ol>
<p>Once that foundation is working, it's much easier to iterate.</p>
<p>You can always add more tools, resources, prompts, richer authentication flows, and additional transports later.</p>
<p>In my experience, the challenge isn't usually exposing another tool. It's making sure the entire flow works smoothly—from connecting the client, to authenticating the user, to successfully invoking functionality in your application.</p>
<h2>Nice-to-Haves That Improve the Experience</h2>
<p>Once you have a working integration, there are several things that can make your MCP server even more effective.</p>
<h3>6. Provide Context</h3>
<p>One thing I didn't fully appreciate at first is that exposing tools is only part of the solution.</p>
<p>The AI also needs context to understand how those tools should be used.</p>
<p>For example, in one implementation, the underlying application stored dates and times in a specific timezone, while users interacted with the AI in their own local timezone.</p>
<p>Providing that context allowed the AI to perform the appropriate conversions before invoking tools or presenting results.</p>
<p>I found this particularly powerful because it allowed the AI to adapt its behavior without requiring additional tools or changes to the underlying APIs to accommodate every possible use case.</p>
<p>In many cases, if the AI seems to be making poor decisions, the missing piece isn't another capability—it's additional context.</p>
<h3>7. Consider Resources and Prompts</h3>
<p>Many MCP servers start with tools, but the protocol also supports resources and prompts.</p>
<p>Resources can provide additional context, such as product documentation, while prompts can expose reusable instructions or workflows.</p>
<p>These aren't always necessary for a first version, but they can be valuable additions as your MCP server evolves.</p>
<h3>8. Document How to Use It</h3>
<p>Even with a standardized protocol, documentation still matters.</p>
<p>Users need to know:</p>
<ul>
<li><p>What your MCP server does</p>
</li>
<li><p>How to install it</p>
</li>
<li><p>How to authenticate</p>
</li>
<li><p>Which AI tools support it</p>
</li>
</ul>
<p>Good documentation often makes the difference between an MCP server that gets adopted and one that doesn't.</p>
<h2>Conclusion</h2>
<p>One thing I learned is that a lot of MCP server design decisions become clearer through testing and real usage.</p>
<p>As you try different scenarios, you'll quickly discover whether:</p>
<ul>
<li><p>The agent is missing important context.</p>
</li>
<li><p>A tool is missing.</p>
</li>
<li><p>Two tools should be combined.</p>
</li>
<li><p>A description needs to be clearer.</p>
</li>
<li><p>Additional resources would help.</p>
</li>
</ul>
<p>I was also surprised by how capable modern AI clients are once they have access to well-defined tools. They can often chain multiple calls together, provide the appropriate inputs, and orchestrate workflows that I initially thought would require dedicated tools.</p>
<p>The best way to understand what your MCP server needs isn't to design every possible workflow upfront—it's to start with a small but useful integration and observe how the AI client uses it in practice.</p>
<p>Over time, those interactions will tell you where the gaps are and how the server should evolve.</p>
]]></content:encoded></item><item><title><![CDATA[How Does MCP Actually Work Behind the Scenes? A Simple Mental Model]]></title><description><![CDATA[In my previous article, I introduced MCP and explained why so many companies are adopting it.
But what actually happens when an AI assistant uses an MCP server?
You don't need to understand every deta]]></description><link>https://codelikeawoman.com/how-does-mcp-actually-work-behind-the-scenes-a-simple-mental-model</link><guid isPermaLink="true">https://codelikeawoman.com/how-does-mcp-actually-work-behind-the-scenes-a-simple-mental-model</guid><category><![CDATA[mcp]]></category><category><![CDATA[AI]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[software development]]></category><category><![CDATA[ai agents]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Tue, 16 Jun 2026 12:25:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/67c0bd8498b78e6abd0ca1ae/16d1b4b0-86e9-41b2-bde7-f7b399b31efa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous article, I introduced MCP and explained why so many companies are adopting it.</p>
<p>But what actually happens when an AI assistant uses an MCP server?</p>
<p>You don't need to understand every detail of the protocol to understand MCP. A simple mental model is enough.</p>
<h2>The Big Picture</h2>
<pre><code class="language-text">MCP Client (Claude, Cursor, ChatGPT, etc.)
                    │
                    ▼
               MCP Server
                    │
                    ▼
              Your Application
</code></pre>
<p>The MCP client is usually an AI application such as Claude, Cursor, ChatGPT, or Claude Code.</p>
<p>The MCP server sits between the AI assistant and your application. Its job is to expose information and functionality that the AI can discover and use.</p>
<p>You can think of it as another layer of abstraction between the AI client and your application's underlying APIs or services.</p>
<pre><code class="language-text">Claude
   │
   ▼
MCP Server
   │
   ▼
Your APIs / Services
</code></pre>
<p>But where does the MCP server come from?</p>
<p>Someone has to build it.</p>
<p>In many cases, the company behind the product provides an official MCP server. For example, GitHub, Linear, and other companies now offer MCP servers that expose functionality from their platforms to AI assistants.</p>
<p>If your company wants AI agents to interact with its products, your team would typically build and host an MCP server that AI clients can connect to.</p>
<p>Much like a REST API allows developers to interact with your application, an MCP server allows AI agents to interact with it.</p>
<h2>What Does an MCP Server Expose?</h2>
<p>At a high level, an MCP server can expose three types of things:</p>
<pre><code class="language-text">MCP Server
│
├── Tools
├── Resources
└── Prompts
</code></pre>
<h3>Tools</h3>
<p>Tools are actions the AI can perform.</p>
<p>Examples:</p>
<pre><code class="language-text">create_ticket
search_issues
send_message
</code></pre>
<p>When you ask Claude to create a Linear ticket, it is typically invoking a tool exposed by the Linear MCP server.</p>
<h3>Resources</h3>
<p>Resources are information the AI can read and use as context.</p>
<p>For example, imagine your company exposes its product documentation as a resource. An AI assistant could retrieve that documentation to answer questions or better understand how to use your product before invoking any tools.</p>
<p>A simple way to think about it:</p>
<ul>
<li><p>Tools → the AI wants to do something</p>
</li>
<li><p>Resources → the AI wants to know something</p>
</li>
</ul>
<h3>Prompts</h3>
<p>Prompts are reusable instructions exposed by the MCP server.</p>
<p>For example, a company might provide prompts such as:</p>
<ul>
<li><p>Summarize a project</p>
</li>
<li><p>Review code changes</p>
</li>
<li><p>Explain an error message</p>
</li>
</ul>
<p>Rather than requiring every client to define these instructions, they can be exposed directly by the MCP server.</p>
<p>A simple way to think about it:</p>
<ul>
<li><p>Tools → the AI wants to do something</p>
</li>
<li><p>Resources → the AI wants to know something</p>
</li>
<li><p>Prompts → the AI wants guidance on how to do it</p>
</li>
</ul>
<h2>How Does the AI Know What's Available?</h2>
<p>Before an AI assistant can use a tool, it first needs to discover what the MCP server provides.</p>
<p>A simplified version of that conversation looks like this:</p>
<pre><code class="language-text">Client
  │
  ├── initialize
  │
  ├── tools/list
  │
  ├── resources/list
  │
  └── prompts/list
</code></pre>
<p>Think of it as the AI asking:</p>
<blockquote>
<p>What can you do?</p>
</blockquote>
<p>The server responds with the tools, resources, and prompts it makes available.</p>
<h2>How Do Clients and Servers Communicate?</h2>
<p>All interactions between an MCP client and an MCP server happen through messages.</p>
<p>MCP standardizes these interactions using JSON-RPC, a lightweight protocol for request and response communication.</p>
<p>Those messages travel through a transport layer. MCP supports transports such as <code>stdio</code> and <code>HTTP</code>, which determine how the client and server communicate with each other.</p>
<p>Most developers interact with MCP through SDKs, which handle much of the underlying protocol and transport details for you. This allows developers to focus on the functionality they want to expose rather than the mechanics of the protocol itself.</p>
<h2>What Happens When a Tool Is Used?</h2>
<p>Let's say you ask Claude:</p>
<pre><code class="language-text">Create a Linear ticket for a login bug.
</code></pre>
<p>The flow looks something like this:</p>
<pre><code class="language-text">User
 │
 ▼
"Create a Linear ticket"
 │
 ▼
Claude
 │
 ▼
tools/call(create_ticket)
 │
 ▼
Linear MCP Server
 │
 ▼
Linear
</code></pre>
<p>Claude invokes the appropriate tool, the MCP server performs the operation, and the result is returned back to Claude.</p>
<h2>Bringing It All Together</h2>
<pre><code class="language-text">           MCP Client
      (Claude, Cursor, etc.)
                   │
                   ▼
             MCP Server
        ┌──────┼──────┐
        ▼      ▼      ▼
      Tools Resources Prompts
                   │
                   ▼
      APIs / Databases / Services
</code></pre>
<p>The client discovers what the server exposes and uses tools, resources, or prompts as needed.</p>
<p>That's the core mental model behind MCP.</p>
<p>In the next article, we'll look at what you actually need to build your own MCP server.</p>
]]></content:encoded></item><item><title><![CDATA[What Is MCP? The Protocol Behind Many AI Coding Integrations]]></title><description><![CDATA[About four months ago, I came across the term MCP for the first time while working on a project that required building an MCP server so customers could integrate AI agents with their time tracking dat]]></description><link>https://codelikeawoman.com/what-is-mcp-the-protocol-behind-many-ai-coding-integrations</link><guid isPermaLink="true">https://codelikeawoman.com/what-is-mcp-the-protocol-behind-many-ai-coding-integrations</guid><category><![CDATA[mcp]]></category><category><![CDATA[AI]]></category><category><![CDATA[Developer Tools]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Sat, 13 Jun 2026 15:34:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/67c0bd8498b78e6abd0ca1ae/95809933-ea78-4248-b072-41c1847b0154.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>About four months ago, I came across the term <strong>MCP</strong> for the first time while working on a project that required building an MCP server so customers could integrate AI agents with their time tracking data and automate workflows.</p>
<p>After shipping the first version, I started noticing MCP everywhere. GitHub has one. Linear has one. Slack, Notion, databases, browser automation tools—the list keeps growing. It seems like every week another company is making their functionalities available through MCP.</p>
<p>So what exactly is MCP?</p>
<h2>What Is MCP?</h2>
<p>MCP (Model Context Protocol) is a lightweight standard that allows AI agents to discover and use the actions an application makes available, such as creating a ticket, searching for issues, retrieving customer data, or updating a record.</p>
<p>Many companies already expose this functionality —often referred to as capabilities— through REST or GraphQL APIs. The challenge is not that the functionality doesn't exist—it's that every API exposes it differently. MCP provides a standard way for AI agents to discover what's available, understand how to invoke it, and interact with it consistently.</p>
<blockquote>
<p>REST APIs are typically designed for developers. MCP servers are designed for AI agents.</p>
</blockquote>
<h2>How Does It Work?</h2>
<p>A typical setup looks something like this:</p>
<pre><code class="language-text">AI Assistant
      ↓
  MCP Server
      ↓
 REST / GraphQL API
      ↓
 Application
</code></pre>
<p>The MCP server exposes information and functionality that the AI assistant can discover and use.</p>
<p>When a user asks the assistant to perform an action or retrieve information, the assistant can interact with the underlying application through the MCP server.</p>
<h2>MCP Usage in Practice</h2>
<p>Many popular products now provide official MCP integrations, including:</p>
<ul>
<li><p>GitHub</p>
</li>
<li><p>Linear</p>
</li>
<li><p>Slack</p>
</li>
<li><p>Notion</p>
</li>
<li><p>Stripe</p>
</li>
<li><p>Browser automation tools</p>
</li>
</ul>
<p>Let's look at a concrete example using the Linear MCP with Claude Code.</p>
<h3>Step 1: Install the Linear MCP</h3>
<pre><code class="language-bash">claude mcp add linear
</code></pre>
<p>Or simply ask Claude:</p>
<pre><code class="language-text">Install the Linear MCP for me.
</code></pre>
<p>Claude will guide you through the installation and authentication process.</p>
<h3>Step 2: Use It</h3>
<p>Once connected, you can ask things like:</p>
<p><strong>View your open issues</strong></p>
<pre><code class="language-text">What are my open Linear issues?
</code></pre>
<p><strong>Create a ticket</strong></p>
<pre><code class="language-text">Create a high-priority bug ticket for users being logged out unexpectedly.
</code></pre>
<p><strong>Search sprint work</strong></p>
<pre><code class="language-text">Show me all issues assigned to me this sprint.
</code></pre>
<p>From the user's perspective, it feels like a conversation.</p>
<p>For example, when you ask Claude to create a Linear ticket, Claude sends the request to the Linear MCP server. The MCP server exposes actions such as creating tickets or searching issues and knows how to translate those requests into operations in Linear.</p>
<p>##If AI agents can already use APIs, why do we need MCP?</p>
<p>AI agents can interact with REST and GraphQL APIs directly, so MCP isn't solving a technical limitation.</p>
<p>The value of MCP is that it gives AI agents a predictable way to discover what an application can do and how to use it.</p>
<p>For example, an AI assistant could be connected to GitHub, Linear, Slack, and dozens of other tools. Without a common standard, each integration would expose its functionality differently. MCP provides a consistent way for AI agents to discover available actions and interact with those systems.</p>
<h2>Why Developers Should Care</h2>
<p>MCP is quickly becoming one of the standard ways companies expose their products to AI agents. If your company provides APIs, there's a good chance you'll encounter MCP as organizations look for ways to make their products accessible to AI-powered tools and workflows.</p>
<p>Even if you're not building MCP servers yourself, you can benefit from the growing ecosystem of MCP integrations. By connecting AI assistants to tools you already use—such as GitHub, Linear, Slack, or Notion—you can automate repetitive tasks, retrieve information more easily, and streamline everyday workflows.</p>
<p>Whether you're building products or simply using them, MCP is becoming an increasingly important part of how AI systems interact with software.</p>
]]></content:encoded></item><item><title><![CDATA[Git Worktrees: A Git Feature I Wish I Had Tried Earlier]]></title><description><![CDATA[I had heard about Git worktrees before, but I didn’t really try them until recently — when a coding assistant I was using created one naturally as part of its workflow.
I was working on a feature when]]></description><link>https://codelikeawoman.com/git-worktrees-a-git-feature-i-wish-i-had-tried-earlier</link><guid isPermaLink="true">https://codelikeawoman.com/git-worktrees-a-git-feature-i-wish-i-had-tried-earlier</guid><category><![CDATA[Git]]></category><category><![CDATA[software development]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[version control]]></category><category><![CDATA[developer productivity]]></category><category><![CDATA[AI-assisted development]]></category><category><![CDATA[AI]]></category><category><![CDATA[claude]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Tue, 26 May 2026 19:14:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/67c0bd8498b78e6abd0ca1ae/c8906a52-4b91-4064-9d8f-bc314ad280c8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I had heard about Git worktrees before, but I didn’t really try them until recently — when a coding assistant I was using created one naturally as part of its workflow.</p>
<p>I was working on a feature when we realized there was a bug fix that needed to happen first because it was a prerequisite.</p>
<p>And that’s when worktrees clicked for me.</p>
<h2>So… what is a Git worktree?</h2>
<p>A Git worktree lets you have <strong>multiple working directories of the same repository on your computer</strong>, each checked out to a different branch.</p>
<p>Instead of constantly switching branches in one folder, you can have something like this:</p>
<pre><code class="language-plaintext">/my-app-main
/my-app-feature
/my-app-bugfix
</code></pre>
<p>All connected to the same Git repository — but each on a different branch.</p>
<h2>Without worktrees</h2>
<p>Imagine you’re halfway through building a feature:</p>
<pre><code class="language-plaintext">git checkout feature/new-reporting
</code></pre>
<p>Then you realize a bug fix must happen first because it’s blocking the feature.</p>
<p>Normally, the flow might look something like this:</p>
<pre><code class="language-plaintext">git stash
git checkout main
git pull
git checkout -b fix/auth-token
</code></pre>
<p>Fix the bug, push it, merge it… then come back:</p>
<pre><code class="language-plaintext">git checkout feature/new-reporting
git stash pop
</code></pre>
<p>Totally workable.</p>
<p>But there’s friction.</p>
<p>You interrupt your flow, mentally bookmark where you were, and juggle branch switching, stashes, and working state.</p>
<h2>With worktrees</h2>
<p>Instead, you can keep your feature exactly where it is and create a separate working directory for the bug fix.</p>
<p>From your repo:</p>
<pre><code class="language-plaintext">git worktree add ../my-app-bugfix -b fix/auth-token main
</code></pre>
<p>Now you have:</p>
<pre><code class="language-plaintext">/my-app-feature   → feature/new-reporting
/my-app-bugfix    → fix/auth-token
</code></pre>
<p>You can literally open both folders side by side.</p>
<p>Your feature stays untouched while you work on the prerequisite bug fix. When the fix is merged, you can update your feature branch and continue.</p>
<p>You’re still context switching.</p>
<p>But it feels much more graceful.</p>
<p>Especially with coding assistants, I’ve found this surprisingly helpful.</p>
<p>It makes parallel threads of work feel much more natural.</p>
<p>For example, I might be actively building a feature in one worktree while a separate Claude session works on a prerequisite bug fix in another — all within the same repository, but isolated from each other.</p>
<p>Or I might spin up a temporary worktree for an experiment without disrupting the work already in progress.</p>
<p>You’re still coordinating and context switching, but the friction feels much lower.</p>
<h2>A small practice that seems helpful</h2>
<p>It could be helfpul s keep a <strong>default worktree always synced with</strong> <code>main</code>, something like:</p>
<pre><code class="language-plaintext">/my-app-main      → always synced with main
/my-app-feature   → current feature
/my-app-hotfix    → urgent fix
</code></pre>
<p>That way, creating new branches or experiments feels lightweight and you always have a clean starting point.</p>
<p>It’s one of those Git features I wish I had tried earlier.</p>
<p>Sharing in case it’s useful for someone else too.</p>
]]></content:encoded></item><item><title><![CDATA[How I’ve Been Working With Claude Code (and What’s Helped So Far)]]></title><description><![CDATA[What Changed in My Workflow After Using Claude Code
Claude Code has quickly become one of the go-to coding assistants for many developers and teams. I’ve been using it as part of my day-to-day workflo]]></description><link>https://codelikeawoman.com/how-i-ve-been-working-with-claude-code-and-what-s-helped-so-far</link><guid isPermaLink="true">https://codelikeawoman.com/how-i-ve-been-working-with-claude-code-and-what-s-helped-so-far</guid><category><![CDATA[AI]]></category><category><![CDATA[claude-code]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[claude]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Wed, 29 Apr 2026 00:36:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/67c0bd8498b78e6abd0ca1ae/0a3c1899-facf-4cc3-b8ca-14be6df99377.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>What Changed in My Workflow After Using Claude Code</h1>
<p>Claude Code has quickly become one of the go-to coding assistants for many developers and teams. I’ve been using it as part of my day-to-day workflow, and over time I’ve noticed that it hasn’t just changed how I code, but also how I approach building software.</p>
<p>This is not meant to be a set of best practices or anything definitive—just a collection of things that have genuinely helped me so far, in case they’re useful to someone else as well.</p>
<p>I’ve found my way of working with it gradually shifting:</p>
<ul>
<li><p>from using it for isolated tasks</p>
</li>
<li><p>to being more intentional about planning and context</p>
</li>
<li><p>to using it for refinement and quality improvements</p>
</li>
<li><p>and finally toward thinking more automation-first in general</p>
</li>
</ul>
<h2>1. Getting comfortable with sessions and keeping context</h2>
<p>One of the first things that made a difference for me was just getting comfortable with how sessions work, and how to recover or continue work without losing context.</p>
<h3><code>/login</code> helps you recover without losing context</h3>
<p>If you ever need to switch accounts or your session expires, you can use:</p>
<p><code>/login</code></p>
<p>This lets you reauthenticate without losing your current context.</p>
<p>Useful when:</p>
<ul>
<li><p>switching subscriptions or accounts</p>
</li>
<li><p>dealing with expired sessions</p>
</li>
<li><p>recovering access without restarting your work</p>
</li>
</ul>
<p>Small thing, but I’ve found it helps maintain flow.</p>
<h3><code>claude --resume</code> is a safety net (with one catch)</h3>
<p>Another thing that has been really helpful is being able to resume sessions.</p>
<p>You can use:</p>
<p><code>claude --resume</code></p>
<p>to return to a previous session.</p>
<p>This has been especially useful when things go wrong:</p>
<ul>
<li><p>accidental terminal closes</p>
</li>
<li><p>machine restarts</p>
</li>
<li><p>terminal freezes (this has happened to me more than a handful of times)</p>
</li>
</ul>
<p>It’s also useful when working on different things and wanting to keep contexts separated across sessions.</p>
<p>One thing I didn’t realize at first:</p>
<blockquote>
<p><code>--resume</code> is scoped per directory.</p>
</blockquote>
<p>If you’re not in the same directory where you started the session, you won’t see it. I learned this empirically after thinking I had lost everything—when I was just in the wrong folder.</p>
<h3><code>/btw</code> helps you keep momentum</h3>
<p>More recently, I’ve also found <code>/btw</code> useful.</p>
<p>It lets you ask questions or leave comments without interrupting the current work.</p>
<p>Instead of breaking the flow of a task, you can surface clarifications while the assistant continues working.</p>
<p>It’s a small thing, but it helps keep iteration smooth.</p>
<p>There are many other commands and I haven’t explored most of them yet, but I’m curious to keep discovering more over time.</p>
<h2>2. Learning to guide the assistant better</h2>
<h3>Plan before implementing</h3>
<p>I’ve found it works much better to align on a plan before jumping into implementation.</p>
<p>Before coding, I usually ask Claude to outline:</p>
<ul>
<li><p>the approach</p>
</li>
<li><p>the scope</p>
</li>
<li><p>the main steps</p>
</li>
</ul>
<p>This tends to lead to more predictable outcomes and fewer surprises later.</p>
<p>Otherwise, you risk getting code that technically works but doesn’t match how you actually wanted things to be structured or behave.</p>
<h3>Provide the right context, not more context</h3>
<p>Coding assistants have gotten really good—but the outcome is still very tied to the input.</p>
<p>When it makes sense, I try to include things like:</p>
<ul>
<li><p>ticket context (title + description)</p>
</li>
<li><p>PRDs or specs</p>
</li>
<li><p>related PRs or discussions</p>
</li>
<li><p>incident reports</p>
</li>
<li><p>logs or traces</p>
</li>
<li><p>specific files or references</p>
</li>
</ul>
<p>The goal is to help build the right context around the problem.</p>
<p>That said, this is very dependent on what you’re building. For simpler tasks, you don’t need much input to get a correct implementation.</p>
<p>But as things get more complex, the difference becomes obvious.</p>
<blockquote>
<p>It’s not about adding more input—it’s about adding the right input.</p>
</blockquote>
<p>I like to think of it as getting an incident report with no repro steps or logs—you’d be lost. And the same applies to the agent.</p>
<h3>Challenge limitations instead of accepting them</h3>
<p>Sometimes the agent will say it can’t do something and suggest doing it manually in another terminal.</p>
<p>In those cases, I don’t always take that at face value.</p>
<p>There have been situations where:</p>
<ul>
<li><p>it actually can do it within the current context</p>
</li>
<li><p>it has done similar things before</p>
</li>
<li><p>or the limitation isn’t entirely clear</p>
</li>
</ul>
<p>So instead, I try to push a bit:</p>
<ul>
<li><p>“Can you try doing this directly?”</p>
</li>
<li><p>“What exactly is preventing you from doing it here?”</p>
</li>
</ul>
<p>Not in a forceful way, but just to better understand what’s going on and avoid unnecessary manual work when possible.</p>
<h3>Use Claude for refinement, not just implementation</h3>
<p>Another part of how I use Claude is not just to build things, but to refine and improve them.</p>
<p>This can include:</p>
<ul>
<li><p>system architecture</p>
</li>
<li><p>code structure and conventions</p>
</li>
<li><p>testing strategy</p>
</li>
<li><p>performance considerations</p>
</li>
<li><p>maintainability and scalability</p>
</li>
<li><p>security and documentation</p>
</li>
</ul>
<p>These are all things I used to think through more manually, and now I find it helpful to involve the agent in that process as well.</p>
<p>It doesn’t replace thinking, but it helps get to a more polished result faster.</p>
<h3>Preferences help, but don’t always persist</h3>
<p>Another thing I do is ask the agent to keep certain preferences in mind.</p>
<p>This might include:</p>
<ul>
<li><p>coding style</p>
</li>
<li><p>architectural choices</p>
</li>
<li><p>naming conventions</p>
</li>
<li><p>testing expectations</p>
</li>
</ul>
<p>It can help reduce repetition and keep things more aligned with how I like to work.</p>
<p>That said, it’s not perfect. It doesn’t always remember or apply these consistently across sessions, so I do find myself repeating things.</p>
<p>I do think this is an area where things can improve, and I’m curious to explore better ways of handling this over time.</p>
<h2>3. Shifting toward automation-first thinking</h2>
<p>One of the bigger shifts for me has been moving away from doing things manually by default.</p>
<p>Now I tend to delegate a lot of repetitive or operational work to the assistant:</p>
<ul>
<li><p>creating feature branches</p>
</li>
<li><p>opening pull requests</p>
</li>
<li><p>drafting documents</p>
</li>
<li><p>running repetitive git tasks</p>
</li>
<li><p>setting up GitHub workflows</p>
</li>
</ul>
<p>And more generally, it’s changed how I think about work.</p>
<p>Now when I see something manual, my first thought is:</p>
<blockquote>
<p>can this be automated?</p>
</blockquote>
<p>Sometimes that leads to:</p>
<ul>
<li><p>writing a small shell script</p>
</li>
<li><p>creating aliases</p>
</li>
<li><p>setting environment variables</p>
</li>
<li><p>or adding a GitHub workflow to handle it</p>
</li>
</ul>
<p>Individually these are small improvements, but over time they reduce a lot of friction.</p>
<h2>4. Using different tools depending on the stage of work</h2>
<p>Another thing I do sometimes is use non-coding agents, like ChatGPT, for earlier stages of thinking before switching to Claude for implementation.</p>
<p>This has been especially useful for:</p>
<ul>
<li><p>brainstorming ideas</p>
</li>
<li><p>light planning</p>
</li>
<li><p>product and UX thinking</p>
</li>
<li><p>system architecture design</p>
</li>
</ul>
<p>Not all work starts with code. Some of it benefits from a more open-ended space before getting into implementation details.</p>
<p>Once things feel clearer, I then move into Claude to actually build, refine, and execute.</p>
<p>It’s a simple separation, but I’ve found it helps me keep better structure between:</p>
<ul>
<li><p>thinking and shaping the problem</p>
</li>
<li><p>and actually building the solution</p>
</li>
</ul>
<h2>Final thoughts</h2>
<p>These are just some of the things that have helped me so far while working with Claude.</p>
<p>What stands out most to me is that this is still evolving. The more I use it, the more I notice small adjustments in how I think about building, structuring, and automating work.</p>
<p>Some of these things I’ve learned through trial and error, and others have come more naturally as I’ve kept incorporating AI into my day-to-day workflow.</p>
<p>I’m sure this will continue to evolve over time—and I’d be curious to hear how others are approaching it as well.</p>
]]></content:encoded></item><item><title><![CDATA[Building My First Side Project: From Intuition to a Repeatable Way of Thinking]]></title><description><![CDATA[This is the first time I’m intentionally working on a side project end-to-end — outside of a company, outside of a team, and outside of an existing product system.
It’s just me, an idea, and the respo]]></description><link>https://codelikeawoman.com/building-my-first-side-project-from-intuition-to-a-repeatable-way-of-thinking</link><guid isPermaLink="true">https://codelikeawoman.com/building-my-first-side-project-from-intuition-to-a-repeatable-way-of-thinking</guid><category><![CDATA[AI Coding Assistant]]></category><category><![CDATA[product thinking]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[side project]]></category><category><![CDATA[Startups]]></category><category><![CDATA[AI in Development]]></category><category><![CDATA[prd document ]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Fri, 24 Apr 2026 17:24:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/67c0bd8498b78e6abd0ca1ae/98aa0875-ad0b-4200-82a6-a2f22cc534e6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the first time I’m intentionally working on a side project end-to-end — outside of a company, outside of a team, and outside of an existing product system.</p>
<p>It’s just me, an idea, and the responsibility of turning it into something real.</p>
<p>At first, I assumed the challenge would be execution: writing code and building features quickly.</p>
<p>But I’ve realized something more subtle:</p>
<blockquote>
<p>The hardest part is not building the feature — it’s deciding what to build, and how small that version needs to be to validate real user behavior.</p>
</blockquote>
<p>This is just one of several challenges I’m starting to recognize, and I suspect there are more worth writing about as I keep building.</p>
<hr />
<h2>How I’ve Always Thought About Features</h2>
<p>I’ve always approached features with a consistent mental model.</p>
<p>Whenever I work on something, I naturally think about:</p>
<ul>
<li><p>why it exists and what value it creates</p>
</li>
<li><p>what problem it solves</p>
</li>
<li><p>how it can be simplified</p>
</li>
<li><p>what edge cases matter</p>
</li>
<li><p>what I explicitly don’t want to build</p>
</li>
<li><p>how it fits into the existing data model and UI</p>
</li>
<li><p>how the user experience should feel end-to-end</p>
</li>
<li><p>how to implement it with minimal user friction</p>
</li>
<li><p>what signals would indicate this feature is actually working</p>
</li>
</ul>
<p>This isn’t something I learned recently — it’s just how I reason about problems.</p>
<p>Even in my engineering role, I’ve always used a strong user-story mindset: understanding intent, questioning value, and sometimes even challenging whether something should be built at all.</p>
<p>Over time, I realized this is what more senior thinking actually looks like:</p>
<blockquote>
<p>Not just implementing features, but deeply understanding intent and improving it when needed.</p>
</blockquote>
<hr />
<h2>The Problem I Didn’t Have a Name For</h2>
<p>In my side project, I started running into a subtle issue.</p>
<p>I would do most of the feature thinking upfront — naturally and consistently — before writing any code: planning how it would fit into the existing data model, how it would behave in the UI, and what the user experience would feel like end-to-end.</p>
<p>But once I started implementing, that thinking had nowhere to live.</p>
<p>If I stored it in a Linear ticket, it would get buried in execution details. More importantly, a Linear ticket — as a small unit of work — often didn’t represent the full end-to-end feature vision, only the initial increment being implemented.</p>
<p>If I stored it in Google Docs, it would quickly become something I forgot to revisit.</p>
<p>So I was left with a gap:</p>
<blockquote>
<p>A lot of clarity before coding… and very little preservation of that clarity afterward.</p>
</blockquote>
<hr />
<h2>Seeing PRDs Differently</h2>
<p>I’ve seen PRDs before — usually as input documents in product discussions or strategic meetings. But I never had to write them myself.</p>
<p>For context, a <strong>PRD (Product Requirements Document)</strong> is a structured document used to define what a product or feature should do, why it exists, and how success is measured before development begins.</p>
<p>They felt formal, structured, and somewhat distant from how I naturally think when building.</p>
<p>That changed in this side project.</p>
<p>Because I am now both the product thinker and the implementer, I started noticing that I may need a simple framework to structure this type of thinking, and a persistent place to store it so it could eventually be referenced when implementing features in Linear.</p>
<p>Not as something I fully have — but as something that might be useful to formalize.</p>
<hr />
<h2>PRD-Lite: A Repeatable Thinking System (Emerging Idea)</h2>
<p>Over time, I noticed I was already doing a fairly repeatable type of thinking — just informally.</p>
<p>To make it easier to reason about, I started sketching a simple structure I might use for future features. I’m considering storing it as a Markdown file in the repo so it stays close to the code and could eventually be referenced during implementation.</p>
<p>I haven’t adopted this yet, but it feels like a direction worth exploring.</p>
<h3>🧾 PRD-lite format</h3>
<ol>
<li><p><strong>Why it exists</strong> Why this should be built and what value it creates</p>
</li>
<li><p><strong>MVP scope</strong> What the smallest useful version includes</p>
</li>
<li><p><strong>User flow</strong> What the user does</p>
</li>
<li><p><strong>Data model (light)</strong> What objects exist</p>
</li>
<li><p><strong>Out of scope</strong> What I am explicitly not building</p>
</li>
</ol>
<p>Right now, this is more of a thinking scaffold than a system — something I use to avoid losing structure while I’m reasoning about a feature.</p>
<hr />
<h2>The AI Layer: A Possible Extension of This Idea</h2>
<p>Another thing I’ve been thinking about is how this kind of structured thinking might interact with AI coding assistants.</p>
<p>If I eventually write these PRD-like notes in the repo, they could serve as useful context when working with tools like Claude or similar assistants.</p>
<p>Instead of re-explaining intent in prompts, the assistant could potentially use:</p>
<ul>
<li><p>structured feature definitions</p>
</li>
<li><p>scope boundaries</p>
</li>
<li><p>user flows</p>
</li>
<li><p>data model assumptions</p>
</li>
</ul>
<p>This is not something I’m actively doing yet — but it’s one of the reasons this idea feels interesting.</p>
<p>It suggests a workflow where thinking becomes more portable between planning and implementation.</p>
<hr />
<h2>Why This Matters in a Side Project</h2>
<p>When you’re building alone, there is no separation between:</p>
<ul>
<li><p>product thinking</p>
</li>
<li><p>decision making</p>
</li>
<li><p>implementation</p>
</li>
</ul>
<p>Everything collapses into one continuous flow.</p>
<p>That makes it very easy to:</p>
<ul>
<li><p>lose intent while coding</p>
</li>
<li><p>overbuild in the moment</p>
</li>
<li><p>forget original assumptions</p>
</li>
<li><p>drift away from the real problem you were solving</p>
</li>
</ul>
<p>What I’m exploring here is not a process — it’s a way to preserve intent long enough to actually build from it.</p>
<hr />
<h2>Final Thought</h2>
<p>I used to think PRDs were documents created for engineers to follow.</p>
<p>Now I see them differently.</p>
<p>They are not external instructions — they are a way to make your thinking persistent enough to actually build from it.</p>
<p>And for the first time building something on my own, I’ve realized I’ve naturally been doing product thinking all along — and I’m now starting to explore how to structure that thinking so it doesn’t get lost between idea and implementation.</p>
<p>Think clearly. Write it down. Build intentionally.</p>
<p>That’s the system I’m starting to discover</p>
]]></content:encoded></item><item><title><![CDATA[The Unspoken Feelings of a Senior Developer Working With AI-Powered Tools]]></title><description><![CDATA[AI-powered tools have changed how we work — significantly.
They help us explore faster, reduce friction, catch bugs in seconds, diagnose issues in minutes, refactor code precisely, and move through iterations at a pace that would have felt unrealisti...]]></description><link>https://codelikeawoman.com/the-unspoken-feelings-of-a-senior-developer-working-with-ai-powered-tools</link><guid isPermaLink="true">https://codelikeawoman.com/the-unspoken-feelings-of-a-senior-developer-working-with-ai-powered-tools</guid><category><![CDATA[senior-developers]]></category><category><![CDATA[AI]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[developer experience]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Fri, 16 Jan 2026 21:25:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768598600847/6ef50785-2dce-4a79-bc48-eb3cef6c3ba3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AI-powered tools have changed how we work — significantly.</p>
<p>They help us explore faster, reduce friction, catch bugs in seconds, diagnose issues in minutes, refactor code precisely, and move through iterations at a pace that would have felt unrealistic not long ago.</p>
<p>All of that is objectively positive.</p>
<p>And yet, alongside those gains, something quieter has shifted — not in capability, but in <strong>how the work feels</strong>.</p>
<p>This article is an attempt to name that shift from the perspective of a senior developer working with AI-powered tools — not as a critique, but as a reflection on the feelings and navigation required in this new paradigm.</p>
<hr />
<h2 id="heading-from-building-systems-to-shaping-them">From building systems to shaping them</h2>
<p>For much of my career, the relationship between effort and ownership was relatively clear.</p>
<p>You analyzed and built solutions.<br />You carried problems end to end.<br />You found and fixed issues opportunely.<br />You mastered your stack, sharpened your understanding of computer science, system design, and engineering — and used that as a guiding signal of how good you were becoming.</p>
<p>Today, that relationship is less predictable.</p>
<p>AI doesn’t just help write code — it can:</p>
<ul>
<li><p>propose the structure</p>
</li>
<li><p>draft the solution</p>
</li>
<li><p>fill in edge cases</p>
</li>
<li><p>produce something that already works</p>
</li>
</ul>
<p>When that happens, the output can be correct and high quality — yet still feel oddly distant.</p>
<p>We’ve shifted from knowing things at a very granular level to <strong>orchestrating tools and shaping systems into existence</strong>.</p>
<hr />
<h2 id="heading-when-contribution-starts-to-feel-ambiguous">When contribution starts to feel ambiguous</h2>
<p>I’ve noticed that how I feel about my contribution depends less on how much AI I use, and more on <strong>how I’m involved</strong>.</p>
<p>I feel more grounded when I:</p>
<ul>
<li><p>intentionally orchestrate the process</p>
</li>
<li><p>participate actively in decision-making</p>
</li>
<li><p>debug and investigate issues</p>
</li>
<li><p>guide refactors toward something more mature</p>
</li>
<li><p>go beyond the first iteration</p>
</li>
<li><p>push for quality, correctness, tests, observability, and other core software engineering practices</p>
</li>
</ul>
<p>In those moments, the work feels <strong>shaped</strong>, not just completed.</p>
<p>By contrast, when AI:</p>
<ul>
<li><p>proposes the structure</p>
</li>
<li><p>drafts most of the solution</p>
</li>
<li><p>resolves edge cases</p>
</li>
<li><p>delivers something that already works</p>
</li>
<li><p>resolves things quickly</p>
</li>
</ul>
<p>…and my role is mainly to approve, lightly edit, and merge, a different feeling can emerge:</p>
<blockquote>
<p><em>“I didn’t really contribute enough.”</em></p>
</blockquote>
<p>The difference isn’t about typing versus not typing.<br />It’s about <strong>being necessary in the process</strong>.</p>
<hr />
<h2 id="heading-how-ai-can-aggravate-impostor-syndrome">How AI can aggravate impostor syndrome</h2>
<p>This is where impostor syndrome can quietly enter — even for experienced developers.</p>
<p>Not because the work is poor.<br />Not because the system is fragile.<br />But because familiar signals of contribution are no longer reliable.</p>
<p>When AI takes a large portion of the work off my plate, it can provoke thoughts like:</p>
<ul>
<li><p>“I didn’t do this myself.”</p>
</li>
<li><p>“I couldn’t have done this without help.”</p>
</li>
<li><p>“How much of this was really me?”</p>
</li>
</ul>
<p>The system may be better.<br />The outcome may be right.<br />But the internal sense of contribution can lag behind.</p>
<p>At times, this can feel like a lack of competence — but it’s really a <strong>paradigm shift</strong>.</p>
<p>Ways of recognizing value that worked for more than a decade — attention to detail, deeply caring about correctness and quality — don’t always map cleanly onto AI-assisted workflows or speedy shipment.</p>
<p>That mismatch can create doubt or unease, even when everything is working as intended.</p>
<hr />
<h2 id="heading-a-different-shape-of-ownership">A different shape of ownership</h2>
<p>At senior levels, ownership no longer means:</p>
<ul>
<li><p>writing every line</p>
</li>
<li><p>remembering every detail</p>
</li>
<li><p>coming up with the architecture entirely on your own</p>
</li>
</ul>
<p>It means:</p>
<ul>
<li><p>defining the right problem</p>
</li>
<li><p>choosing the right constraints</p>
</li>
<li><p>rejecting wrong or premature solutions</p>
</li>
<li><p>integrating pieces into a coherent system</p>
</li>
<li><p>being accountable when it breaks</p>
</li>
</ul>
<p>When something fails, no one asks how much AI was involved.<br />They ask <strong>you</strong> — the engineer who shipped the solution — to stand behind it.</p>
<p>That responsibility hasn’t gone away, even if the path to it looks different now.</p>
<hr />
<h2 id="heading-closing">Closing</h2>
<p>I don’t think I’m alone in experiencing this shift.</p>
<p>I suspect many senior developers are navigating something similar: working effectively with powerful tools, delivering solid systems, and still adjusting to how contribution and ownership <em>feel</em> in this new context.</p>
<p>This article itself was written with AI assistance — intentionally. Not to dilute the voice, but to reflect the reality it describes. The thoughts captured here represent feelings I’ve been sitting with as I navigate this new paradigm.</p>
<p>If this resonates, I’d be genuinely interested in hearing how others are experiencing this shift — what feels familiar, what feels different, and how you’re making sense of authorship and ownership in AI-assisted work.</p>
]]></content:encoded></item><item><title><![CDATA[Modern Java Feature: String Templates (Preview)]]></title><description><![CDATA[Update – December 2024:String Templates were available as a preview feature in Java 21 and Java 22.However, the feature was withdrawn from Java 23 because the JDK team decided it required more design work before moving forward.The concept is not canc...]]></description><link>https://codelikeawoman.com/modern-java-feature-string-templates-preview</link><guid isPermaLink="true">https://codelikeawoman.com/modern-java-feature-string-templates-preview</guid><category><![CDATA[Java]]></category><category><![CDATA[Modern Java]]></category><category><![CDATA[string templates]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Mon, 24 Nov 2025 13:03:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764021053920/ddc7f1c5-fa5d-459e-b817-d8c22c71d181.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Update – December 2024:</strong><br />String Templates were available as a preview feature in Java 21 and Java 22.<br />However, the feature was <strong>withdrawn from Java 23</strong> because the JDK team decided it required more design work before moving forward.<br />The concept is not canceled — it is expected to return in a future release with an improved design — but it is <strong>not available in Java 23</strong>.</p>
<p>Everything described in this article refers to the earlier preview versions (Java 21–22). I’m keeping the article online for educational purposes and will update it again when the new design becomes available.</p>
</blockquote>
<p>String Templates are one of the most anticipated additions to modern Java. They were first introduced as a preview feature in <strong>Java 21</strong>, refined again in <strong>Java 22</strong>, and kept in preview in <strong>Java 23</strong>. They are expected to remain in preview until at least Java 24 or 25, when the design stabilizes enough to be finalized.</p>
<p>Even as a preview feature, String Templates are worth trying out. They significantly improve how developers construct strings in Java, and as a result, you will be better prepared when they are finalized.</p>
<h2 id="heading-what-is-this-feature-about">What is this feature about?</h2>
<p>String Templates allow embedding Java expressions directly inside string literals using the <code>STR</code> processor. This provides cleaner syntax for building structured strings and complements Text Blocks, making Java feel more expressive and modern.</p>
<p><strong>Quick example:</strong></p>
<pre><code class="lang-java">String name = <span class="hljs-string">"Mirna"</span>;
String message = STR.<span class="hljs-string">"Hello, \{name}! Today is \{LocalDate.now()}"</span>;
System.out.println(message);
</code></pre>
<p><strong>Sample output:</strong></p>
<pre><code class="lang-java">Hello, Mirna! Today is <span class="hljs-number">2025</span>-<span class="hljs-number">01</span>-<span class="hljs-number">01</span>
</code></pre>
<p><strong>How to run preview features:</strong><br />If you are trying this with Java 21 or newer, you must enable preview mode, for a class for code that uses this feature like StringTemplatesDemo, we will need:</p>
<pre><code class="lang-java">javac --enable-preview --release <span class="hljs-number">21</span> StringTemplatesDemo.java
java  --enable-preview StringTemplatesDemo
</code></pre>
<p>Adjust the version number if you use a newer JDK (22, 23, etc.).</p>
<hr />
<h1 id="heading-common-use-cases"><strong>Common Use Cases</strong></h1>
<h2 id="heading-1-build-json-cleanly">1. Build JSON cleanly</h2>
<pre><code class="lang-java">String user = <span class="hljs-string">"Mirna"</span>;
<span class="hljs-keyword">int</span> score = <span class="hljs-number">98</span>;

String json = STR.<span class="hljs-string">""</span><span class="hljs-string">"
{
  "</span>user<span class="hljs-string">": "</span>\{user}<span class="hljs-string">",
  "</span>score<span class="hljs-string">": \{score},
  "</span>active<span class="hljs-string">": true
}
"</span><span class="hljs-string">""</span>;

System.out.println(json);
</code></pre>
<h2 id="heading-2-construct-sql-dynamically">2. Construct SQL dynamically</h2>
<pre><code class="lang-java">String table = <span class="hljs-string">"users"</span>;
String email = <span class="hljs-string">"mirna@example.com"</span>;

String query = STR.<span class="hljs-string">""</span><span class="hljs-string">"
SELECT *
FROM \{table}
WHERE email = '\{email}'
"</span><span class="hljs-string">""</span>;

System.out.println(query);
</code></pre>
<h2 id="heading-3-build-html-fragments">3. Build HTML fragments</h2>
<pre><code class="lang-java">String name = <span class="hljs-string">"Mirna"</span>;

String html = STR.<span class="hljs-string">""</span><span class="hljs-string">"
&lt;p&gt;Hello, &lt;b&gt;\{name}&lt;/b&gt;!&lt;/p&gt;
"</span><span class="hljs-string">""</span>;

System.out.println(html);
</code></pre>
<h2 id="heading-4-use-expressions-directly">4. Use expressions directly</h2>
<pre><code class="lang-java">String math = STR.<span class="hljs-string">"2 + 2 = \{2 + 2}"</span>;
String random = STR.<span class="hljs-string">"Random value: \{Math.round(Math.random() * 10)}"</span>;

System.out.println(math);
System.out.println(random);
</code></pre>
<h2 id="heading-5-use-methods-inside-templates">5. Use methods inside templates</h2>
<pre><code class="lang-java"><span class="hljs-function">String <span class="hljs-title">greet</span><span class="hljs-params">(String name)</span> </span>{
    <span class="hljs-keyword">return</span> STR.<span class="hljs-string">"Hello, \{name.toUpperCase()}!"</span>;
}

System.out.println(greet(<span class="hljs-string">"Mirna"</span>));
</code></pre>
<h2 id="heading-6-combine-text-blocks-templates">6. Combine Text Blocks + Templates</h2>
<pre><code class="lang-java">String language = <span class="hljs-string">"Java"</span>;
String feature = <span class="hljs-string">"String Templates"</span>;

String article = STR.<span class="hljs-string">""</span><span class="hljs-string">"
## Feature Highlight

We're exploring \{feature} in \{language}.

Advantages:
- Readable
- Multiline
- Interpolated directly in code
"</span><span class="hljs-string">""</span>;

System.out.println(article);
</code></pre>
<h1 id="heading-final-thoughts">Final Thoughts</h1>
<p>String Templates make Java more modern and readable, especially when combined with Text Blocks. The feature is a meaningful improvement over string concatenation and <code>String.format</code>.</p>
<p>There are still two things that feel a bit unnatural to me.<br />First, the backslash before the curly braces (<code>\{name}</code>). Second, having to prefix a Text Block with <code>STR."""</code> just to enable interpolation. Most modern languages do not require this extra step. I can live with both, though, since the improvement in readability is real.</p>
<p>I’m excited to see how this feature evolves as it moves toward finalization.</p>
]]></content:encoded></item><item><title><![CDATA[Using Cursor as my AI pair-programmer — a personal take]]></title><description><![CDATA[I’ve been using Cursor as part of my daily development flow and wanted to share what’s worked (and what hasn’t) from my own experience. I’ll keep this casual and short.
Quick note: I’m not affiliated with Cursor in any way. This is just my honest exp...]]></description><link>https://codelikeawoman.com/using-cursor-as-my-ai-pair-programmer-a-personal-take</link><guid isPermaLink="true">https://codelikeawoman.com/using-cursor-as-my-ai-pair-programmer-a-personal-take</guid><category><![CDATA[cursor IDE]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[pair programming]]></category><category><![CDATA[Junior developer ]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Sun, 28 Sep 2025 14:25:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759069375045/83ee80e1-93a4-4b6f-8b53-af92bf96b3df.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I’ve been using Cursor as part of my daily development flow and wanted to share what’s worked (and what hasn’t) from my own experience. I’ll keep this casual and short.</p>
<p>Quick note: I’m not affiliated with Cursor in any way. This is just my honest experience using it as part of my daily development flow.</p>
<h2 id="heading-quick-intro-what-is-cursor">Quick intro — what is Cursor?</h2>
<p>Cursor is an AI-powered coding editor that acts like an extra (very eager) developer: it reads your repo, runs agent-style tasks, edits files, suggests fixes, and can even scaffold features. The real game changer for me is that Cursor <em>has the whole codebase as context</em>. You don’t need to paste files or explain the entire project — you just reference what you want, and it knows what you mean.</p>
<h2 id="heading-pricing">Pricing</h2>
<p>Cursor has a free option and paid tiers. Honestly, the free tier didn’t help me much beyond getting a feel for the tool. The real value came once I switched to the paid plan, and I’m grateful my team enabled it for us. On paid plans you get a limited number of requests each month, and you can also set an extra buffer of requests if someone goes over — which is especially useful for teams.</p>
<hr />
<h2 id="heading-my-overall-impression">My overall impression</h2>
<p>I’m genuinely impressed. When you give Cursor a clear task with a simple scope and good instructions, it can really deliver. Some people compare it to having a junior dev working for you — eager to move fast and do as much as possible. I completely agree.</p>
<h2 id="heading-where-cursor-really-helped-me">Where Cursor really helped me</h2>
<ul>
<li><p><strong>Bug fixing:</strong> Quick suggestions to try out, which makes debugging less painful.</p>
</li>
<li><p><strong>Asking questions about the codebase:</strong> Instead of searching forever, I just ask Cursor about specific parts of the repo.</p>
</li>
<li><p><strong>Implementing new features with clear scope:</strong> It’s great at well-defined, non-ambiguous tasks.</p>
</li>
<li><p><strong>Remembering syntax/commands:</strong> Especially across multiple languages and tools.</p>
</li>
<li><p><strong>Running commands directly:</strong> This feature has been surprisingly useful. Instead of switching back and forth, I can run commands right from Cursor and keep my flow.</p>
</li>
</ul>
<h2 id="heading-but-its-not-perfect">But it’s not perfect</h2>
<ul>
<li><p>It makes mistakes and sometimes gives “bandaid” fixes (like just adding a null check without solving the real root cause).</p>
</li>
<li><p>It can get stuck repeating the same approach or stuck in general</p>
</li>
<li><p>You still need to test, review, and ask hard questions. Think of it as a junior dev — you’re still the one driving.</p>
</li>
<li><p>It might overengineer solutions at times</p>
</li>
<li><p>AI hallucinates and gives you wrong answers or partially right ones</p>
</li>
</ul>
<hr />
<h2 id="heading-things-that-helped-me-get-more-out-of-cursor">Things that helped me get more out of Cursor</h2>
<ul>
<li><p><strong>Split complex tasks into steps.</strong> Easier to validate each result.</p>
</li>
<li><p><strong>Use git intentionally.</strong> Feature branches, small commits, incremental progress, stashes, etc to record the steps that are in a good shape or acceptably good to go. That will save you when you need to reverse things safely</p>
</li>
<li><p><strong>Run QA and tests.</strong> Don’t trust the shiny “all fixed” message until you confirm.</p>
</li>
<li><p><strong>Ask for tests.</strong> Make Cursor write them, then review and improve.</p>
</li>
<li><p><strong>Provide detailed context.</strong> Logs, corner cases, knowns/unknowns, filenames, code fragment — the more thoughtful you are at providing guidance, the better the output.</p>
</li>
<li><p><strong>Track usage.</strong> Requests are limited, so I keep an eye on how many I’ve used.</p>
</li>
<li><p><strong>Pair it with ChatGPT.</strong> I use ChatGPT for general questions or planning, Cursor for codebase-aware tasks.</p>
</li>
<li><p><strong>Be specific when reverting changes.</strong> Otherwise, it might undo more than you expect.</p>
</li>
<li><p><strong>Batch steps into one request when possible.</strong> Saves credits.</p>
</li>
<li><p><strong>Keep learning prompt engineering.</strong> Makes a big difference in quality.</p>
</li>
<li><p><strong>Know when to pivot.</strong> If it’s stuck, switch strategies or take over manually.</p>
</li>
<li><p><strong>Still use docs/Stack Overflow/debugging.</strong> AI is great, but not everything.</p>
</li>
</ul>
<p>And yes — don’t waste requests saying “thank you” 😅.</p>
<hr />
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p>I’d say Cursor is <strong>absolutely worth it</strong>. You just need to learn how to use it well: give it scope, guide it, question it, and keep testing. The better you are at driving, the more you’ll get out of it. For me, it’s taken a lot of the heavy lifting and repetitive tasks off my plate, while still leaving me in control of the important decisions.  </p>
<p>What about you? Have you tried Cursor as your AI pair-programmer? How do you use it day-to-day? I would love to hear your experience as well!</p>
]]></content:encoded></item><item><title><![CDATA[Modern Java Feature: Text Blocks]]></title><description><![CDATA[Java developers have long struggled with multi-line strings containing escaped characters and awkward formatting. Enter Text Blocks, a modern Java feature that makes multi-line string handling cleaner, more readable, and more expressive.
🆕 What Is a...]]></description><link>https://codelikeawoman.com/modern-java-feature-text-blocks</link><guid isPermaLink="true">https://codelikeawoman.com/modern-java-feature-text-blocks</guid><category><![CDATA[text blocks]]></category><category><![CDATA[java strings]]></category><category><![CDATA[Modern Java]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Tue, 22 Jul 2025 13:12:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753190645882/db639e67-391c-4ab4-ae51-af45cb6894df.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Java developers have long struggled with multi-line strings containing escaped characters and awkward formatting. Enter <strong>Text Blocks</strong>, a modern Java feature that makes multi-line string handling <em>cleaner, more readable, and more expressive</em>.</p>
<h2 id="heading-what-is-a-text-block">🆕 What Is a Text Block?</h2>
<p>A <strong>text block</strong> is a multi-line string literal introduced as a <strong>preview in Java 13</strong> and <strong>officially added in Java 15</strong>. It allows you to write strings across multiple lines without having to escape every newline or quote.</p>
<h3 id="heading-syntax">Syntax</h3>
<p>Text blocks are enclosed in <strong>three double quotes (</strong><code>"""</code>), and must start on a <strong>new line</strong>:</p>
<pre><code class="lang-java">String html = <span class="hljs-string">""</span><span class="hljs-string">"
    &lt;html&gt;
        &lt;body&gt;
            &lt;h1&gt;Hello, World!&lt;/h1&gt;
        &lt;/body&gt;
    &lt;/html&gt;
    "</span><span class="hljs-string">""</span>;
</code></pre>
<p>This is far more readable than:</p>
<pre><code class="lang-java">String html = <span class="hljs-string">"&lt;html&gt;\n"</span> +
              <span class="hljs-string">"    &lt;body&gt;\n"</span> +
              <span class="hljs-string">"        &lt;h1&gt;Hello, World!&lt;/h1&gt;\n"</span> +
              <span class="hljs-string">"    &lt;/body&gt;\n"</span> +
              <span class="hljs-string">"&lt;/html&gt;\n"</span>;
</code></pre>
<hr />
<h3 id="heading-where-can-you-use-a-text-block">Where Can You Use a Text Block?</h3>
<p>Anywhere you can use a regular string, you can use a text block. That includes:</p>
<ul>
<li><p>Assignments to variables</p>
</li>
<li><p>Method arguments</p>
</li>
<li><p>Return values</p>
</li>
<li><p>Annotations</p>
</li>
<li><p>Logs and templates</p>
</li>
</ul>
<pre><code class="lang-java">System.out.println(<span class="hljs-string">""</span><span class="hljs-string">"
    This is a valid
    text block string
    used as an argument.
    "</span><span class="hljs-string">""</span>);
</code></pre>
<p>Text blocks shine when dealing with structured or long-form content:</p>
<ul>
<li><p>🖥️ <strong>HTML/XML/JSON snippets</strong></p>
</li>
<li><p>💾 <strong>SQL queries</strong></p>
</li>
<li><p>🤖 <strong>Prompt engineering for AI</strong></p>
</li>
<li><p>🧑‍🏫 <strong>Code samples for documentation</strong></p>
</li>
<li><p>📜 <strong>Poetry, song lyrics, or long messages</strong></p>
</li>
</ul>
<pre><code class="lang-java">String sql = <span class="hljs-string">""</span><span class="hljs-string">"
    SELECT id, name
    FROM users
    WHERE active = 1
    ORDER BY name;
    "</span><span class="hljs-string">""</span>;
</code></pre>
<hr />
<h2 id="heading-smart-whitespace-handling-incidental-vs-essential">Smart Whitespace Handling: Incidental vs Essential</h2>
<p>One of the most powerful features of text blocks is their ability to <strong>remove incidental white space</strong>—the indentation that's not part of the string itself but exists to align with your code.</p>
<p>Let’s visualize this with <code>·</code> characters to represent leading spaces.</p>
<h3 id="heading-example-incidental-white-space-removed">👇 Example: Incidental White Space Removed</h3>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">writeHTML</span><span class="hljs-params">()</span> </span>{
    String html = <span class="hljs-string">""</span><span class="hljs-string">"
········&lt;html&gt;
········    &lt;body&gt;
········        &lt;p&gt;Hello World.&lt;/p&gt;
········    &lt;/body&gt;
········&lt;/html&gt;
········"</span><span class="hljs-string">""</span>;
    writeOutput(html);
}
</code></pre>
<p>✅ The output of <code>html</code> becomes:</p>
<pre><code class="lang-plaintext">&lt;html&gt;
    &lt;body&gt;
        &lt;p&gt;Hello World.&lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Java determines the <em>minimum indentation</em> level (based on the closing delimiter position) and removes it from all lines. This keeps your string readable <em>and</em> aligned with your code.</p>
<h3 id="heading-preserving-essential-white-space">Preserving Essential White Space</h3>
<p>To preserve indentation within the string, just move your content to the right:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">writeHTML</span><span class="hljs-params">()</span> </span>{
    String html = <span class="hljs-string">""</span><span class="hljs-string">"
········    &lt;html&gt;
········        &lt;body&gt;
········            &lt;p&gt;Hello World.&lt;/p&gt;
········        &lt;/body&gt;
········    &lt;/html&gt;
········"</span><span class="hljs-string">""</span>;
    writeOutput(html);
}
</code></pre>
<p>Result:</p>
<pre><code class="lang-plaintext">    &lt;html&gt;
        &lt;body&gt;
            &lt;p&gt;Hello World.&lt;/p&gt;
        &lt;/body&gt;
    &lt;/html&gt;
</code></pre>
<h3 id="heading-opting-out-of-trimming-entirely">Opting Out of Trimming Entirely</h3>
<p>If you don’t want Java to trim anything, place the closing delimiter on the far left:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">writeHTML</span><span class="hljs-params">()</span> </span>{
    String html = <span class="hljs-string">""</span><span class="hljs-string">"
                  &lt;html&gt;
                      &lt;body&gt;
                          &lt;p&gt;Hello World.&lt;/p&gt;
                      &lt;/body&gt;
                  &lt;/html&gt;
"</span><span class="hljs-string">""</span>;
    writeOutput(html);
}
</code></pre>
<p>Java will treat every character as-is, preserving all leading spaces.</p>
<blockquote>
<p>For all the nitty-gritty details, see JEP 355.</p>
</blockquote>
<hr />
<h3 id="heading-normalize-line-terminators">Normalize Line Terminators</h3>
<p>Text blocks use <code>\n</code> (line feed) as the default line terminator on all platforms. If you need to convert them to your system-specific line separator (e.g. <code>\r\n</code> on Windows), you can do:</p>
<pre><code class="lang-java">String adjusted = textBlock.replaceAll(<span class="hljs-string">"\n"</span>, System.lineSeparator());
</code></pre>
<p>This ensures your strings behave consistently across environments.</p>
<hr />
<h2 id="heading-new-string-methods-introduced">New String Methods Introduced</h2>
<p>Java 15 introduced several useful methods in the <code>String</code> class to complement and enhance the text block feature:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Method</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>stripIndent()</code></td><td>Removes incidental indentation from a multi-line string</td></tr>
<tr>
<td><code>translateEscapes()</code></td><td>Converts escape sequences like <code>\\n</code> or <code>\\t</code> into actual characters</td></tr>
<tr>
<td><code>formatted(Object...)</code></td><td>A more readable alternative to <code>String.format()</code>, used directly on string instances</td></tr>
</tbody>
</table>
</div><h4 id="heading-example-formatted-with-text-blocks">Example: 📄 <code>formatted(...)</code> with Text Blocks</h4>
<p>You can use <code>.formatted(...)</code> directly on a text block to inject dynamic values:</p>
<pre><code class="lang-java">String email = <span class="hljs-string">""</span><span class="hljs-string">"
    Dear %s,

    Your order #%d has been shipped and is expected to arrive by %s.

    Thank you for shopping with us!
    "</span><span class="hljs-string">""</span>.formatted(<span class="hljs-string">"Mirna"</span>, <span class="hljs-number">12345</span>, <span class="hljs-string">"Friday"</span>);

System.out.println(email);
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-plaintext">Dear Mirna,

Your order #12345 has been shipped and is expected to arrive by Friday.

Thank you for shopping with us!
</code></pre>
<p>This makes text blocks a great fit for templated emails, prompts, or code generation — with clean syntax and no clutter.</p>
<h2 id="heading-official-documentation">📚 Official Documentation</h2>
<p>Want to learn more or see additional examples? Check out the official guide:<br />👉 <a target="_blank" href="https://docs.oracle.com/en/java/javase/15/text-blocks/index.html">Text Blocks in Java 15</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Text blocks are a small yet powerful improvement in Java that makes your code easier to read, write, and maintain—especially when working with structured or formatted content.</p>
<p>No more escaping newlines or cramming everything into one line. Just write clean, readable text!</p>
<p>🧭 Stay tuned for more in the <em>Modern Java Features</em> series!</p>
]]></content:encoded></item><item><title><![CDATA[“Model” Means What, Exactly? Understanding a Word with Many Faces in Tech]]></title><description><![CDATA[In tech, some words seem to show up everywhere — but they don’t always mean the same thing. One of those words is “model.” I remember early on assuming I knew what a model was… only to realize I was completely off.
What I experienced is known as sema...]]></description><link>https://codelikeawoman.com/model-means-what-exactly-understanding-a-word-with-many-faces-in-tech</link><guid isPermaLink="true">https://codelikeawoman.com/model-means-what-exactly-understanding-a-word-with-many-faces-in-tech</guid><category><![CDATA[#esldevs]]></category><category><![CDATA[Mindset]]></category><category><![CDATA[Java]]></category><category><![CDATA[Ruby]]></category><category><![CDATA[Python]]></category><category><![CDATA[OpenApi]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[HTML]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Tue, 17 Jun 2025 21:28:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750195560501/21f0536b-2117-469b-8aef-f2f616e153f3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In tech, some words seem to show up everywhere — but they don’t always mean the same thing. One of those words is <strong>“model.”</strong> I remember early on assuming I knew what a model was… only to realize I was completely off.</p>
<p>What I experienced is known as <strong>semantic overload</strong> — when a single word is used in multiple ways across a field. And now I understand why: <em>“model”</em> is one of the most overloaded words in software and AI.</p>
<p>In the sections below, we’ll break down some of the most common meanings of “model” across different tech contexts, with examples to help make sense of each one.</p>
<hr />
<h2 id="heading-1-openapi-swagger-model-data-structure">1. OpenAPI / Swagger: Model = Data Structure</h2>
<p>In OpenAPI (or Swagger), a <strong>model</strong> refers to a <strong>data structure</strong> — usually described in YAML or JSON — that defines the shape of the data your API sends or receives.</p>
<p>🧠 Think of it as a <em>contract</em> between the client and server.</p>
<p>📦 Example:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">User:</span>
  <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
  <span class="hljs-attr">properties:</span>
    <span class="hljs-attr">id:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">integer</span>
    <span class="hljs-attr">name:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
    <span class="hljs-attr">email:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
</code></pre>
<p>This model describes what a <code>User</code> object should look like when exchanged through the API.</p>
<hr />
<h2 id="heading-2-mvc-model-business-logic-layer">2. MVC: Model = Business Logic Layer</h2>
<p>In <strong>Model-View-Controller (MVC)</strong> architecture, the model represents your <strong>business logic</strong> and <strong>domain data</strong>. It’s responsible for how the data behaves, not how it looks or how users interact with it.</p>
<p>🧠 Think of it as the <em>“what”</em> your app is about.</p>
<p>📦 Example (Java):</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span> </span>{
    <span class="hljs-keyword">private</span> String title;
    <span class="hljs-keyword">private</span> String body;
    <span class="hljs-keyword">private</span> LocalDateTime publishedAt;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Post</span><span class="hljs-params">(String title, String body)</span> </span>{
        <span class="hljs-keyword">this</span>.title = title;
        <span class="hljs-keyword">this</span>.body = body;
        <span class="hljs-keyword">this</span>.publishedAt = LocalDateTime.now();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">publish</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">this</span>.publishedAt = LocalDateTime.now();
    }

    <span class="hljs-comment">// Getters and setters omitted for brevity</span>
}
</code></pre>
<p>This plain Java class represents a <code>Post</code> and contains some basic behavior (like publishing). It’s part of the “Model” in MVC — separate from how the post is displayed (View) or handled via user interaction (Controller).</p>
<hr />
<h2 id="heading-3-ruby-on-rails-model-activerecord-class">3. Ruby on Rails: Model = ActiveRecord Class</h2>
<p>In Rails, “model” often refers to an <strong>ActiveRecord class</strong>, which connects to a database table and includes both data and behavior.</p>
<p>🧠 Think of it as your <em>data and rules in one place</em>.</p>
<p>📦 Example:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span> &lt; ApplicationRecord</span>
  validates <span class="hljs-symbol">:title</span>, <span class="hljs-symbol">presence:</span> <span class="hljs-literal">true</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>This model connects to the <code>posts</code> table and adds validations or callbacks related to posts.</p>
<hr />
<h2 id="heading-4-artificial-intelligence-model-trained-algorithm">4. Artificial Intelligence: Model = Trained Algorithm</h2>
<p>In AI or Machine Learning, a <strong>model</strong> is a trained system that makes predictions or generates content based on patterns it learned from data.</p>
<p>🧠 Think of it as a <em>trained brain</em> that knows how to do a specific task.</p>
<p>📦 Example:</p>
<pre><code class="lang-python">prediction = spam_model.predict(<span class="hljs-string">"You've won a prize!"</span>)
</code></pre>
<p>Here, <code>spam_model</code> is a trained object — not a class or schema — that returns a prediction.</p>
<hr />
<h2 id="heading-5-domain-driven-design-ddd-model-domain-representation">5. Domain-Driven Design (DDD): Model = Domain Representation</h2>
<p>In <strong>Domain-Driven Design</strong>, a <strong>domain model</strong> represents the core concepts and behaviors of your problem space. It’s focused on encapsulating business rules.</p>
<p>🧠 Think of it as a <em>rich, real-world object</em> with behaviors that matter.</p>
<p>📦 Example:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Account</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">deposit</span><span class="hljs-params">(Money amount)</span> </span>{ ... }
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">withdraw</span><span class="hljs-params">(Money amount)</span> </span>{ ... }
}
</code></pre>
<p>This model knows how to modify its own state through well-defined methods.</p>
<hr />
<h2 id="heading-6-frontend-frameworks-model-view-data">6. Frontend Frameworks: Model = View Data</h2>
<p>In frontend frameworks like AngularJS, a <strong>model</strong> is simply the <strong>data behind the UI</strong> — especially in systems with two-way binding.</p>
<p>📦 Example:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">ng-model</span>=<span class="hljs-string">"user.name"</span>&gt;</span>
</code></pre>
<p>Changes in the input automatically update <a target="_blank" href="http://user.name"><code>user.name</code></a>, and vice versa.</p>
<hr />
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>If you’ve ever felt confused about what “model” means, you’re not alone. It’s not you — it’s the context.</p>
<p>The key takeaway is this:<br />✅ <strong>Don’t assume a word means the same thing everywhere.</strong></p>
<p>A beginner’s mindset — being open, curious, and unafraid to ask — helps you adapt faster and avoid misunderstandings.</p>
<p>So the next time someone says <em>“this model does X”</em>, don’t hesitate to ask:<br /><strong>“Wait, which kind of model are we talking about?”</strong><br /><strong>What does ‘model’ mean in this context?</strong></p>
<p>How about you? Have you ever experienced <strong>context overload</strong>?<br />I’d love to hear about it — let me know in the comments. 🙂</p>
]]></content:encoded></item><item><title><![CDATA[🧠 Essential Git Commands Cheat Sheet]]></title><description><![CDATA[Whether you're new to Git or want to keep your workflow sharp, here’s a handy list of commands that cover the most common — and a few life-saving — actions.
Clone the repo
git clone <repository-url>

🔍 See What's Going On
git status

Shows what's ch...]]></description><link>https://codelikeawoman.com/essential-git-commands-cheat-sheet</link><guid isPermaLink="true">https://codelikeawoman.com/essential-git-commands-cheat-sheet</guid><category><![CDATA[Git]]></category><category><![CDATA[cheatsheet]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Mon, 16 Jun 2025 20:12:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750104700778/ba009cca-973f-4c33-a587-3c725d509d40.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Whether you're new to Git or want to keep your workflow sharp, here’s a handy list of commands that cover the most common — and a few life-saving — actions.</p>
<h2 id="heading-clone-the-repo">Clone the repo</h2>
<pre><code class="lang-powershell">git clone &lt;repository<span class="hljs-literal">-url</span>&gt;
</code></pre>
<h2 id="heading-see-whats-going-on">🔍 See What's Going On</h2>
<pre><code class="lang-powershell">git status
</code></pre>
<p>Shows what's changed, what's staged, and what's untracked.</p>
<pre><code class="lang-powershell">git log -<span class="hljs-literal">-oneline</span>
</code></pre>
<p>View commit history (detailed or summarized).</p>
<h2 id="heading-stage-amp-commit-changes">➕ Stage &amp; Commit Changes</h2>
<pre><code class="lang-bash">git add &lt;file&gt;     <span class="hljs-comment"># Stage a single file</span>
git add .          <span class="hljs-comment"># Stage everything</span>
</code></pre>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"Your message here"</span> Creates a commit with your staged changes.
</code></pre>
<blockquote>
<p>💡 <strong>Git Tip:</strong> Think of Git as a three-step process:<br />1️⃣ <em>Working Directory</em> – where you make edits<br />2️⃣ <em>Staging Area</em> – where you select what to commit<br />3️⃣ <em>Repository</em> – where your project history lives</p>
<p>Staging gives you control over what gets committed, so you can group related changes together before saving them permanently.</p>
</blockquote>
<h2 id="heading-stash-changes">🔄 Stash Changes</h2>
<pre><code class="lang-powershell">git stash <span class="hljs-literal">-m</span> <span class="hljs-string">"WIP: login bug"</span>   <span class="hljs-comment"># Save changes with a label</span>
git stash list                  <span class="hljs-comment"># View stashes</span>
git stash apply [<span class="hljs-type">stash</span><span class="hljs-selector-tag">@</span>{<span class="hljs-type">id</span>}]    <span class="hljs-comment"># Reapply a specific stash</span>
</code></pre>
<blockquote>
<p>💡 <strong>Git Tip:</strong> Need to switch tasks but don’t want to commit your work yet?<br />Use <code>git stash</code> to save your changes temporarily and return to a clean working state.<br />Later, use <code>git stash apply</code> to get your work back.</p>
<p>🛠️ Pro Tip: Use <code>git stash list</code> to see all stashes, and <code>git stash drop</code> to delete one you no longer need</p>
</blockquote>
<h2 id="heading-branching">🌿 Branching</h2>
<pre><code class="lang-powershell">git branch                    <span class="hljs-comment"># List branches</span>
git branch feature<span class="hljs-literal">-xyz</span>        <span class="hljs-comment"># Create a new branch</span>
git checkout feature<span class="hljs-literal">-xyz</span>      <span class="hljs-comment"># Switch to it</span>
git checkout <span class="hljs-literal">-b</span> feature<span class="hljs-literal">-xyz</span>   <span class="hljs-comment"># Create and switch to a new branch in one line</span>
git <span class="hljs-keyword">switch</span> feature<span class="hljs-literal">-xyz</span>        <span class="hljs-comment"># Newer switch syntax</span>
</code></pre>
<hr />
<h2 id="heading-sync-with-remote">⬇️⬆️ Sync with Remote</h2>
<pre><code class="lang-powershell">git pull          <span class="hljs-comment"># Pull latest changes</span>
git push          <span class="hljs-comment"># Push local commits</span>

<span class="hljs-comment"># Sets the upstream tracking branch when pushing for the first time</span>
git push <span class="hljs-literal">-u</span> origin [<span class="hljs-type">branch</span>-<span class="hljs-type">name</span>]

<span class="hljs-comment"># Force-push your local branch — use with caution! Ideal after a rebase:</span>
git push -<span class="hljs-literal">-force</span>
</code></pre>
<h2 id="heading-undoing-mistakes">🔧 Undoing Mistakes</h2>
<pre><code class="lang-powershell">git restore &lt;file&gt;            <span class="hljs-comment"># Discard local changes</span>
git restore -<span class="hljs-literal">-staged</span> &lt;file&gt;   <span class="hljs-comment"># Unstage a file</span>
</code></pre>
<hr />
<h2 id="heading-life-saving-commands">🧨 Life-Saving Commands</h2>
<p>Pull the latest from main and rebase your current branch in one single step:</p>
<pre><code class="lang-powershell">git fetch &amp;&amp; git rebase origin/main
</code></pre>
<blockquote>
<p>💡 <strong>Git Tip:</strong> Keep your branch up-to-date and avoid merge commits by rebasing onto the latest <code>main</code>. Perfect for clean history before a PR.</p>
</blockquote>
<p>Remove commits but keep the changes:</p>
<blockquote>
<p>💡 Need to rewrite history? <code>--soft</code> lets you uncommit changes but keeps them staged so you can tweak and recommit.</p>
</blockquote>
<pre><code class="lang-powershell">git reset [<span class="hljs-type">commit</span>-<span class="hljs-type">hash</span>] -<span class="hljs-literal">-soft</span>
</code></pre>
<p>Pull a file from another branch to modify it locally:</p>
<blockquote>
<p>💡 Want just one file from another branch? This command pulls it into your current branch without switching context.</p>
</blockquote>
<pre><code class="lang-powershell">git checkout other<span class="hljs-literal">-branch</span> -- path/to/file
</code></pre>
]]></content:encoded></item><item><title><![CDATA[What Do You Mean by "Dogfooding"? And Other Questions You Were Afraid to Ask]]></title><description><![CDATA[“Let’s dogfood this before the bug bash.”Or maybe: “The feature isn’t gaining traction — we might need to pivot.”
If you’ve ever heard phrases like that and wondered if you know English — you’re not alone.
Tech jargon is part of the culture. It’s not...]]></description><link>https://codelikeawoman.com/what-do-you-mean-by-dogfooding-and-other-questions-you-were-afraid-to-ask</link><guid isPermaLink="true">https://codelikeawoman.com/what-do-you-mean-by-dogfooding-and-other-questions-you-were-afraid-to-ask</guid><category><![CDATA[TechJargon]]></category><category><![CDATA[software culture]]></category><category><![CDATA[StartupLife]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Thu, 12 Jun 2025 20:53:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749733379311/63a045cd-4bb2-4df5-87ff-d71fa023dbc0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>“Let’s dogfood this before the bug bash.”<br />Or maybe: “The feature isn’t gaining traction — we might need to pivot.”</p>
<p>If you’ve ever heard phrases like that and wondered if you know English — you’re not alone.</p>
<p>Tech jargon is part of the culture. It’s not something you usually learn in school, but something you pick up over time as you work, adapt to your company’s way of speaking, and grow more comfortable in the environment.</p>
<p>I put together this glossary to walk you through some of the most common terms — the kind you’ll hear in meetings, Slack threads, and docs. Whether you’re starting your first job in tech, joining a remote team, or working in English as a second language, I hope this gives you helpful context.</p>
<hr />
<h2 id="heading-communication-amp-workflows">💬 Communication &amp; Workflows</h2>
<p><strong>Circling Back</strong><br />A polite way to revisit a topic — used to follow up, remind, or bring it up again.</p>
<ul>
<li><p><em>“Just circling back on that spec we discussed.”</em> → <strong>“Just following up.”</strong></p>
</li>
<li><p><em>“Circling back now that we have more data.”</em> → <strong>“Revisiting now that we know more.”</strong></p>
</li>
<li><p><em>“Let me finish this, and I’ll circle back later today.”</em> → <strong>“I’ll return to this later.”</strong></p>
</li>
</ul>
<p><strong>Touch Base</strong><br />A casual way to say "connect briefly."</p>
<blockquote>
<p><em>“Can we touch base tomorrow?”</em> → <strong>“Have a quick chat?”</strong></p>
</blockquote>
<p><strong>Bandwidth</strong><br />Refers to someone’s time or capacity to take on work.</p>
<blockquote>
<p><em>“I don’t have bandwidth right now.”</em> → <strong>“I’m too busy.”</strong></p>
</blockquote>
<p><strong>Low-Hanging Fruit</strong><br />Simple tasks that bring quick wins.</p>
<blockquote>
<p><em>“Let’s tackle the low-hanging fruit first.”</em> → <strong>“Let’s start with the easiest wins.”</strong></p>
</blockquote>
<p><strong>Doubling Down</strong><br />Committing more strongly to an idea or effort.</p>
<blockquote>
<p><em>“We’re doubling down on performance.”</em> → <strong>“We’re putting more effort into this area.”</strong></p>
</blockquote>
<p><strong>Pushing Back</strong><br />Means delaying or rescheduling something for later — not earlier.</p>
<ul>
<li><p><em>“We’re pushing back the deadline to next Friday.”</em> → <strong>“Delaying the deadline.”</strong></p>
</li>
<li><p><em>“Can we push the meeting back an hour?”</em> → <strong>“Start the meeting later.”</strong></p>
</li>
<li><p><em>“They pushed back the release to Q3.”</em> → <strong>“Postponed to Q3.”</strong></p>
</li>
</ul>
<p><strong>Why it’s confusing:</strong> For many ESL speakers, the word “back” suggests moving something earlier — like going back in time. But in this context, it actually means shifting something <em>further into the future</em>. It’s a counterintuitive phrase until you get used to how it’s used at work.</p>
<hr />
<h2 id="heading-product-amp-qa">🧪 Product &amp; QA</h2>
<p><strong>Dogfooding</strong><br />Using your own product internally before releasing it to users.</p>
<blockquote>
<p><em>“We dogfooded the new dashboard and found key issues.”</em><br />Why it matters: It helps catch problems early and shows confidence in your product.</p>
</blockquote>
<p><strong>Bug Bash</strong><br />A planned team session where everyone tries to find bugs.</p>
<blockquote>
<p><em>“The bug bash helped uncover edge cases before launch.”</em><br />Why it matters: It’s a fast, team-wide way to catch problems with more eyes on the product.</p>
</blockquote>
<p><strong>Bug Dash</strong><br />A focused effort to fix as many bugs as possible in a short time.</p>
<blockquote>
<p><em>“We’re doing a bug dash to clean up the backlog.”</em></p>
</blockquote>
<hr />
<h2 id="heading-growth-strategy-amp-metrics">📈 Growth, Strategy &amp; Metrics</h2>
<p><strong>Churn</strong><br />When users stop using your product or cancel a subscription.</p>
<ul>
<li><p><em>“Our churn rate is 7%.”</em> → <strong>7 out of 100 users left this month.</strong></p>
</li>
<li><p><em>“We saw churn increase after the pricing change.”</em> → <strong>“More users left.”</strong></p>
</li>
</ul>
<p>Why it matters: It’s a sign that users didn’t find enough value to stay. You’ll hear it often in conversations about retention, onboarding, or pricing.</p>
<p><strong>RRM (Rolling Retention Metric)</strong><br />Tracks what percent of users return after a set number of days (e.g. 7-day RRM).</p>
<blockquote>
<p><em>“Our 7-day RRM dropped — let’s look into why users disengage.”</em></p>
</blockquote>
<p><strong>North Star Metric</strong><br />The single most important number that reflects product success.</p>
<blockquote>
<p><em>“Weekly active users is our north star metric.”</em></p>
</blockquote>
<p><strong>Customer Journey</strong><br />The complete experience a user has — from signup to loyal customer (or churn).</p>
<blockquote>
<p><em>“We’re mapping the customer journey to improve onboarding.”</em></p>
</blockquote>
<hr />
<h3 id="heading-common-workplace-shorthand">Common Workplace Shorthand</h3>
<p>These abbreviations are everywhere — in Slack threads, PR reviews (oops, just used one myself — PR = <em>Pull Request</em> 😅), email subjects, and Jira comments. Here’s what they mean:</p>
<h4 id="heading-hard-stop"><strong>Hard Stop</strong></h4>
<p>A firm end time for a meeting or task.<br />💬 “I have a hard stop at 3PM.” → <em>“I need to leave at 3, no matter what.”</em></p>
<h4 id="heading-asap-eod-cob"><strong>ASAP / EOD / COB</strong></h4>
<p>Used to signal urgency or deadlines.<br />• <strong>ASAP</strong> = <em>As Soon As Possible</em><br />• <strong>EOD</strong> = <em>End of Day</em><br />• <strong>COB</strong> = <em>Close of Business</em> (same as EOD, just a bit more formal)<br />💬 “Please review the PR ASAP.”<br />💬 “Can you finish this by EOD?”</p>
<p><strong>OOO</strong><br />Out of Office — often used in auto-replies or status updates.<br />💬 “OOO next week, back on Monday!”<br />💬 “Just a heads-up, I’ll be OOO this afternoon.”</p>
<h4 id="heading-tldr"><strong>TL;DR</strong></h4>
<p>Too long; didn’t read — a summary, usually at the top (or bottom!) of a long message.<br />💬 “TL;DR: We’re moving forward with option B.”</p>
<h4 id="heading-fyi"><strong>FYI</strong></h4>
<p>For your information — no action needed, just awareness.<br />💬 “FYI: The deploy is scheduled for tomorrow morning.”</p>
<h4 id="heading-eta"><strong>ETA</strong></h4>
<p>Estimated time of arrival — when something is expected to be done or delivered.<br />💬 “What’s the ETA on the bug fix?”</p>
<h4 id="heading-nit"><strong>NIT</strong></h4>
<p>Short for “nitpick.”<br />Used in code reviews to point out something small — not a blocker.<br />💬 “NIT: Consider renaming this variable for clarity.”<br /><em>Translation: You don’t have to change it… but I noticed it.</em></p>
<h2 id="heading-final-thoughts">🙏 Final Thoughts</h2>
<p>Jargon is something you grow into. Don’t feel pressured to memorize everything — this list is just a head start. Save it, refer back to it, and most of all, don’t be afraid to ask when something doesn’t make sense.</p>
<p>Beyond these common terms, acronyms are everywhere. English speakers love to shorten things, and the corporate world takes it to the next level. At my current job, for example, <strong>CPT</strong> stands for <em>Client, Project, and Tasks</em>. You’ll encounter acronyms for tools, teams, roles — almost everything.</p>
<p>If it ever feels like people are speaking a foreign language, you’re not alone. Especially when landing your first job in tech or working remotely in English, it can feel a bit overwhelming at first. But with a little patience and curiosity, you’ll be fluent in “corporate” in no time!</p>
<p><strong>What about you?</strong><br />Is there a term you keep hearing that isn’t listed here? Drop it in the comments — I’d love to keep learning, too.</p>
]]></content:encoded></item><item><title><![CDATA[Why Separating DTOs from Domain Models Matters in Swift App Architecture]]></title><description><![CDATA[Let me be clear:I hate having to write both DTOs and domain models. It feels like double work. It clutters the codebase. It adds yet another layer to think about when you're just trying to get an API to show some data on screen.
And yet... I do it be...]]></description><link>https://codelikeawoman.com/why-separating-dtos-from-domain-models-matters-in-swift-app-architecture</link><guid isPermaLink="true">https://codelikeawoman.com/why-separating-dtos-from-domain-models-matters-in-swift-app-architecture</guid><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Clean Architecture]]></category><category><![CDATA[dto]]></category><category><![CDATA[domain model]]></category><dc:creator><![CDATA[Virginia Pujols]]></dc:creator><pubDate>Thu, 12 Jun 2025 14:54:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749667508573/6c46c541-333c-455e-84dd-564aca732858.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let me be clear:<br />I <em>hate</em> having to write both DTOs and domain models. It feels like double work. It clutters the codebase. It adds yet another layer to think about when you're just trying to get an API to show some data on screen.</p>
<p>And yet... I do it because when I didn’t, it blew up in my face later.</p>
<p>This post breaks down what DTOs and domain models are, why separating them is important, and provides a few real-world examples of how skipping that step can backfire.</p>
<hr />
<h2 id="heading-lets-talk-about-the-basics">Let’s Talk About the Basics</h2>
<h3 id="heading-dto-data-transfer-object">DTO (Data Transfer Object)</h3>
<p>A DTO is a <strong>data container</strong> used to exchange information across boundaries — usually between a remote API and your app.</p>
<p>Think: Backend response → DTO → App</p>
<p>It represents exactly what the backend gives you. No assumptions, no transformations, just raw data.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">UserDTO</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> first_name: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> last_name: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> email_address: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> created_at: <span class="hljs-type">String</span>
}
</code></pre>
<h3 id="heading-domain-model">Domain Model</h3>
<p>The domain model reflects the structure and language of <strong>your app’s business logic</strong>. It’s what the UI, business rules, and features should operate on.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> fullName: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> email: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> joinDate: <span class="hljs-type">Date</span>
}
</code></pre>
<p>Notice how this version:</p>
<ul>
<li><p>Combines <code>first_name</code> + <code>last_name</code></p>
</li>
<li><p>Converts <code>created_at</code> (a string) into a <code>Date</code></p>
</li>
<li><p>Renames fields for clarity and Swift naming conventions</p>
</li>
</ul>
<h2 id="heading-why-the-separation-matters">Why the Separation Matters</h2>
<h3 id="heading-reason-1-domain-logic-shouldnt-care-about-backend-garbage"><strong>Reason</strong> #1: Domain Logic Shouldn’t Care About Backend Garbage</h3>
<p>Sometimes APIs give you fields that don’t belong in your app logic at all:</p>
<ul>
<li><p>Debug-only fields</p>
</li>
<li><p>Internal backend IDs</p>
</li>
<li><p>Raw numeric codes instead of enums</p>
</li>
<li><p><strong>Deeply nested structures you don’t actually need</strong></p>
</li>
</ul>
<p>Let’s say you receive a JSON like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"meta"</span>: {
    <span class="hljs-attr">"request_id"</span>: <span class="hljs-string">"abc123"</span>,
    <span class="hljs-attr">"timestamp"</span>: <span class="hljs-string">"2024-01-01T00:00:00Z"</span>
  },
  <span class="hljs-attr">"data"</span>: {
    <span class="hljs-attr">"user"</span>: {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">42</span>,
      <span class="hljs-attr">"profile"</span>: {
        <span class="hljs-attr">"first_name"</span>: <span class="hljs-string">"John"</span>,
        <span class="hljs-attr">"last_name"</span>: <span class="hljs-string">"Appleseed"</span>,
        <span class="hljs-attr">"email"</span>: <span class="hljs-string">"john@example.com"</span>
      },
      <span class="hljs-attr">"roles"</span>: [
        {
          <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>,
          <span class="hljs-attr">"label"</span>: <span class="hljs-string">"admin"</span>,
          <span class="hljs-attr">"permissions"</span>: [<span class="hljs-string">"READ"</span>, <span class="hljs-string">"WRITE"</span>, <span class="hljs-string">"DELETE"</span>]
        }
      ],
      <span class="hljs-attr">"audit"</span>: {
        <span class="hljs-attr">"created_by"</span>: <span class="hljs-string">"system"</span>,
        <span class="hljs-attr">"created_at"</span>: <span class="hljs-string">"2023-05-01T10:00:00Z"</span>,
        <span class="hljs-attr">"updated_at"</span>: <span class="hljs-string">"2023-06-01T15:30:00Z"</span>
      }
    }
  }
}
</code></pre>
<h4 id="heading-what-should-you-do">What <em>should</em> you do?</h4>
<p>First, define a clean domain model:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> fullName: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> email: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> role: <span class="hljs-type">String</span>
}
</code></pre>
<p>Then, write a DTO and map what you need:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">UserResponseDTO</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> data: <span class="hljs-type">DataNode</span>
    <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">DataNode</span>: <span class="hljs-title">Codable</span> </span>{
        <span class="hljs-keyword">let</span> user: <span class="hljs-type">UserNode</span>
    }
    ...
}

<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">UserResponseDTO</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">toDomain</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">User</span> {
        <span class="hljs-keyword">let</span> user = data.user
        <span class="hljs-keyword">return</span> <span class="hljs-type">User</span>(
            id: user.id,
            fullName: <span class="hljs-string">"\(user.profile.first_name) \(user.profile.last_name)"</span>,
            email: user.profile.email,
            role: user.roles.first?.label ?? <span class="hljs-string">"unknown"</span>
        )
    }
}
</code></pre>
<p>Now your domain model is clean, shallow, and safe — and your app no longer lives at the mercy of backend nesting changes.</p>
<h3 id="heading-reason-2-backend-contracts-change"><strong>Reason</strong> #2: Backend Contracts Change</h3>
<p>Ever had a backend team rename a field because they “standardized the naming convention”? One day it’s <code>email_address</code>. Next day? <code>email</code>. No warning. No version bump. Just… surprise!</p>
<p>If you were piping that directly into your SwiftUI view, you’ve just earned yourself a lovely <code>nil</code> crash and a bunch of angry users.</p>
<p>But if that chaos hit a <strong>DTO</strong>, you’d be fine (only one file change).</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">CodingKeys</span>: <span class="hljs-title">String</span>, <span class="hljs-title">CodingKey</span> </span>{
    <span class="hljs-keyword">case</span> emailAddress = <span class="hljs-string">"email"</span>
}
</code></pre>
<p>The UI wouldn’t even notice the explosion behind the scenes. That’s the point. DTOs act like airbags — ugly, but essential when things go wrong.</p>
<h3 id="heading-reason-3-different-sources-one-model"><strong>Reason</strong> #3: Different Sources, One Model</h3>
<p>Suppose your app gets <code>User</code> data from:</p>
<ul>
<li><p>An API</p>
</li>
<li><p>A local cache</p>
</li>
<li><p>A CoreData store</p>
</li>
</ul>
<p>All of them return different formats, and some even lack fields.</p>
<p><strong>Solution</strong>: Use DTOs per source and map them into a consistent domain model.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">UserDTOFromAPI</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">toDomain</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">User</span> {
        <span class="hljs-type">User</span>(
            id: id, 
            fullName: <span class="hljs-string">"\(first_name) \(last_name)"</span>, 
            email: email_address,
            joinDate: created_at.toDate()
        )
    }
}

<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">UserDTOFromLocalCache</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">toDomain</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">User</span> {
        <span class="hljs-type">User</span>(
            id: userId, 
            fullName: name, 
            email: email, 
            joinDate: <span class="hljs-type">Date</span>(timeIntervalSince1970: timestamp)
        )
    }
}
</code></pre>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>Yes, writing both DTOs and domain models feels like <em>extra work</em> most of the time, but the truth is: if you skipped them, you’ll pay for it later — in broken UIs, fragile tests, and spaghetti logic tied directly to whatever the backend felt like returning that week. So now I treat them like seatbelts. You don’t put them on because you’re expecting a crash; you put them on because you <em>know</em> what happens when you don’t.</p>
<p>If you want your Swift app to scale, survive backend changes, and stay testable and sane, separate your DTOs and your domain logic.<br />Future you will thank you.</p>
]]></content:encoded></item><item><title><![CDATA[My First Week with Ruby on Rails as a Java Developer]]></title><description><![CDATA[After more than a decade working with Java, I recently jumped into a codebase written in Ruby on Rails. I wasn’t entirely sure what to expect — just that it would be different. And it was.
I’m writing this for anyone who’s ever considered trying a ne...]]></description><link>https://codelikeawoman.com/my-first-week-with-ruby-on-rails-as-a-java-developer</link><guid isPermaLink="true">https://codelikeawoman.com/my-first-week-with-ruby-on-rails-as-a-java-developer</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Java Developer]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[coding]]></category><category><![CDATA[beginner]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Wed, 04 Jun 2025 21:01:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749069705041/68d8fa1f-3039-426d-94e2-13e1df4e6a97.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After more than a decade working with Java, I recently jumped into a codebase written in Ruby on Rails. I wasn’t entirely sure what to expect — just that it would be different. And it was.</p>
<p>I’m writing this for anyone who’s ever considered trying a new tech stack and felt intimidated by not knowing enough. If that’s you, you’re not alone. It’s okay to be new. It’s okay not to know yet.</p>
<p>In this post, I’m sharing a few things that surprised me during my first week, and a reflection on what it feels like to start over in unfamiliar territory.</p>
<h2 id="heading-adjusting-to-interpreted-code">Adjusting to interpreted code</h2>
<p>Coming from Java, I'm used to having the compiler catch my mistakes immediately. If something is wrong, it just doesn’t compile — simple. But with Ruby being an interpreted language, that safety net is gone. When I refactor code now, I can’t just assume it’s fine — it might not even be syntactically correct, and I won’t know until I run it.</p>
<p>That felt strange at first. I caught myself thinking, “Did I break something? Did I miss a typo?” It pushed me to rely more on writing test cases just to make sure the code even runs — not just that it works correctly, but that it <em>runs</em>. Still, I like that now I have one more reason to write those tests.</p>
<h2 id="heading-no-type-definitions">No type definitions</h2>
<p>One thing I’m still adjusting to is the lack of type declarations — not even <code>def</code> for variables. I’ll just see a variable name and a value assigned to it, and that’s it.</p>
<pre><code class="lang-ruby">total = <span class="hljs-number">5</span>
name = <span class="hljs-string">"Mirna"</span>
</code></pre>
<p>Coming from Java, where you’d write something like:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> total = <span class="hljs-number">5</span>;
String name = <span class="hljs-string">"Mirna"</span>;
</code></pre>
<p>…it feels odd not to declare intent up front. I’m not sure yet what issues this might bring long-term, but so far I really appreciate how concise the code is. It’s fast to write and easy to follow — once you get used to it.</p>
<hr />
<h2 id="heading-running-code-with-no-main">Running code with no <code>main</code></h2>
<p>Another thing that surprised me: you can just open a console (IRB or Rails console) and run Ruby code — no <code>main</code>, no class, no setup. Just type and go.</p>
<pre><code class="lang-ruby"><span class="hljs-number">2</span> + <span class="hljs-number">2</span>
<span class="hljs-comment"># =&gt; 4</span>

<span class="hljs-string">"hello"</span>.upcase
<span class="hljs-comment"># =&gt; "HELLO"</span>
</code></pre>
<p>Coming from Java, where even the simplest program needs at least a <code>public static void main(String[] args)</code>This felt super lightweight.</p>
<hr />
<h2 id="heading-you-can-call-any-method-from-the-console">You can call any method from the console</h2>
<p>Along the same lines, something I really liked is that you can call any method from the Rails console and immediately see the result. No need to wire up a controller, run the app, or hit an endpoint.</p>
<p>If the method is loaded, you just call it:</p>
<pre><code class="lang-ruby">TimeEntry.describe(<span class="hljs-string">"Worked on bug fixes"</span>)
</code></pre>
<p>It just runs and returns the result.</p>
<p>I didn’t use it much yet, but I can already tell this is going to be useful when I’m testing things out on the spot — especially when I don’t want to break flow or set up a full test just to try something small.</p>
<hr />
<h2 id="heading-final-reflection-being-a-beginner">Final Reflection – Being a Beginner</h2>
<p>The biggest adjustment hasn’t been the syntax or the framework — it’s been the feeling of being new. Starting with a tech stack you don’t know means becoming a beginner again in areas where you once felt confident.</p>
<p>Not knowing how things are supposed to be done — whether it’s the language itself, Rails conventions, GraphQL, or even the testing setup — can feel disorienting. Here’s what has helped so far:</p>
<ul>
<li><p>Being incremental</p>
</li>
<li><p>Alternating between breadth and depth depending on what I’m trying to implement</p>
</li>
<li><p>Embracing a beginner’s mindset</p>
</li>
<li><p>Asking questions</p>
</li>
<li><p>Googling</p>
</li>
<li><p>Leaning on AI when it helps</p>
</li>
<li><p>Reaching out to teammates when I need clarity</p>
</li>
<li><p>Focusing on one task at a time and approaching it in a structured way — learning just enough to get it done, instead of trying to master everything at once</p>
</li>
<li><p>Being Patient</p>
</li>
</ul>
<p>With this approach, I learn something every day. And little by little, things begin to make more sense. The code doesn’t feel as alien as it did on day one.</p>
<p>And even though everything feels new, not everything <em>is</em> new. Many things come with you: your intuition, your debugging skills, your understanding of software fundamentals — they don’t disappear. They guide you through the process and help more than you might expect.</p>
<p>It’s only been a week — there’s still a long way to go — but I’m glad I took the chance. And I’m even more excited to keep learning.</p>
<p>I want to reiterate what I said in the intro, for you, today:</p>
<blockquote>
<p><em>It’s okay to be new.</em><br /><em>It’s okay not to know yet.</em></p>
</blockquote>
<p>And if you’ve gone through a similar transition — from one stack to another, or from confidence to beginner mode — I’d love to hear how it went for you. Feel free to share your experience!</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[Modern Java Switch: Clear and Concise]]></title><description><![CDATA[Java’s switch statement has come a long way.
In earlier versions, it was verbose, error-prone, and limited in what you could do with it. But starting in Java 14 and finalized in Java 21, switch has evolved into a far more powerful and expressive tool...]]></description><link>https://codelikeawoman.com/modern-java-switch-clear-and-concise</link><guid isPermaLink="true">https://codelikeawoman.com/modern-java-switch-clear-and-concise</guid><category><![CDATA[java switch]]></category><category><![CDATA[Switch case]]></category><category><![CDATA[Modern Java]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Tue, 20 May 2025 21:56:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747778139313/53a4aff4-2579-4e9b-98df-757fe700782e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Java’s</strong> <code>switch</code> statement has come a long way.</p>
<p>In earlier versions, it was verbose, error-prone, and limited in what you could do with it. But starting in Java 14 and finalized in Java 21, <code>switch</code> has evolved into a far more powerful and expressive tool.</p>
<p>In this article, we’ll walk through the key enhancements introduced across Java versions — with examples and explanations — so you can start using the upgrades right away.</p>
<hr />
<h2 id="heading-arrow-syntax-gt-introduced-in-java-14">➤ Arrow Syntax (<code>-&gt;</code>) <em>(introduced in Java 14)</em></h2>
<p>In traditional <code>switch</code>, forgetting a <code>break</code> could lead to bugs due to fall-through behavior. Modern <code>switch</code> introduces arrow syntax to make things safer and more concise.</p>
<blockquote>
<p>💡 <em>Fall-through</em> means that if a <code>case</code> doesn't explicitly end (usually with <code>break</code>), execution continues into the next <code>case</code> — often unintentionally. Modern <code>switch</code> introduces arrow syntax to make things safer and more concise.</p>
</blockquote>
<p><strong>Before:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">switch</span> (status) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">"NEW"</span>:
    result = <span class="hljs-string">"Pending"</span>;
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-string">"DONE"</span>:
    result = <span class="hljs-string">"Complete"</span>;
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">default</span>:
    result = <span class="hljs-string">"Unknown"</span>;
}
</code></pre>
<p><strong>After:</strong></p>
<pre><code class="lang-java">result = <span class="hljs-keyword">switch</span> (status) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">"NEW"</span> -&gt; <span class="hljs-string">"Pending"</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-string">"DONE"</span> -&gt; <span class="hljs-string">"Complete"</span>;
  <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Unknown"</span>;
};
</code></pre>
<p>✅ No need for <code>break</code><br />✅ No risk of accidental fall-through<br />✅ Cleaner and more readable</p>
<hr />
<h2 id="heading-multi-label-case-introduced-in-java-14">➤ Multi-label Case <em>(introduced in Java 14)</em></h2>
<p>You can now group multiple labels in a single case using commas.</p>
<pre><code class="lang-java">result = <span class="hljs-keyword">switch</span> (status) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">"NEW"</span>, <span class="hljs-string">"PENDING"</span> -&gt; <span class="hljs-string">"In Progress"</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-string">"DONE"</span> -&gt; <span class="hljs-string">"Completed"</span>;
  <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Unknown"</span>;
};
</code></pre>
<p>✅ Reduces duplication<br />✅ Easier to maintain grouped logic</p>
<hr />
<h2 id="heading-switch-as-an-expression-introduced-in-java-14">➤ Switch as an Expression <em>(introduced in Java 14)</em></h2>
<p>Switch can now return a value, just like an expression. You can directly assign its result to a variable.</p>
<pre><code class="lang-java">String label = <span class="hljs-keyword">switch</span> (code) {
  <span class="hljs-keyword">case</span> <span class="hljs-number">1</span> -&gt; <span class="hljs-string">"Low"</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-number">2</span> -&gt; <span class="hljs-string">"Medium"</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-number">3</span> -&gt; <span class="hljs-string">"High"</span>;
  <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Unknown"</span>;
};
</code></pre>
<p>✅ No temp variables needed<br />✅ Functional, compact code style</p>
<blockquote>
<p>📝 <em>Note: This example uses integers to illustrate the feature, but in real-world code, enums are often more appropriate for modeling discrete, known states like severity or status. If all you need is to associate static values (like labels) to enums, it's often cleaner to define those inside the enum itself.</em> <code>switch</code> expressions shine when you need dynamic branching or more complex logic that's not easily handled by an enum field.</p>
</blockquote>
<hr />
<h2 id="heading-yield-for-multi-line-blocks-introduced-in-java-13">➤ <code>yield</code> for Multi-line Blocks <em>(introduced in Java 13)</em></h2>
<p>When you need more logic before returning a value from a case, use a block with <code>yield</code>.</p>
<pre><code class="lang-java">String message = <span class="hljs-keyword">switch</span> (status) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">"NEW"</span> -&gt; {
    log(<span class="hljs-string">"Creating message..."</span>);
    yield <span class="hljs-string">"Pending"</span>;
  }
  <span class="hljs-keyword">case</span> <span class="hljs-string">"DONE"</span> -&gt; <span class="hljs-string">"Complete"</span>;
  <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Unknown"</span>;
};
</code></pre>
<p>✅ <code>yield</code> lets you return from a block<br />⚠️ <code>return</code> is not allowed inside a <code>switch</code> expression block</p>
<hr />
<h2 id="heading-pattern-matching-finalized-in-java-21">➤ Pattern Matching <em>(finalized in Java 21)</em></h2>
<p>Java 21 introduced <strong>pattern matching for</strong> <code>switch</code> as a stable feature. It allows switching based on the type of an object and binds variables inline.</p>
<pre><code class="lang-java">Object obj = <span class="hljs-string">"Hello"</span>;

String result = <span class="hljs-keyword">switch</span> (obj) {
  <span class="hljs-keyword">case</span> String s -&gt; <span class="hljs-string">"String of length "</span> + s.length();
  <span class="hljs-keyword">case</span> Integer i -&gt; <span class="hljs-string">"Integer doubled: "</span> + (i * <span class="hljs-number">2</span>);
  <span class="hljs-keyword">case</span> <span class="hljs-keyword">null</span> -&gt; <span class="hljs-string">"Was null"</span>;
  <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Something else"</span>;
};
</code></pre>
<p>✅ Match and bind values in one line<br />✅ Works with <code>null</code><br />✅ Cleaner than <code>instanceof</code> + cast</p>
<hr />
<h2 id="heading-when-guards-finalized-in-java-21">➤ <code>when</code> Guards <em>(finalized in Java 21)</em></h2>
<p>You can add conditions to a type match using <code>when</code>:</p>
<pre><code class="lang-java">String result = <span class="hljs-keyword">switch</span> (obj) {
  <span class="hljs-keyword">case</span> String s when s.length() &gt; <span class="hljs-number">10</span> -&gt; <span class="hljs-string">"Long string"</span>;
  <span class="hljs-keyword">case</span> String s -&gt; <span class="hljs-string">"Short string"</span>;
  <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Other"</span>;
};
</code></pre>
<p>✅ Adds control to pattern matches</p>
<hr />
<h2 id="heading-exhaustiveness-with-sealed-types-introduced-in-java-17">➤ Exhaustiveness with Sealed Types <em>(introduced in Java 17)</em></h2>
<p>If you switch over a <code>sealed</code> class or interface, Java checks that all subtypes are handled — and you don’t need a <code>default</code> case.</p>
<pre><code class="lang-java">sealed <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Shape</span> <span class="hljs-title">permits</span> <span class="hljs-title">Circle</span>, <span class="hljs-title">Square</span> </span>{}
<span class="hljs-function">record <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> r)</span> implements Shape </span>{}
<span class="hljs-function">record <span class="hljs-title">Square</span><span class="hljs-params">(<span class="hljs-keyword">double</span> s)</span> implements Shape </span>{}

String label = <span class="hljs-keyword">switch</span> (shape) {
  <span class="hljs-keyword">case</span> Circle c -&gt; <span class="hljs-string">"Circle with radius "</span> + c.r();
  <span class="hljs-keyword">case</span> Square s -&gt; <span class="hljs-string">"Square with side "</span> + s.s();
};
</code></pre>
<p>✅ Compiler ensures all subtypes are covered<br />✅ Safe refactoring: if a new subtype is added, you’ll get a compile error</p>
<hr />
<h2 id="heading-conclusion">✅ Conclusion</h2>
<p>The modern <code>switch</code> is one of the most developer-friendly upgrades to Java in years.<br />It eliminates boilerplate, reduces common errors, and introduces a clean, expression-style syntax that aligns well with modern programming principles.</p>
<p>If you haven’t already, try using these enhancements in your next refactor — they make your code more readable, expressive, and maintainable.</p>
<p>Happy refactoring!</p>
]]></content:encoded></item><item><title><![CDATA[Understanding the Observer Design Pattern (With a Simple Book Club Java Example)]]></title><description><![CDATA[The Observer pattern is a behavioral design pattern that defines a one-to-many relationship between objects. When the state of one object (the subject) changes, all its dependents (the observers) are automatically notified and updated. This pattern p...]]></description><link>https://codelikeawoman.com/understanding-the-observer-design-pattern-with-a-simple-book-club-java-example</link><guid isPermaLink="true">https://codelikeawoman.com/understanding-the-observer-design-pattern-with-a-simple-book-club-java-example</guid><category><![CDATA[Observer Pattern]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Sun, 18 May 2025 00:35:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747528110882/c48dace6-f9c9-418e-8fe3-2a13710ae6ce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Observer_w_update.svg/800px-Observer_w_update.svg.png" alt="File:Observer w update.svg" /></p>
<p>The <strong>Observer pattern</strong> is a behavioral design pattern that defines a <strong>one-to-many relationship</strong> between objects. When the state of one object (the <em>subject</em>) changes, all its dependents (the <em>observers</em>) are automatically notified and updated. This pattern promotes <strong>loose coupling</strong> between the subject and its observers and is widely used in event-driven systems.</p>
<p>What do you need to implement it on a high level?</p>
<ul>
<li><p>Define two interfaces: Observer and Subject</p>
</li>
<li><p>Define a concrete implementation of the Subject</p>
</li>
<li><p>Define as many concrete implementations of the Observer interface as you need</p>
</li>
<li><p>Wired everything together externally</p>
</li>
</ul>
<hr />
<h2 id="heading-key-characteristics-of-the-observer-pattern">✨ Key Characteristics of the Observer Pattern</h2>
<ul>
<li><p><strong>One-to-many dependency</strong>: One subject notifies multiple observers.</p>
</li>
<li><p><strong>Loose coupling</strong>: Subjects don't need to know the concrete details of their observers.</p>
</li>
<li><p><strong>Dynamic subscription</strong>: Observers can be added or removed at runtime.</p>
</li>
<li><p><strong>Push or pull model</strong>: The subject may either send specific data or let the observer pull the data it needs.</p>
</li>
</ul>
<hr />
<h2 id="heading-when-should-you-use-it">🧠 When Should You Use It?</h2>
<p>Use the Observer pattern when:</p>
<ul>
<li><p>You have a data source or subject whose state changes over time.</p>
</li>
<li><p>Multiple parts of your system need to respond to that change.</p>
</li>
<li><p>You want to decouple the logic of the source from its listeners.</p>
</li>
</ul>
<p>It is common in:</p>
<ul>
<li><p>UI frameworks (e.g., event listeners in Java Swing or JavaScript)</p>
</li>
<li><p>MVC architectures</p>
</li>
<li><p>Logging systems</p>
</li>
<li><p>Notification and alerting systems</p>
</li>
</ul>
<hr />
<h2 id="heading-a-concrete-example-book-club-announcement-system">📚 A Concrete Example: Book Club Announcement System</h2>
<p>Let’s implement the Observer pattern using a simple domain: a <strong>Book Club</strong>. The book club announces new books on different schedules (monthly, biweekly, yearly), and its members are notified via different channels (email, push notification).</p>
<p>We’ll begin by defining the core interfaces for the pattern. This will help establish the contract for communication between the subject and its observers.</p>
<h3 id="heading-step-1-define-observer-and-subject-interfaces">🔌 Step 1: Define Observer and Subject Interfaces</h3>
<p>The <code>Observer</code> interface represents any component that wants to receive updates. The <code>Subject</code> interface is implemented by the class that owns the state and sends updates.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Observer</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(ScheduleType scheduleType, String bookTitle)</span></span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Subject</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">addObserver</span><span class="hljs-params">(Observer observer)</span></span>;
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">removeObserver</span><span class="hljs-params">(Observer observer)</span></span>;
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">notifyObservers</span><span class="hljs-params">(ScheduleType scheduleType, String bookTitle)</span></span>;
}
</code></pre>
<h3 id="heading-step-2-create-the-concrete-subject-bookclub">📦 Step 2: Create the Concrete Subject - BookClub</h3>
<p>The <code>BookClub</code> class implements the <code>Subject</code> interface. It stores a list of observers and notifies them whenever a new book is announced. The announcement can happen on different schedules — monthly, biweekly, or yearly — using clearly named methods like <code>announceMonthlyBook</code>. This improves <strong>clarity and reusability</strong>, as each method encapsulates a specific context in which observers are notified.</p>
<p>This implementation also demonstrates a <strong>push model</strong>: the subject actively pushes data (schedule type and book title) to all observers when a change occurs.</p>
<blockquote>
<p>🧠 In contrast, a <strong>pull model</strong> would mean the subject simply notifies observers that something changed, and the observers then call back to the subject to fetch the updated data. For that, the <code>update()</code> method in the <code>Observer</code> interface might receive no arguments, and observers would query the <code>BookClub</code> to retrieve the latest book title themselves.</p>
</blockquote>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookClub</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Subject</span> </span>{
  <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">ScheduleType</span> </span>{
    BIWEEKLY, MONTHLY, YEARLY
  }

  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> List&lt;Observer&gt; observers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addObserver</span><span class="hljs-params">(Observer observer)</span> </span>{
    observers.add(observer);
  }

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">removeObserver</span><span class="hljs-params">(Observer observer)</span> </span>{
    observers.remove(observer);
  }

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">notifyObservers</span><span class="hljs-params">(ScheduleType scheduleType, String bookTitle)</span> </span>{
    System.out.printf(<span class="hljs-string">"Announcing new book, scheduleType: %s, bookTitle: %s%n"</span>, scheduleType, bookTitle);
    observers.forEach(o -&gt; o.update(scheduleType, bookTitle));
    System.out.println(<span class="hljs-string">"------------"</span>);
  }

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">announceMonthlyBook</span><span class="hljs-params">(String bookTitle)</span> </span>{
    notifyObservers(ScheduleType.MONTHLY, bookTitle);
  }

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">announceBiweeklyBook</span><span class="hljs-params">(String bookTitle)</span> </span>{
    notifyObservers(ScheduleType.BIWEEKLY, bookTitle);
  }

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">announceYearlyBook</span><span class="hljs-params">(String bookTitle)</span> </span>{
    notifyObservers(ScheduleType.YEARLY, bookTitle);
  }
}
</code></pre>
<h3 id="heading-step-3-create-the-concrete-observers">📬 Step 3: Create the Concrete Observers</h3>
<p>Observers react to announcements in different ways. Below are two examples: one sends an email and another sends a push notification.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailNotificationMember</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Observer</span> </span>{
  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(ScheduleType scheduleType, String bookTitle)</span> </span>{
    System.out.printf(<span class="hljs-string">"[Email] New %s book: '%s'%n"</span>, scheduleType, bookTitle);
  }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PushNotificationMember</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Observer</span> </span>{
  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(ScheduleType scheduleType, String bookTitle)</span> </span>{
    System.out.printf(<span class="hljs-string">"[PushNotification] New %s book: '%s'%n"</span>, scheduleType, bookTitle);
  }
}
</code></pre>
<p>Each observer implements the <code>update</code> method, which is called by the <code>BookClub</code> subject.</p>
<h3 id="heading-step-4-wiring-it-together-in-the-main-app">🚀 Step 4: Wiring it Together in the Main App</h3>
<p>The main application is where we create the <code>BookClub</code>, register observers, and simulate announcements.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookClubApp</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
    BookClub nonFictionClub = <span class="hljs-keyword">new</span> BookClub();
    nonFictionClub.addObserver(<span class="hljs-keyword">new</span> EmailNotificationMember());
    nonFictionClub.addObserver(<span class="hljs-keyword">new</span> PushNotificationMember());

    nonFictionClub.announceMonthlyBook(<span class="hljs-string">"Atomic Habits"</span>);
    nonFictionClub.announceBiweeklyBook(<span class="hljs-string">"Hellen Keller Summarized Bio"</span>);
    nonFictionClub.announceYearlyBook(<span class="hljs-string">"A History of Ancient Rome"</span>);
  }
}
</code></pre>
<p>When run, this will output messages showing which observers received which book announcements.</p>
<hr />
<h2 id="heading-beyond-the-basics-real-world-design-considerations">🔍 Beyond the Basics: Real-World Design Considerations</h2>
<h3 id="heading-push-vs-pull-model">📤 Push vs Pull Model</h3>
<p>Our BookClub example uses a <strong>push model</strong>: the subject passes all necessary data directly to the observers. This works well for small examples but may lead to long parameter lists and tight coupling as the data grows.</p>
<blockquote>
<p>💡 In such cases, it's better to encapsulate the data being sent in a dedicated class (e.g., <code>BookAnnouncement</code>) to keep the observer interface clean and extendable.</p>
</blockquote>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookAnnouncement</span> </span>{
  <span class="hljs-keyword">private</span> ScheduleType scheduleType;
  <span class="hljs-keyword">private</span> String bookTitle;
  <span class="hljs-comment">// getters, constructors, etc.</span>
}
</code></pre>
<p>Then the observer interface could change to:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(BookAnnouncement announcement)</span></span>;
</code></pre>
<p>🧠 In contrast, a <strong>pull model</strong> would mean the subject simply notifies observers that something changed, and the observers then call back to the subject to fetch the updated data. For that, the <code>update()</code> method in the <code>Observer</code> interface might receive no arguments, and observers would query the <code>BookClub</code> to retrieve the latest book title themselves.</p>
<h3 id="heading-modeling-real-members-vs-notification-channels">🧩 Modeling Real Members vs Notification Channels</h3>
<p>Our example keeps things simple by treating notification channels (email, push) as observers. But in a real system, you'd model things differently.</p>
<h3 id="heading-option-1-member-as-the-observer">🧍 Option 1: <code>Member</code> as the Observer</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Member</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Observer</span> </span>{
  <span class="hljs-keyword">private</span> String name;
  <span class="hljs-keyword">private</span> String email;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> wantsMonthlyOnly;

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(ScheduleType scheduleType, String bookTitle)</span> </span>{
    <span class="hljs-keyword">if</span> (wantsMonthlyOnly &amp;&amp; scheduleType != ScheduleType.MONTHLY) <span class="hljs-keyword">return</span>;
    System.out.printf(<span class="hljs-string">"Email to %s: New %s book: '%s'%n"</span>, name, scheduleType, bookTitle);
  }
}
</code></pre>
<h3 id="heading-option-2-notification-observers-acting-on-member">📡 Option 2: Notification Observers Acting on <code>Member</code></h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailNotifier</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Observer</span> </span>{
  <span class="hljs-keyword">private</span> List&lt;Member&gt; members;

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(ScheduleType scheduleType, String bookTitle)</span> </span>{
    <span class="hljs-keyword">for</span> (Member m : members) {
      <span class="hljs-keyword">if</span> (!m.prefersEmail()) <span class="hljs-keyword">continue</span>;
      System.out.printf(<span class="hljs-string">"[Email] To %s: '%s' (%s)%n"</span>, m.getEmail(), bookTitle, scheduleType);
    }
  }
}
</code></pre>
<p>This second approach <strong>decouples domain from infrastructure</strong>, scales better, and aligns more closely with real-world design needs.</p>
<hr />
<h2 id="heading-observer-pattern-in-frameworks-and-real-systems">🧩 Observer Pattern in Frameworks and Real Systems</h2>
<p>In real-world software systems, the Observer pattern appears frequently — even if you don’t always implement it directly. Recognizing it helps you understand the underlying architecture of many tools and frameworks.</p>
<p>Some common real-world manifestations include:</p>
<ul>
<li><p><strong>Pub/Sub architectures</strong>: Systems like Apache Kafka, RabbitMQ, or Google Pub/Sub implement the Observer pattern at scale. Publishers emit events to a channel or topic, and subscribers react to those events.</p>
</li>
<li><p><strong>UI frameworks</strong>: In <strong>Java Swing</strong>, <strong>React</strong>, or <strong>Android</strong>, you often attach listeners or observers to UI components to handle events.</p>
</li>
<li><p><strong>JavaScript</strong>: Methods like <code>addEventListener</code> in the DOM model exemplify the pattern.</p>
</li>
<li><p><strong>Spring Framework</strong>: The <code>@EventListener</code> annotation enables event-driven programming by observing and reacting to domain events.</p>
</li>
<li><p><strong>Reactive Programming</strong>: Libraries like RxJava, Project Reactor, or RxJS are built entirely around observables and subscribers.</p>
</li>
</ul>
<p>Understanding the pattern beneath these tools gives you an edge when debugging, designing for extensibility, or choosing the right communication strategy in your system.</p>
<hr />
<h2 id="heading-conclusion">✅ Conclusion</h2>
<p>The Observer pattern is powerful when you need dynamic, loosely-coupled communication between components. While you may not implement it often by hand, understanding it helps you better navigate modern event-driven and reactive systems.</p>
<p>The BookClub example demonstrates the essentials, and the design reflection helps bridge the gap between learning and applying the pattern effectively in real-world systems.</p>
<p><strong>Have you ever implemented the Observer pattern yourself, or mostly seen it abstracted in frameworks?</strong> I’d genuinely love to hear your experience. Whether you’re revisiting the pattern or discovering it for the first time, I hope this article gave you a clearer picture of how it works — and why it matters. Thanks for reading, and happy coding!</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[Strategy Design Pattern: Clear and Concise with Java Examples]]></title><description><![CDATA[The Strategy pattern lets you define a family of algorithms, encapsulate each one, and make them interchangeable. It enables selecting an algorithm at runtime, promoting flexibility and adherence to SOLID principles.

Understanding the Class Diagram
...]]></description><link>https://codelikeawoman.com/strategy-design-pattern-clear-and-concise-with-java-examples</link><guid isPermaLink="true">https://codelikeawoman.com/strategy-design-pattern-clear-and-concise-with-java-examples</guid><category><![CDATA[design patterns]]></category><category><![CDATA[StrategyPattern]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Thu, 15 May 2025 15:27:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747323085933/c115c998-86a2-453a-865d-bb69453a26e8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <strong>Strategy pattern</strong> lets you define a family of algorithms, encapsulate each one, and make them interchangeable. It enables selecting an algorithm at runtime, promoting flexibility and adherence to SOLID principles.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/3/39/Strategy_Pattern_in_UML.png" alt /></p>
<h3 id="heading-understanding-the-class-diagram">Understanding the Class Diagram</h3>
<ul>
<li><p><strong>Context</strong>: Has a <code>Strategy</code> object and uses it to delegate the work, without knowing the implementation details.</p>
</li>
<li><p><strong>Strategy</strong>: An interface defining a method (here called <code>execute()</code>), which each concrete strategy implements with its own behavior.</p>
</li>
<li><p><strong>ConcreteStrategyA / B</strong>: Specific implementations of the strategy, interchangeable at runtime.</p>
</li>
</ul>
<p><strong>How it works</strong>: The <code>Context</code> relies on the <code>Strategy</code> to perform the task. This allows swapping behaviors easily, promoting flexibility and following the Open/Closed Principle.</p>
<h3 id="heading-simple-example">Simple Example</h3>
<p>Let’s say we’re implementing a payment system, and we have multiple payment methods:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentService</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(String method, <span class="hljs-keyword">int</span> amount)</span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-string">"credit"</span>.equals(method)) {
            <span class="hljs-comment">// logic for credit card</span>
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-string">"paypal"</span>.equals(method)) {
            <span class="hljs-comment">// logic for PayPal</span>
        }
        <span class="hljs-comment">// more conditions to come...</span>
    }
}
</code></pre>
<p>Having a long payment method with the needed logic to process multiple payment methods is rigid, grows unwieldy, and violates <strong>Open/Closed Principle</strong> (OCP). Each new method increases <strong>cyclomatic complexity</strong> and requires modifying the existing code.</p>
<h3 id="heading-applying-the-strategy-pattern">Applying the Strategy Pattern</h3>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">int</span> amount)</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreditCardPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">int</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid "</span> + amount + <span class="hljs-string">" with credit card"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PayPalPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">int</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid "</span> + amount + <span class="hljs-string">" with PayPal"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentService</span> </span>{
    <span class="hljs-keyword">private</span> PaymentStrategy strategy;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PaymentService</span><span class="hljs-params">(PaymentStrategy strategy)</span> </span>{
        <span class="hljs-keyword">this</span>.strategy = strategy;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setStrategy</span><span class="hljs-params">(PaymentStrategy strategy)</span> </span>{
        <span class="hljs-keyword">this</span>.strategy = strategy;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">process</span><span class="hljs-params">(<span class="hljs-keyword">int</span> amount)</span> </span>{
        strategy.pay(amount);
    }
}
</code></pre>
<p>✅ This avoids conditionals, respects OCP, and makes each strategy testable and reusable — aligning with <strong>Single Responsibility Principle</strong> (SRP) too.</p>
<h3 id="heading-example-usage">Example Usage</h3>
<pre><code class="lang-java">PaymentService service = <span class="hljs-keyword">new</span> PaymentService(<span class="hljs-keyword">new</span> CreditCardPayment());
service.processPayment(<span class="hljs-number">100</span>);  <span class="hljs-comment">// Outputs: Paid $100 with Credit Card.</span>

service.setStrategy(<span class="hljs-keyword">new</span> PayPalPayment());
service.processPayment(<span class="hljs-number">75</span>);   <span class="hljs-comment">// Outputs: Paid $75 with PayPal.</span>
</code></pre>
<hr />
<h3 id="heading-a-quick-note-on-cyclomatic-complexity">A Quick Note on Cyclomatic Complexity</h3>
<p><strong>Cyclomatic complexity</strong> increases as your code has more <code>if-else</code> branches, making it harder to test, understand, and change safely.</p>
<h4 id="heading-without-strategy-pattern-multiple-paths">❌ Without Strategy Pattern (Multiple Paths)</h4>
<pre><code class="lang-java">javaCopyEditclass PaymentService {
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(String method, <span class="hljs-keyword">int</span> amount)</span> </span>{
        <span class="hljs-keyword">if</span> (method.equals(<span class="hljs-string">"credit"</span>)) {
            System.out.println(<span class="hljs-string">"Paid with Credit Card"</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (method.equals(<span class="hljs-string">"paypal"</span>)) {
            System.out.println(<span class="hljs-string">"Paid with PayPal"</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (method.equals(<span class="hljs-string">"applepay"</span>)) {
            System.out.println(<span class="hljs-string">"Paid with Apple Pay"</span>);
        }
    }
}
</code></pre>
<p>Every new method adds a new branch — more paths, more chances to break something.</p>
<h4 id="heading-with-strategy-pattern-single-path">✅ With Strategy Pattern (Single Path)</h4>
<pre><code class="lang-java">javaCopyEditclass PaymentService {
    <span class="hljs-keyword">private</span> PaymentStrategy strategy;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PaymentService</span><span class="hljs-params">(PaymentStrategy strategy)</span> </span>{
        <span class="hljs-keyword">this</span>.strategy = strategy;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">process</span><span class="hljs-params">(<span class="hljs-keyword">int</span> amount)</span> </span>{
        strategy.pay(amount); <span class="hljs-comment">// Always a single, clean path</span>
    }
}
</code></pre>
<p>No matter how many strategies you add, <code>process()</code> always follows one path.<br />This makes your code <strong>easier to test, reason about, and extend</strong> — which helps maintain quality as the system grows.</p>
<h3 id="heading-functional-programming-a-modern-alternative">Functional Programming: A Modern Alternative?</h3>
<p>In languages that support <strong>first-class functions</strong>, you can simplify the strategy pattern using lambdas:</p>
<pre><code class="lang-java">Consumer&lt;Integer&gt; creditCard = amount -&gt; System.out.println(<span class="hljs-string">"Paid "</span> + amount + <span class="hljs-string">" with credit card"</span>);
Consumer&lt;Integer&gt; paypal = amount -&gt; System.out.println(<span class="hljs-string">"Paid "</span> + amount + <span class="hljs-string">" with PayPal"</span>);

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(Consumer&lt;Integer&gt; strategy, <span class="hljs-keyword">int</span> amount)</span> </span>{
    strategy.accept(amount);
}
</code></pre>
<p>For short, stateless behaviors, lambdas are concise and flexible. But if the strategy:</p>
<ul>
<li><p>Has internal state</p>
</li>
<li><p>Needs validation logic</p>
</li>
<li><p>Requires encapsulation</p>
</li>
</ul>
<p>…then creating a full class (like <code>CreditCardPayment</code>) may be more appropriate to uphold <strong>SRP</strong> and <strong>encapsulation</strong>.</p>
<hr />
<h3 id="heading-when-should-you-use-the-strategy-pattern">When Should You Use the Strategy Pattern?</h3>
<p>Look for these <strong>clues</strong>:</p>
<h4 id="heading-1-you-have-multiple-if-else-or-switch-statements-selecting-behavior">1. <strong>You have multiple</strong> <code>if-else</code> or <code>switch</code> statements selecting behavior</h4>
<h4 id="heading-2-you-expect-the-behavior-to-change-at-runtime">2. <strong>You expect the behavior to change at runtime</strong></h4>
<p>Strategy lets you swap logic dynamically — for example, letting a user choose a payment method at runtime.</p>
<h4 id="heading-3-you-want-to-follow-the-openclosed-principle">3. <strong>You want to follow the Open/Closed Principle</strong></h4>
<p>New behaviors can be added via new strategy classes, without touching existing logic.</p>
<h4 id="heading-4-you-want-to-reuse-or-test-behaviors-independently">4. <strong>You want to reuse or test behaviors independently</strong></h4>
<p>Each strategy is a standalone unit that’s easier to test and reuse in other parts of the system.</p>
<h3 id="heading-tip-let-the-strategy-pattern-emerge">💡 Tip: Let the Strategy Pattern Emerge</h3>
<blockquote>
<p>Start with the simplest solution. If you notice repeated conditionals or growing complexity, <strong>that’s your cue to refactor</strong> using the Strategy pattern.</p>
<p>With experience, you’ll start recognizing these patterns earlier and apply them upfront when it makes sense.</p>
</blockquote>
<h3 id="heading-conclusion">🧩 Conclusion</h3>
<p>The Strategy pattern is one of the simplest and most practical ways to apply the <strong>SOLID principles</strong>. In fact, if you study SOLID first, you’ll see that Strategy is a natural implementation of those ideas in action.<br />👉 You can refresh those principles in my article: <a target="_blank" href="https://code-like-a-woman.hashnode.dev/solid-principles-refresher">SOLID Principles Refresher</a></p>
<p>By applying this pattern, you get code that is:</p>
<ul>
<li><p>Easier to maintain</p>
</li>
<li><p>Less prone to errors</p>
</li>
<li><p>Simpler to test and extend</p>
</li>
</ul>
<p>I think there’s no real downside to using Strategy, as long as you apply it where <strong>flexibility is needed</strong> and don’t over-engineer parts of your code that are meant to stay simple or static.</p>
<p>👉 <strong>Enjoyed this article?</strong><br />Check out the rest of my <strong>Design Patterns</strong> series here:<br />🔗 <a target="_blank" href="https://code-like-a-woman.hashnode.dev/series/design-patterns">code-like-a-woman.hashnode.dev/series/design-patterns</a></p>
]]></content:encoded></item><item><title><![CDATA[The Prototype Pattern with Java Examples]]></title><description><![CDATA[What Is the Prototype Pattern?
A prototype is a pre-existing object that you use as a template to create new objects. Instead of creating an object from scratch, with newYou clone an existing one that already has the desired state.
The Prototype Patt...]]></description><link>https://codelikeawoman.com/the-prototype-pattern-with-java-examples</link><guid isPermaLink="true">https://codelikeawoman.com/the-prototype-pattern-with-java-examples</guid><category><![CDATA[prototype design pattern]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Java]]></category><category><![CDATA[cloneable]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Mon, 05 May 2025 15:05:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746457539218/7419eaf3-e3de-4f9f-bfe4-1fee48027dc3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-what-is-the-prototype-pattern">What Is the Prototype Pattern?</h3>
<p>A <strong>prototype</strong> is a <strong>pre-existing object that you use as a template</strong> to create new objects. Instead of creating an object from scratch, with <code>new</code>You <strong>clone an existing one</strong> that already has the desired state.</p>
<p>The <strong>Prototype Pattern</strong> is a creational design pattern that lets you:</p>
<ul>
<li><p>Create new objects by <strong>copying</strong> (not instantiating) a prototype</p>
</li>
<li><p>Avoid repeating complex setup logic</p>
</li>
<li><p>Keep code flexible by not tying it to specific class constructors</p>
</li>
</ul>
<p>For example, here’s how you would copy an object without this pattern:</p>
<pre><code class="lang-java">Book book1 = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"Effective Java"</span>, <span class="hljs-string">"Joshua Bloch"</span>, List.of(<span class="hljs-string">"Item 1"</span>, <span class="hljs-string">"Item 2"</span>));

Book book2 = <span class="hljs-keyword">new</span> Book(
    book1.getTitle(),
    book1.getAuthor(),
    <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(book1.getChapters())
);
</code></pre>
<p>You have to manually copy each field — error-prone and repetitive.</p>
<hr />
<h3 id="heading-with-prototype-pattern-via-copy-method">🧬 With Prototype Pattern (via copy method)</h3>
<pre><code class="lang-java">Book book1 = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"Effective Java"</span>, <span class="hljs-string">"Joshua Bloch"</span>, List.of(<span class="hljs-string">"Item 1"</span>, <span class="hljs-string">"Item 2"</span>));
Book book2 = book1.copy();
</code></pre>
<p>Much cleaner and encapsulated — the <code>copy()</code> method inside <code>Book</code> handles the duplication safely.</p>
<p><strong>In Java, you have two alternatives to implement the pattern: implementing the Cloneable interface or defining a custom</strong> <code>copy()</code> <strong>method.</strong></p>
<hr />
<h3 id="heading-ways-to-implement-the-prototype-pattern-in-java">Ways to Implement the Prototype Pattern in Java</h3>
<h4 id="heading-option-1-using-cloneable-superclone">Option 1: Using <code>Cloneable</code> + <code>super.clone()</code></h4>
<p>🧩 Before We Start: What Is <code>Cloneable</code> and What Does It Do?</p>
<p>To use <code>super.clone()</code> in Java, your class must implement the <code>Cloneable</code> interface:</p>
<pre><code>public interface Cloneable { }
</code></pre><p>It’s a <strong>marker interface</strong> — it has no methods. Its purpose is to signal the JVM that your object supports cloning. If your class does <strong>not</strong> implement <code>Cloneable</code>, calling <code>super.clone()</code> will throw a <code>CloneNotSupportedException</code>.</p>
<p><strong>What You Must Do:</strong></p>
<ol>
<li><p>Implement <code>Cloneable</code></p>
</li>
<li><p>Override <code>clone()</code> and make it <code>public</code></p>
</li>
<li><p>Handle <code>CloneNotSupportedException</code> or throw it</p>
</li>
<li><p>Return the correct type by downcasting</p>
</li>
</ol>
<p>Here’s the implementation of the Prototype pattern following this recipe:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Document</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Cloneable</span> </span>{
    <span class="hljs-keyword">private</span> String title;
    <span class="hljs-keyword">private</span> List&lt;String&gt; paragraphs;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Document</span><span class="hljs-params">(String title, List&lt;String&gt; paragraphs)</span> </span>{
        <span class="hljs-keyword">this</span>.title = title;
        <span class="hljs-keyword">this</span>.paragraphs = paragraphs;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Document <span class="hljs-title">clone</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">return</span> (Document) <span class="hljs-keyword">super</span>.clone(); <span class="hljs-comment">// Shallow copy</span>
        } <span class="hljs-keyword">catch</span> (CloneNotSupportedException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> AssertionError(); <span class="hljs-comment">// This should never happen</span>
        }
    }
}
</code></pre>
<p>✅ <strong>Pros</strong>: fast, native shallow copy, you can skip the manual work of copying each field</p>
<p>❌ <strong>Cons</strong>: This is shallow copying, which might violate the principle of least surprise (more on that later)</p>
<h4 id="heading-option-2-custom-copy-no-cloneable">Option 2: Custom Copy (No <code>Cloneable</code>)</h4>
<p>You implement your copy method manually and have full control of what you copy and follow the copying approach (deep or shallow) that best follows your needs:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Document</span> </span>{
    <span class="hljs-keyword">private</span> String title;
    <span class="hljs-keyword">private</span> List&lt;String&gt; paragraphs;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Document</span><span class="hljs-params">(String title, List&lt;String&gt; paragraphs)</span> </span>{
        <span class="hljs-keyword">this</span>.title = title;
        <span class="hljs-keyword">this</span>.paragraphs = paragraphs;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> Document <span class="hljs-title">copy</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Document(title, <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(paragraphs));
    }
}
</code></pre>
<p>✅ <strong>Pros</strong>: clearer, performs deep copy, no weird <code>CloneNotSupportedException</code></p>
<p>❌ <strong>Cons</strong>: more manual work</p>
<hr />
<h3 id="heading-shallow-vs-deep-copy-key-differences">📃 Shallow vs Deep Copy: Key Differences</h3>
<p>Whether you're using <code>Cloneable</code> or a manual copy method, you can implement a deep or shallow copy of your objects. Understanding shallow vs deep copy is necessary:</p>
<h4 id="heading-shallow-copy-example">Shallow Copy Example</h4>
<pre><code class="lang-java">Document original = <span class="hljs-keyword">new</span> Document(<span class="hljs-string">"My Title"</span>, <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(List.of(<span class="hljs-string">"Intro"</span>, <span class="hljs-string">"Content"</span>)));
Document copy = original.clone();

copy.getParagraphs().set(<span class="hljs-number">0</span>, <span class="hljs-string">"Modified"</span>);
System.out.println(original.getParagraphs()); <span class="hljs-comment">// Prints: ["Modified", "Content"]</span>
</code></pre>
<p>This happens because both <code>Document</code> instances share the same <code>paragraphs</code> list.</p>
<h4 id="heading-deep-copy-example-with-cloneable">Deep Copy Example (with Cloneable)</h4>
<pre><code class="lang-java"><span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Document <span class="hljs-title">clone</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">try</span> {
        Document copy = (Document) <span class="hljs-keyword">super</span>.clone();
        copy.paragraphs = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(<span class="hljs-keyword">this</span>.paragraphs); <span class="hljs-comment">// Deep copy the list</span>
        <span class="hljs-keyword">return</span> copy;
    } <span class="hljs-keyword">catch</span> (CloneNotSupportedException e) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> AssertionError();
    }
}
</code></pre>
<p>Now, modifying <code>copy.paragraphs</code> won't affect the original object.</p>
<p>This deep copy can also be achieved without <code>Cloneable</code> by writing a custom <code>copy()</code> method. The key is duplicating mutable fields to avoid shared references.</p>
<hr />
<h3 id="heading-performance-vs-clarity-should-you-use-superclone">⚖️ Performance vs. Clarity: Should You Use <code>super.clone()</code>?</h3>
<blockquote>
<p><strong>"The Principle of Least Surprise"</strong> says that code should behave in a way that minimizes confusion for those reading or using it. Users should not be surprised by how something works.</p>
</blockquote>
<p><code>Cloneable</code> in Java violates this principle because:</p>
<ul>
<li><p>It defines no methods, yet calling <code>super.clone()</code> depends on it.</p>
</li>
<li><p>Forgetting to implement it leads to unexpected <code>CloneNotSupportedException</code>.</p>
</li>
<li><p>Even when it works, it does a shallow copy by default, which can lead to shared internal state.</p>
</li>
</ul>
<p>In short:</p>
<ul>
<li><code>super.clone()</code> is <strong>fast</strong> but potentially confusing.</li>
</ul>
<ul>
<li>Manual <code>copy()</code> methods are <strong>clearer</strong> and allow full control.</li>
</ul>
<p>Use what fits your case:</p>
<ul>
<li><p>Go with <code>clone()</code> for speed and simplicity <strong>if</strong> you're confident about the structure.</p>
</li>
<li><p>Prefer manual copies for <strong>clarity</strong>, <strong>immutability</strong>, and <strong>safe separation of state</strong>.</p>
</li>
</ul>
<hr />
<h3 id="heading-disadvantages-of-the-prototype-pattern">🔻 Disadvantages of the Prototype Pattern</h3>
<ol>
<li><p><strong>Complex Cloning Logic:</strong> Deep copying can be error-prone and requires careful handling of nested objects, references, and circular dependencies.</p>
</li>
<li><p><strong>Cloning Limitations in Java</strong></p>
<ul>
<li><p>Using <code>clone()</code> (especially in Java) may confuse developers unfamiliar with how shallow vs deep copies work.</p>
</li>
<li><p>Java’s <code>Cloneable</code> interface is considered flawed:</p>
<ul>
<li><p>It lacks a <code>clone()</code> method in the interface.</p>
</li>
<li><p><code>Object.clone()</code> is protected, requiring workarounds.</p>
</li>
<li><p>Doesn't support deep cloning out of the box.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Hard to Maintain</strong></p>
<ul>
<li>If objects evolve (e.g., new fields), developers must update the cloning logic, increasing maintenance effort and risk of bugs.</li>
</ul>
</li>
</ol>
<h3 id="heading-conclusion">Conclusion</h3>
<p>The Prototype Pattern lets you <strong>create new objects by copying</strong> existing ones. It can improve performance, simplify object creation, and reduce coupling to concrete classes.</p>
<p>You can implement it using Java's <code>Cloneable</code> interface and <code>super.clone()</code> or define your own copy methods:</p>
<ul>
<li><p>Use <code>super.clone()</code> when speed matters and your object is simple</p>
</li>
<li><p>Use manual copying when clarity, immutability, or safety is more important</p>
</li>
</ul>
<p>Choose the approach that best matches the complexity and goals of your project.</p>
]]></content:encoded></item><item><title><![CDATA[The Builder Pattern in Java: A Tasty Example]]></title><description><![CDATA[The Builder pattern is a creational design pattern used to construct complex objects step-by-step. It’s useful when a class has many optional parameters or an object construction needs to be made more readable and flexible.
In this post, we’ll explor...]]></description><link>https://codelikeawoman.com/the-builder-pattern-in-java-a-tasty-example</link><guid isPermaLink="true">https://codelikeawoman.com/the-builder-pattern-in-java-a-tasty-example</guid><category><![CDATA[builder pattern]]></category><category><![CDATA[design patterns]]></category><dc:creator><![CDATA[Mirna De Jesus Cambero]]></dc:creator><pubDate>Mon, 05 May 2025 01:20:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746407894010/f7ad8ac9-caa5-4d4d-becd-fee5e2a40263.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Builder pattern is a creational design pattern used to <strong>construct complex objects step-by-step</strong>. It’s useful when a class has many optional parameters or an object construction needs to be made more readable and flexible.</p>
<p>In this post, we’ll explore the Builder pattern through a fun and relatable example: building a custom sandwich.</p>
<hr />
<h2 id="heading-1-what-is-the-builder-pattern-and-when-to-use-it">1. What Is the Builder Pattern and When to Use It?</h2>
<p>The Builder Pattern lets you <strong>separate object construction from its representation</strong>. It’s helpful when:</p>
<ul>
<li><p>You have a class with many parameters</p>
</li>
<li><p>Some parameters are optional</p>
</li>
<li><p>You want to make object creation readable and safe</p>
</li>
<li><p>You want to avoid telescoping constructors (constructors with many overloads)</p>
</li>
</ul>
<h3 id="heading-the-basic-recipe-for-the-builder-pattern">🍞 The Basic Recipe for the Builder Pattern</h3>
<p>Before jumping into the full example, here’s a quick overview of how the Builder pattern is typically implemented:</p>
<p><strong>Prerequisite</strong>: You have a class with many fields or complex configuration logic.</p>
<h3 id="heading-steps">🔧 Steps:</h3>
<ol>
<li><p>In the enclosing class (the one with many fields), define a <strong>static nested</strong> <code>Builder</code> class.</p>
</li>
<li><p>In the <code>Builder</code> class, declare <strong>the same fields</strong> as in the enclosing class.</p>
</li>
<li><p>In the <code>Builder</code> constructor, set any <strong>required fields</strong>.</p>
</li>
<li><p>In the <code>Builder</code>, provide setter methods (e.g., <code>setX(value)</code>) for <strong>optional fields</strong>.</p>
</li>
<li><p>Ensure each setter <strong>returns</strong> <code>this</code> (the builder instance) so you can <strong>chain calls fluently</strong>.</p>
</li>
<li><p>In the <code>Builder</code>, implement a <code>build()</code> method that returns the final object.</p>
</li>
<li><p>In the enclosing class, create a <strong>private constructor</strong> that initializes its fields using the builder’s fields.</p>
</li>
</ol>
<h2 id="heading-2-a-sandwich-builder-example">2. A Sandwich Builder Example</h2>
<p>Let’s say you want to create a customizable sandwich with required and optional ingredients.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> design_patterns;

<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sandwich</span> </span>{
    <span class="hljs-comment">//required fields</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String breadType;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String mainFilling;

    <span class="hljs-comment">//optional fields</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String cheese;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> List&lt;String&gt; veggies;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> List&lt;String&gt; sauces;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">boolean</span> toasted;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Sandwich</span><span class="hljs-params">(Builder builder)</span> </span>{
       <span class="hljs-keyword">this</span>.breadType = builder.breadType;
       <span class="hljs-keyword">this</span>.mainFilling = builder.mainFilling;
       <span class="hljs-keyword">this</span>.cheese = builder.cheese;
       <span class="hljs-keyword">this</span>.veggies = builder.veggies;
       <span class="hljs-keyword">this</span>.sauces = builder.sauces;
       <span class="hljs-keyword">this</span>.toasted = builder.toasted;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Builder <span class="hljs-title">builder</span><span class="hljs-params">(String breadType, String mainFilling)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Builder(breadType, mainFilling);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> String.format(
            <span class="hljs-string">"Sandwich: \n- Bread: %s\n- Main Filling: %s\n- Cheese: %s\n- Veggies: %s\n- Sauces: %s\n- Toasted: %s"</span>,
            breadType,
            mainFilling,
            cheese != <span class="hljs-keyword">null</span> ? cheese : <span class="hljs-string">"None"</span>,
            veggies != <span class="hljs-keyword">null</span> ? veggies : <span class="hljs-string">"None"</span>,
            sauces != <span class="hljs-keyword">null</span> ? sauces : <span class="hljs-string">"None"</span>,
            toasted ? <span class="hljs-string">"Yes"</span> : <span class="hljs-string">"No"</span>
        );
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Builder</span> </span>{
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String breadType;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String mainFilling;
        <span class="hljs-keyword">private</span> String cheese;
        <span class="hljs-keyword">private</span> List&lt;String&gt; veggies;
        <span class="hljs-keyword">private</span> List&lt;String&gt; sauces;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> toasted;

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Builder</span><span class="hljs-params">(String breadType, String mainFilling)</span> </span>{
            <span class="hljs-keyword">this</span>.breadType = breadType;
            <span class="hljs-keyword">this</span>.mainFilling = mainFilling;
            <span class="hljs-keyword">this</span>.veggies = List.of();
            <span class="hljs-keyword">this</span>.sauces = List.of();
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> Builder <span class="hljs-title">setCheese</span><span class="hljs-params">(String cheese)</span> </span>{
            <span class="hljs-keyword">this</span>.cheese = cheese;
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> Builder <span class="hljs-title">setVeggies</span><span class="hljs-params">(List&lt;String&gt; veggies)</span> </span>{
            <span class="hljs-keyword">this</span>.veggies = veggies.stream().toList();
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> Builder <span class="hljs-title">setSauces</span><span class="hljs-params">(List&lt;String&gt; sauces)</span> </span>{
            <span class="hljs-keyword">this</span>.sauces = sauces.stream().toList();
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> Builder <span class="hljs-title">setToasted</span><span class="hljs-params">(<span class="hljs-keyword">boolean</span> toasted)</span> </span>{
            <span class="hljs-keyword">this</span>.toasted = toasted;
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> Sandwich <span class="hljs-title">build</span><span class="hljs-params">()</span> </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Sandwich(<span class="hljs-keyword">this</span>);
        }
    }
}
</code></pre>
<p>And here’s how you would use it:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> design_patterns;

<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BuilderPatternExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Sandwich mySandwich = Sandwich.builder(<span class="hljs-string">"Whole Wheat"</span>, <span class="hljs-string">"Chicken"</span>)
            .setCheese(<span class="hljs-string">"Cheddar"</span>)
            .setToasted(<span class="hljs-keyword">true</span>)
            .setSauces(List.of(<span class="hljs-string">"Honey Mustard"</span>))
            .setVeggies(List.of(<span class="hljs-string">"Green Pepper"</span>, <span class="hljs-string">"Red Pepper"</span>, <span class="hljs-string">"Lettuce"</span>))
            .build();
        System.out.println(mySandwich);
    }
}
</code></pre>
<hr />
<h2 id="heading-3-essentials-that-make-the-builder-pattern-work">3. Essentials That Make the Builder Pattern Work</h2>
<ul>
<li><p><strong>Private constructor:</strong> The <code>Sandwich</code> constructor is private so clients are forced to use the builder.</p>
</li>
<li><p><strong>Immutable fields:</strong> All fields in <code>Sandwich</code> are <code>final</code>, making the object immutable after construction.</p>
</li>
<li><p><strong>Required vs Optional Fields:</strong> Required fields are set in the builder constructor, while optional fields have setters.</p>
</li>
<li><p><strong>Static Builder class:</strong> Declaring <code>Builder</code> as a static nested class avoids needing a reference to the outer <code>Sandwich</code>.</p>
</li>
<li><p><strong>Fluent API:</strong> Each setter returns <code>this</code> to support method chaining.</p>
</li>
<li><p><strong>Extensibility:</strong> Easy to add more optional ingredients without changing the constructor signatures.</p>
</li>
</ul>
<hr />
<h2 id="heading-4-pro-level-improvements-for-a-great-builder-api">4. Pro-Level Improvements for a Great Builder API</h2>
<ul>
<li><p><strong>Static</strong> <code>builder()</code> method: Makes usage cleaner than <code>new Sandwich.Builder(...)</code>.</p>
</li>
<li><p><strong>Defensive copying:</strong> Lists are copied using <code>stream().toList()</code> to prevent external mutation.</p>
</li>
<li><p><strong>Default values:</strong> Optional fields like <code>veggies</code> and <code>sauces</code> default to empty lists.</p>
</li>
<li><p><strong>Readable</strong> <code>toString()</code>: Custom <code>toString()</code> improves debuggability and demo value.</p>
</li>
</ul>
<h2 id="heading-5-real-world-examples-of-the-builder-pattern-in-frameworks">5. Real-World Examples of the Builder Pattern in Frameworks</h2>
<p>The Builder pattern is not just a design exercise — it’s widely used in real frameworks and libraries to improve code readability and reduce constructor complexity.</p>
<h3 id="heading-lombok-builder">🔧 Lombok (<code>@Builder</code>)</h3>
<p>In Java, <a target="_blank" href="https://projectlombok.org/">Project Lombok</a> offers a <code>@Builder</code> annotation that auto-generates builder code for you. It’s great for data classes where you want clean, fluent APIs without boilerplate.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Builder</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;
}
</code></pre>
<p>Usage:</p>
<pre><code class="lang-java">User user = User.builder()
    .name(<span class="hljs-string">"Alice"</span>)
    .age(<span class="hljs-number">30</span>)
    .build();
</code></pre>
<hr />
<h3 id="heading-spring-framework">🌱 Spring Framework</h3>
<p>While Spring is best known for dependency injection, many Spring projects (like Spring Security, Spring Boot, and Spring Data) use builder-style APIs to configure components:</p>
<pre><code class="lang-java">HttpSecurity http = ...;

http
  .authorizeRequests()
    .antMatchers(<span class="hljs-string">"/admin/**"</span>).hasRole(<span class="hljs-string">"ADMIN"</span>)
    .anyRequest().authenticated()
  .and()
  .formLogin()
    .loginPage(<span class="hljs-string">"/login"</span>)
    .permitAll();
</code></pre>
<p>This fluent configuration style is inspired by the Builder pattern, providing clarity and flexibility when building complex object graphs.</p>
<hr />
<h3 id="heading-aws-sdk-java">☁️ AWS SDK (Java)</h3>
<p>The AWS SDK uses the Builder pattern extensively to construct requests:</p>
<pre><code class="lang-java">PutObjectRequest request = PutObjectRequest.builder()
    .bucket(<span class="hljs-string">"my-bucket"</span>)
    .key(<span class="hljs-string">"my-file.txt"</span>)
    .contentType(<span class="hljs-string">"text/plain"</span>)
    .build();
</code></pre>
<p>This avoids long constructors and makes API usage expressive and maintainable.</p>
<hr />
<h2 id="heading-6-trade-offs-of-the-builder-pattern">6. Trade-Offs of the Builder Pattern</h2>
<p>While the Builder pattern improves clarity and flexibility, it comes with a few trade-offs:</p>
<ul>
<li><p><strong>Extra boilerplate</strong>: Writing a builder adds more code compared to using constructors or setters directly.</p>
</li>
<li><p><strong>Adds minor indirection:</strong> The object creation is split between the builder and the target class</p>
</li>
<li><p><strong>Not ideal for simple objects</strong>: For classes with only a few fields, the pattern may feel unnecessary.</p>
</li>
</ul>
<p>Despite these, the Builder pattern remains a clean and scalable solution for constructing complex or immutable objects.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The Builder pattern brings <strong>fluency, clarity, and structure</strong> to object creation. It’s widely adopted in frameworks and libraries to improve the readability and flexibility of configuration.</p>
<p>This is one of those patterns that feels sweet and mellow — the trade-offs are minor compared to the flexibility you gain, especially when working with complex objects.</p>
<p>I hope that the next time you enjoy a good sandwich, you’ll think of the Builder pattern. Enjoy! 🥪!</p>
]]></content:encoded></item></channel></rss>