<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Iván Trujillo</title>
        <link>https://ivanbtrujillo.com</link>
        <description>Writing on software development, good practices, and the software industry.</description>
        <lastBuildDate>Wed, 03 Jun 2026 11:12:45 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Iván Trujillo</title>
            <url>https://ivanbtrujillo.com/favicon.ico</url>
            <link>https://ivanbtrujillo.com</link>
        </image>
        <copyright>All rights reserved 2026</copyright>
        <item>
            <title><![CDATA[What to deliver and what to keep in the age of AI]]></title>
            <link>https://ivanbtrujillo.com/articles/what-to-deliver-and-what-to-keep-in-the-age-of-ai</link>
            <guid>https://ivanbtrujillo.com/articles/what-to-deliver-and-what-to-keep-in-the-age-of-ai</guid>
            <pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[As AI makes tacit knowledge explicit, consultants face a new question: what belongs to the client, what belongs to the company, and what belongs to you?]]></description>
            <content:encoded><![CDATA[<p>Last Friday I was talking with one of my guidees about what to deliver and what not to deliver as part of our work, now that so much knowledge can be turned into a skill or part of a prompt.</p>
<p>For years, unwritten knowledge was your best protection. What you knew but couldn&#x27;t easily document was what made you hard to replace.</p>
<p>With AI it&#x27;s the exact opposite. For it to work well, you have to make explicit what was previously intuitive. You have to write down how you think, what you prioritize, how you structure problems. This has made people with solid work methodologies automatically much more productive.</p>
<p>Because you&#x27;re able to articulate your work methodology, you can make AI replicate it. This carries a risk: what&#x27;s explicit is transferable.</p>
<p>If you work for clients and deliver those configurations, you didn&#x27;t just deliver the project. You delivered your way of working, your methodology, and your judgment accumulated over years of practice.</p>
<h2>The line is clearer than it seems</h2>
<p>What goes into the project configuration:</p>
<ul>
<li>Stack conventions</li>
<li>Domain rules</li>
<li>Business-specific context</li>
</ul>
<p>Everything that exists because it&#x27;s <em>that</em> project. That belongs to the client and should stay with them.</p>
<p>What stays with you:</p>
<ul>
<li>What questions you ask before starting</li>
<li>How you evaluate whether the result is good</li>
<li>How you detect when AI is wrong</li>
<li>How you orchestrate multiple tools to work together</li>
<li>How you extract knowledge to build automations</li>
<li>How much you research and stay up to date</li>
<li>What patterns you identify in new tools to integrate them into your workflows</li>
</ul>
<p>The first list describes the project. The second list describes you.</p>
<p>A client can keep the first one. The second is built over years of practice and it belongs to you — don&#x27;t give it away.</p>
<h2>Company-level collective knowledge</h2>
<p>There&#x27;s another category: collective knowledge at the company level.</p>
<p>At company level, there are configurations, internal tools and methodologies that multiply the effectiveness of the entire team. Those belong to the company and benefit everyone who works there.</p>
<p>The key is knowing how to distinguish what&#x27;s personal, what&#x27;s collective knowledge at your company level that you can share with your colleagues for everyone&#x27;s benefit, and what&#x27;s project-specific knowledge that can be delivered to your client.</p>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
        <item>
            <title><![CDATA[The leader that AI agents need]]></title>
            <link>https://ivanbtrujillo.com/articles/the-leader-that-ai-agents-need</link>
            <guid>https://ivanbtrujillo.com/articles/the-leader-that-ai-agents-need</guid>
            <pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Agentic systems don't fail because of the model — they fail because nobody designed the coordination. Good leadership principles apply to AI agents too.]]></description>
            <content:encoded><![CDATA[<p>Most agentic systems don&#x27;t fail because of the model or because AI doesn&#x27;t work. They fail because nobody designed the coordination properly.</p>
<p>They&#x27;re like employees: a junior needs detailed instructions, a senior acts with little context. If you throw a junior into the jungle, don&#x27;t complain later when they do what you didn&#x27;t expect.</p>
<h2>Multi-agent systems are teams</h2>
<p>Multi-agent systems work like teams: they need clear roles, success criteria, mechanisms to escalate blockers, and an orchestrator that synchronizes them and keeps the focus on the overall objective.</p>
<p>They need leaders. The seat-warmers will be the next token-burners.</p>
<p>The difference between agent systems and human teams is that there are no meetings, no standups, and no waiting.</p>
<p>Can you imagine having to wait for the standup to use your next Claude Code session? Or waiting until Thursday&#x27;s meeting with the client to give them the requirements? Or waiting two weeks to define what goes into the next sprint?</p>
<p>Agents don&#x27;t wait. They receive instructions, execute, report back, and take on the next task. Like a newly hired employee at their dream company who gets paid well to work on an exciting project.</p>
<h2>Leadership principles that transfer</h2>
<p>If you&#x27;re a good leader of humans, your agents will thank you. The same principles apply:</p>
<ul>
<li><strong>Clear context</strong>: Agents need to understand <em>why</em>, not just <em>what</em>. The more context you provide, the better their decisions.</li>
<li><strong>Defined boundaries</strong>: What can they decide on their own? When should they escalate? Without this, agents either block on everything or go rogue.</li>
<li><strong>Success criteria</strong>: How do you know the output is good? If you can&#x27;t define it for a human, you can&#x27;t define it for an agent.</li>
<li><strong>Feedback loops</strong>: Agents need to know when they got it right and when they didn&#x27;t. This is how you iterate on prompts and configurations.</li>
</ul>
<p>The companies that will get the most out of agentic AI are the ones that already know how to lead well. The tool is new, but the skill is ancient.</p>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
        <item>
            <title><![CDATA[Employee experience and the cost of ignoring your best people]]></title>
            <link>https://ivanbtrujillo.com/articles/employee-experience-and-the-cost-of-ignoring-your-best-people</link>
            <guid>https://ivanbtrujillo.com/articles/employee-experience-and-the-cost-of-ignoring-your-best-people</guid>
            <pubDate>Tue, 10 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[In any organization, everyone knows who delivers results and who just makes noise. The question is what happens when the ones who deliver stop trying.]]></description>
            <content:encoded><![CDATA[<p>Let&#x27;s talk about your EX — Employee Experience.</p>
<p>It encompasses everything a person lives, feels, and perceives from the moment they join an organization until they leave: the culture, the leadership, the tools, the processes, the recognition, the communication, and the colleagues.</p>
<p>In some places it&#x27;s treated as a priority. In others it&#x27;s an afterthought. But what&#x27;s absolutely clear is that in any organization, someone who&#x27;s been there for a while knows perfectly well who produces results and who only produces noise.</p>
<p>You don&#x27;t need a performance report or an evaluation. You can see it in who shows up when there&#x27;s a hard problem, a compromised situation. Who delivers without anyone having to chase them. Who adds to the team and helps everyone improve.</p>
<h2>The noise makers</h2>
<p>Generally, the person who produces value and generates results is ignored by whoever only produces noise, because they see their position threatened — worried that others might compare and notice they&#x27;re not contributing.</p>
<p>Curiously, one way these noise-makers protect themselves is by creating processes and bureaucracy that slow everyone down equally, making it harder to distinguish who actually delivers.</p>
<h2>The exhaustion of the doers</h2>
<p>The real exhaustion doesn&#x27;t come from the workload. It comes from proposing improvements that never get implemented.</p>
<p>From flagging problems that get ignored until they explode — and then suddenly everything is urgent.</p>
<p>From having conversations that lead nowhere with people who ask a lot and listen very little.</p>
<p>That exhaustion doesn&#x27;t appear overnight. It accumulates slowly, meeting after meeting, broken promise after broken promise, feedback thrown into the void, watching their proposals get ignored while being asked to solve problems generated by others&#x27; incompetence.</p>
<p>And not in their own way, but in the way of whoever manages them. The way that they&#x27;ve already seen fail before and will fail again, but that nobody questions because questioning makes uncomfortable whoever doesn&#x27;t want to be questioned.</p>
<p>Nothing irritates high performers more than: &quot;solve this problem that was created by not listening to you, and solve it my way — the way that never works.&quot;</p>
<h2>When they stop trying</h2>
<p>There comes a point when the people who add value stop proposing, stop identifying improvement opportunities, and stop investing energy in a system that doesn&#x27;t give it back.</p>
<p>That&#x27;s the most expensive moment for any organization — and it&#x27;s almost always invisible until it&#x27;s too late.</p>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
        <item>
            <title><![CDATA[Why traditional companies fail at AI adoption]]></title>
            <link>https://ivanbtrujillo.com/articles/why-traditional-companies-fail-at-ai-adoption</link>
            <guid>https://ivanbtrujillo.com/articles/why-traditional-companies-fail-at-ai-adoption</guid>
            <pubDate>Tue, 10 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Traditional companies keep operating with obsolete work models. They evaluate employees by what they know instead of what they can produce with the tools they master.]]></description>
            <content:encoded><![CDATA[<p>Traditional companies keep operating with obsolete work models. I talk with a lot of people in the community, and I see the same patterns repeating across many organizations.</p>
<p>They evaluate their employees by what they know, not by what they&#x27;re capable of producing with the tools they master.</p>
<p>They&#x27;re reluctant to implement new technologies or new approaches because they have a dinosaur that someone created years ago and worked at the time. Or worse — they ask you to innovate but while carrying the dinosaur with you, using the dinosaur everywhere, and your goal is to make the dinosaur innovative.</p>
<p>They make you attend meetings to say what you did today, when it could be a message or email.</p>
<p>They make you sit in meetings to take notes, when summaries are auto-generated and you could use that time on something productive.</p>
<p>They expect immediate results without giving their teams space to explore, experiment, and learn the technology.</p>
<h2>The &quot;You&#x27;re totally right&quot; loop</h2>
<p>Now AI has arrived and the pattern repeats. If your team hasn&#x27;t learned how to use AI and give it correct instructions, it will help them 50% of the time. The other 50% they&#x27;ll be in an infinite loop of &quot;You&#x27;re totally right,&quot; accepting suggestions blindly hoping that this time it works, until they completely lose control of what they&#x27;re doing.</p>
<p>At that point, the one in control isn&#x27;t that person — it&#x27;s the AI. The only question is who&#x27;s paying for the license and the tokens being burned.</p>
<h2>What successful companies do differently</h2>
<p>Meanwhile, the companies that actually succeed:</p>
<ul>
<li>Give their teams explicit time to explore without immediate deliverables</li>
<li>Allow experimentation and failure</li>
<li>Provide resources to iterate until they find what works</li>
<li>Integrate everything gradually</li>
<li>Train their people to use the technology correctly</li>
</ul>
<h2>The pattern always repeats</h2>
<p>The companies that win long-term are the ones that invest in their teams&#x27; learning, not just in the technology.</p>
<p>This time will be no different.</p>
<p>Dedicate time to adopt all of this, give your people space to experiment and try without fear, and in a few months you&#x27;ll see the tree starting to bear fruit.</p>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
        <item>
            <title><![CDATA[Integrity over demos: building trust in tech]]></title>
            <link>https://ivanbtrujillo.com/articles/integrity-over-demos-building-trust-in-tech</link>
            <guid>https://ivanbtrujillo.com/articles/integrity-over-demos-building-trust-in-tech</guid>
            <pubDate>Thu, 05 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A fake demo isn't just technical debt — it's trust debt. You can show vision without deceiving, and honesty is what will speak for you in the long run.]]></description>
            <content:encoded><![CDATA[<p>Generally, people don&#x27;t like honesty upfront. We all like to hear what we want to hear, and whoever is selling knows it.</p>
<p>Curiously, when problems appear (and they always do), you usually think: &quot;I wish I had closed the deal with whoever was honest from the beginning.&quot;</p>
<p>This is what those of us who work in technology face constantly. In the end, it all comes down to integrity and trust.</p>
<h2>You can show vision without deceiving</h2>
<p>You don&#x27;t need to create a fake demo to explain where you&#x27;re going. You can use a Figma prototype with a well-explained flow to show the idea and the value.</p>
<p>Meanwhile, the development team takes care of what matters: building the foundations and a solid base.</p>
<p>A fake demo isn&#x27;t just technical debt — it&#x27;s trust debt with whoever sees it. You start a relationship with a client or investor based on something you know isn&#x27;t true.</p>
<h2>Being clear from the start</h2>
<p>Personally, I prefer being clear from the beginning: explain the vision, the roadmap, where we are today, and where we&#x27;re heading. If the other party values that transparency, you&#x27;ll build something solid together.</p>
<p>And if they don&#x27;t value it, you probably didn&#x27;t want that client anyway. Because when things get complicated (and they always do), you&#x27;ll wish you had closed with someone who valued honesty.</p>
<p>Being honest, having integrity, and being reliable will make your clients recommend you. In the long run, that&#x27;s what will speak for you.</p>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
        <item>
            <title><![CDATA[State machines and ReactJS]]></title>
            <link>https://ivanbtrujillo.com/articles/state-machines-and-react-js</link>
            <guid>https://ivanbtrujillo.com/articles/state-machines-and-react-js</guid>
            <pubDate>Sun, 13 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[How to use state machines in React JS applications with XState. It covers the steps to define a state machine using XState, create a state machine instance with the useMachine hook from the @xstate/react package, and render the state machine. The article also discusses the advantages of using state machines with XState, including their declarative, composable, testable, and scalable nature.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>State management is an essential aspect of building web applications. In complex applications, state management can become challenging, and manual state management can lead to issues like race conditions, bugs, and other inconsistencies. XState is a JavaScript library that provides a solution to these challenges by allowing developers to model state in a declarative, composable, and testable way. In this article, we will explore how to use state machines in React JS applications with XState.</p>
<h2>What is XState?</h2>
<p>XState is a JavaScript library for creating state machines. It is a finite state machine library that makes it easy to create state machines that are composable, testable, and easy to reason about. XState provides a simple, declarative syntax for defining state machines that can be used in any JavaScript environment.</p>
<h2>What are state machines?</h2>
<p>State machines are a mathematical concept used to model systems that have a finite number of states and can transition between those states based on events. In the context of web development, state machines are used to model the behavior of the user interface in response to user interactions or system events.</p>
<h2>How to use state machines in React with XState</h2>
<p>To use state machines in React with XState, we need to follow these steps:</p>
<p>Define a state machine: The first step is to define a state machine using the XState library. A state machine is defined using a set of states, events, and transitions. For example, here&#x27;s a simple state machine for a toggle button:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> createMachine <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;xstate&#x27;</span>

<span class="token keyword">const</span> toggleMachine <span class="token operator">=</span> <span class="token function">createMachine</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">id</span><span class="token operator">:</span> <span class="token string">&#x27;toggle&#x27;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">initial</span><span class="token operator">:</span> <span class="token string">&#x27;off&#x27;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">states</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">off</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">on</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token constant">TOGGLE</span><span class="token operator">:</span> <span class="token string">&#x27;on&#x27;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">on</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">on</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token constant">TOGGLE</span><span class="token operator">:</span> <span class="token string">&#x27;off&#x27;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
<p>In this state machine, we define two states: off and on. The state machine starts in the off state. When the TOGGLE event is received, the state machine transitions to the other state.</p>
<p>Create a state machine instance: Once we have defined our state machine, we need to create an instance of it using the useMachine hook from the @xstate/react package. Here&#x27;s an example:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useMachine <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;@xstate/react&#x27;</span>
<span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> toggleMachine <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;./toggleMachine&#x27;</span>

<span class="token keyword">function</span> <span class="token function"><span class="token maybe-class-name">App</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">[</span>state<span class="token punctuation">,</span> send<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useMachine</span><span class="token punctuation">(</span>toggleMachine<span class="token punctuation">)</span>

  <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span>
    <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token function">send</span><span class="token punctuation">(</span><span class="token string">&#x27;TOGGLE&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token punctuation">{</span>state<span class="token punctuation">.</span><span class="token property-access">value</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<p>In this example, we import our toggleMachine state machine and create an instance of it using the useMachine hook. The useMachine hook returns an array containing the current state and a send function that can be used to send events to the state machine.</p>
<p>Render the state machine: Finally, we need to render our state machine. We can do this by using the current state returned by the useMachine hook to render the appropriate UI. Here&#x27;s an example:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useMachine <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;@xstate/react&#x27;</span>
<span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> toggleMachine <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;./toggleMachine&#x27;</span>

<span class="token keyword">function</span> <span class="token function"><span class="token maybe-class-name">App</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">[</span>state<span class="token punctuation">,</span> send<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useMachine</span><span class="token punctuation">(</span>toggleMachine<span class="token punctuation">)</span>

  <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span>
    <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token function">send</span><span class="token punctuation">(</span><span class="token string">&#x27;TOGGLE&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>state<span class="token punctuation">.</span><span class="token property-access">value</span> <span class="token operator">===</span> <span class="token string">&#x27;off&#x27;</span> <span class="token operator">?</span> <span class="token string">&#x27;Turn on&#x27;</span> <span class="token operator">:</span> <span class="token string">&#x27;Turn off&#x27;</span><span class="token punctuation">}</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<h2>Advantages of using state machines with XState</h2>
<p>Using state machines with XState in React applications has several advantages:</p>
<ul>
<li>
<p>Declarative: XState provides a declarative syntax for defining state machines. This makes it easier to understand the behavior of the system and how it responds to events.</p>
</li>
<li>
<p>Composable: State machines can be composed to create more complex state machines. This allows developers to break down complex systems into smaller, more manageable pieces.</p>
</li>
<li>
<p>Testable: XState state machines can be tested in isolation, making it easier to write tests for complex systems.</p>
</li>
<li>
<p>Scalable: As applications grow in complexity, XState state machines provide a way to manage state in a scalable and maintainable way.</p>
</li>
</ul>
<h2>Conclusion</h2>
<p>XState is a powerful tool for managing state in React applications. By using state machines, developers can create composable, testable, and scalable state management solutions. XState provides a declarative syntax for defining state machines and the useMachine hook from the @xstate/react package makes it easy to use state machines in React applications.</p>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
        <item>
            <title><![CDATA[The path to high quality software]]></title>
            <link>https://ivanbtrujillo.com/articles/the-path-to-high-quality-software</link>
            <guid>https://ivanbtrujillo.com/articles/the-path-to-high-quality-software</guid>
            <pubDate>Mon, 22 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Maybe the value of creating software lies in providing solutions to complex problems, maybe in providing value. No matter the answer, it is better if we do it in a simple, team-based and scalable way.]]></description>
            <content:encoded><![CDATA[<p>In 1999 Martin Fowler said: &quot;Any fool can write code that a computer can understand. Good programmers write code that humans can understand.&quot;</p>
<p>Many times we find ourselves with code that is impossible to maintain, or that we do not know if changing it will modify some behavior we do not want because it is not tested, or even we ourselves create code to complete a task without caring whether it is tested, scalable and maintainable since our mission is to deliver a feature.</p>
<p>As developers, we should be professionals. When code is difficult to test, it is a sign that it is tightly coupled to the rest of the application and likely needs to be refactored. But what does it mean to refactor?</p>
<p>The definition of refactoring is to make changes to the internal structure of software to make it easier to understand and cheaper to modify without changing its behavior.</p>
<p>To achieve this last premise, we need a reliable and measurable way to know whether the behavior has changed or not. We can do this through unit tests, integration tests, and end-to-end tests.</p>
<p>At this point, we know two things:</p>
<ul>
<li>What refactoring is</li>
<li>To refactor, we need to test our code</li>
</ul>
<p>There is a &quot;boy scout&quot; principle in software development that says when you encounter code, try to leave it better than you found it. Obviously, we cannot spend the day refactoring every file we open, but we can improve the files we have to work on to implement a new feature or fix a bug.</p>
<h2>First crawl, then walk, then run</h2>
<p>When we have to add a new feature to our code but it is not structured correctly, we should first refactor it so that the feature is easy to implement, and then add the feature. This should be done in separate processes, that is, first refactor (commit) and then add the feature (commit). This way, in a code review, it is much easier to explain the reason for the refactoring and explain the functionality without mixing one thing with the other.</p>
<p>We need to be aware that we are not refactoring when we change the code without having tests to verify that its behavior has not changed. We are only changing code, but not refactoring.</p>
<p>The best advice I can give you when you have a large and tightly coupled codebase is to start separating it little by little. Just like when a forensic officer finds a crime scene, we must start looking for evidence that tells us what is happening and allows us to gradually understand what is happening. Once we have evidence (&quot;this piece of code does X&quot;), we can extract it to an independent function and test it.</p>
<h2>Use pure functions</h2>
<p>A good tip here is to create pure functions, that is, given the same input, they always return the same output. This way, we can easily test it, and we will have taken a small step in our refactoring. Remember: mutability is the devil.</p>
<h2>A good naming</h2>
<p>Another good tip is to give a good name to our functions and variables. X, Y, Z, aux ...are not a good name. The code should tell what it does without going into its implementation.</p>
<p>The truth is that it is quite common to talk about all this but in practice nobody, or very few people do it. It is normal and understandable, many times we do not have all the time in the world to make a perfect code. In this case, I can give you three tips:</p>
<p>Learn TDD. If you test your code first, you will automatically have your code tested and documented. At the beginning the development will be slow, but little by little you will pick up speed until you start delivering high quality tested code. Your customers or your company will see that Pepito&#x27;s code has very few bugs or in the case of having them, it is easy to detect where and fix them by having a good test coverage.</p>
<p>As you learn TDD, you can create your test after making a feature. It is best to follow the DRY (Don&#x27;t repeat yourself) and KISS (Keep it stupid simple) principles. This way even if you can&#x27;t test everything (for example, you don&#x27;t have time to learn how to test a custom hook in React), most functions and utilities can be tested.</p>
<p>If you don&#x27;t know how to test, as you learn how to test, add comments to your functions detailing how they should work and a TODO to replace that comment with a test or a series of tests to check (and document) their behavior.</p>
<h2>References</h2>
<p>As a final point to this blog entry, I leave here some references to books that will be useful for you:</p>
<ul>
<li>Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin)</li>
<li>Refactoring: Improving the Design of Existing Code (Martin Fowler)</li>
</ul>
<p>Finally, if you are a frontend developer and you like React, this book is great for getting started with TDD:</p>
<ul>
<li>React Test Driven Development (Daniel Irvine)</li>
</ul>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
        <item>
            <title><![CDATA[Adding a cross-page loader in NextJS]]></title>
            <link>https://ivanbtrujillo.com/articles/adding-a-cross-page-loader-in-nextjs</link>
            <guid>https://ivanbtrujillo.com/articles/adding-a-cross-page-loader-in-nextjs</guid>
            <pubDate>Sat, 25 Apr 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Sometimes you want to show a loader in NextJS that keeps the progress while switching between pages]]></description>
            <content:encoded><![CDATA[<p>To display a loading bar while loading the next page, we will use the NextJS hook useRouter which will provide us with a series of event listeners that we can subscribe to and take actions in response to a route change.</p>
<p>To display the loading bar, we will use NProgress:</p>
<pre><code>npm install nprogress

</code></pre>
<p>The next thing we will do is to create a custom hook that we will call useLoading. Inside the hook, we will subscribe to the router events. When the path changes, we will run NProgress.start() to show the loading bar and when the path has finished loading, we will run NProgress.done() to hide it.</p>
<p>useLayout.tsx</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword module">import</span> <span class="token imports"><span class="token operator">*</span> <span class="token keyword module">as</span> <span class="token maybe-class-name">React</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;react&#x27;</span>
<span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useRouter <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;next/router&#x27;</span>
<span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">NProgress</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;nprogress&#x27;</span>

<span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function">useLoading</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">useRouter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  <span class="token maybe-class-name">React</span><span class="token punctuation">.</span><span class="token method function property-access">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token function-variable function">handleStart</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token maybe-class-name">NProgress</span><span class="token punctuation">.</span><span class="token method function property-access">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> <span class="token function-variable function">handleComplete</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token maybe-class-name">NProgress</span><span class="token punctuation">.</span><span class="token method function property-access">done</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    router<span class="token punctuation">.</span><span class="token property-access">events</span><span class="token punctuation">.</span><span class="token method function property-access">on</span><span class="token punctuation">(</span><span class="token string">&#x27;routeChangeStart&#x27;</span><span class="token punctuation">,</span> handleStart<span class="token punctuation">)</span>
    router<span class="token punctuation">.</span><span class="token property-access">events</span><span class="token punctuation">.</span><span class="token method function property-access">on</span><span class="token punctuation">(</span><span class="token string">&#x27;routeChangeComplete&#x27;</span><span class="token punctuation">,</span> handleComplete<span class="token punctuation">)</span>
    router<span class="token punctuation">.</span><span class="token property-access">events</span><span class="token punctuation">.</span><span class="token method function property-access">on</span><span class="token punctuation">(</span><span class="token string">&#x27;routeChangeError&#x27;</span><span class="token punctuation">,</span> handleComplete<span class="token punctuation">)</span>

    <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
      router<span class="token punctuation">.</span><span class="token property-access">events</span><span class="token punctuation">.</span><span class="token method function property-access">off</span><span class="token punctuation">(</span><span class="token string">&#x27;routeChangeStart&#x27;</span><span class="token punctuation">,</span> handleStart<span class="token punctuation">)</span>
      router<span class="token punctuation">.</span><span class="token property-access">events</span><span class="token punctuation">.</span><span class="token method function property-access">off</span><span class="token punctuation">(</span><span class="token string">&#x27;routeChangeComplete&#x27;</span><span class="token punctuation">,</span> handleComplete<span class="token punctuation">)</span>
      router<span class="token punctuation">.</span><span class="token property-access">events</span><span class="token punctuation">.</span><span class="token method function property-access">off</span><span class="token punctuation">(</span><span class="token string">&#x27;routeChangeError&#x27;</span><span class="token punctuation">,</span> handleComplete<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<p>To display the loading bar on all pages, we need to add the NProgress styles globally. Remember to import that .css file into _app.tsx:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* NProgress */</span>

<span class="token comment">/* Make clicks pass-through */</span>
<span class="token selector"><span class="token id">#nprogress</span></span> <span class="token punctuation">{</span>
  <span class="token property">pointer-events</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector"><span class="token id">#nprogress</span> <span class="token class">.bar</span></span> <span class="token punctuation">{</span>
  <span class="token property">background</span><span class="token punctuation">:</span> <span class="token hexcode color">#29d</span><span class="token punctuation">;</span>

  <span class="token property">position</span><span class="token punctuation">:</span> fixed<span class="token punctuation">;</span>
  <span class="token property">z-index</span><span class="token punctuation">:</span> <span class="token number">1031</span><span class="token punctuation">;</span>
  <span class="token property">top</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token property">left</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">;</span>

  <span class="token property">width</span><span class="token punctuation">:</span> <span class="token number">100</span><span class="token unit">%</span><span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token unit">px</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Fancy blur effect */</span>
<span class="token selector"><span class="token id">#nprogress</span> <span class="token class">.peg</span></span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span>
  <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
  <span class="token property">right</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token unit">px</span><span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> <span class="token number">100</span><span class="token unit">px</span><span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> <span class="token number">100</span><span class="token unit">%</span><span class="token punctuation">;</span>
  <span class="token property">box-shadow</span><span class="token punctuation">:</span> <span class="token number">0</span> <span class="token number">0</span> <span class="token number">10</span><span class="token unit">px</span> <span class="token hexcode color">#29d</span><span class="token punctuation">,</span> <span class="token number">0</span> <span class="token number">0</span> <span class="token number">5</span><span class="token unit">px</span> <span class="token hexcode color">#29d</span><span class="token punctuation">;</span>
  <span class="token property">opacity</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">;</span>

  <span class="token property">-webkit-transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token unit">deg</span><span class="token punctuation">)</span> <span class="token function">translate</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token unit">px</span><span class="token punctuation">,</span> <span class="token number">-4</span><span class="token unit">px</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">-ms-transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token unit">deg</span><span class="token punctuation">)</span> <span class="token function">translate</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token unit">px</span><span class="token punctuation">,</span> <span class="token number">-4</span><span class="token unit">px</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token unit">deg</span><span class="token punctuation">)</span> <span class="token function">translate</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token unit">px</span><span class="token punctuation">,</span> <span class="token number">-4</span><span class="token unit">px</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Remove these to get rid of the spinner */</span>
<span class="token selector"><span class="token id">#nprogress</span> <span class="token class">.spinner</span></span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span>
  <span class="token property">position</span><span class="token punctuation">:</span> fixed<span class="token punctuation">;</span>
  <span class="token property">z-index</span><span class="token punctuation">:</span> <span class="token number">1031</span><span class="token punctuation">;</span>
  <span class="token property">top</span><span class="token punctuation">:</span> <span class="token number">15</span><span class="token unit">px</span><span class="token punctuation">;</span>
  <span class="token property">right</span><span class="token punctuation">:</span> <span class="token number">15</span><span class="token unit">px</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector"><span class="token id">#nprogress</span> <span class="token class">.spinner-icon</span></span> <span class="token punctuation">{</span>
  <span class="token property">width</span><span class="token punctuation">:</span> <span class="token number">18</span><span class="token unit">px</span><span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> <span class="token number">18</span><span class="token unit">px</span><span class="token punctuation">;</span>
  <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span>

  <span class="token property">border</span><span class="token punctuation">:</span> solid <span class="token number">2</span><span class="token unit">px</span> <span class="token color">transparent</span><span class="token punctuation">;</span>
  <span class="token property">border-top-color</span><span class="token punctuation">:</span> <span class="token hexcode color">#29d</span><span class="token punctuation">;</span>
  <span class="token property">border-left-color</span><span class="token punctuation">:</span> <span class="token hexcode color">#29d</span><span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token number">50</span><span class="token unit">%</span><span class="token punctuation">;</span>

  <span class="token property">-webkit-animation</span><span class="token punctuation">:</span> nprogress-spinner <span class="token number">400</span><span class="token unit">ms</span> linear infinite<span class="token punctuation">;</span>
  <span class="token property">animation</span><span class="token punctuation">:</span> nprogress-spinner <span class="token number">400</span><span class="token unit">ms</span> linear infinite<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector"><span class="token class">.nprogress-custom-parent</span></span> <span class="token punctuation">{</span>
  <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
  <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector"><span class="token class">.nprogress-custom-parent</span> <span class="token id">#nprogress</span> <span class="token class">.spinner</span><span class="token punctuation">,</span>
<span class="token class">.nprogress-custom-parent</span> <span class="token id">#nprogress</span> <span class="token class">.bar</span></span> <span class="token punctuation">{</span>
  <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token atrule"><span class="token rule">@-webkit-keyframes</span> nprogress-spinner</span> <span class="token punctuation">{</span>
  <span class="token selector">0%</span> <span class="token punctuation">{</span>
    <span class="token property">-webkit-transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token unit">deg</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">100%</span> <span class="token punctuation">{</span>
    <span class="token property">-webkit-transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span><span class="token number">360</span><span class="token unit">deg</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token atrule"><span class="token rule">@keyframes</span> nprogress-spinner</span> <span class="token punctuation">{</span>
  <span class="token selector">0%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token unit">deg</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">100%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span><span class="token number">360</span><span class="token unit">deg</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>Finally, we will import our custom hook in each page. A good idea is to create a Layout component that imports the hook and receives the content of each page as children. This way we reuse it in a more comfortable way.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">Head</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;next/head&#x27;</span>
<span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useLoading <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">&#x27;components/useLoading&#x27;</span>

<span class="token keyword">type</span> <span class="token class-name"><span class="token maybe-class-name">LayoutProps</span></span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  children<span class="token operator">:</span> <span class="token maybe-class-name">React</span><span class="token punctuation">.</span><span class="token property-access"><span class="token maybe-class-name">ReactChild</span></span> <span class="token operator">|</span> <span class="token maybe-class-name">React</span><span class="token punctuation">.</span><span class="token property-access"><span class="token maybe-class-name">ReactChild</span></span><span class="token punctuation">[</span><span class="token punctuation">]</span>
  title<span class="token operator">:</span> <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token maybe-class-name">Layout</span><span class="token operator">:</span> <span class="token maybe-class-name">React</span><span class="token punctuation">.</span><span class="token constant">SFC</span><span class="token operator">&lt;</span><span class="token maybe-class-name">LayoutProps</span><span class="token operator">&gt;</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> children<span class="token punctuation">,</span> title <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token arrow operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">useLoading</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span>
    <span class="token operator">&lt;</span><span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span><span class="token maybe-class-name">Head</span><span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>title<span class="token operator">&gt;</span><span class="token punctuation">{</span>title<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>title<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>meta
          name<span class="token operator">=</span><span class="token string">&quot;viewport&quot;</span>
          content<span class="token operator">=</span><span class="token string">&quot;width=device-width, initial-scale=1&quot;</span>
        <span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>meta<span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span><span class="token maybe-class-name">Head</span><span class="token operator">&gt;</span>
      <span class="token punctuation">{</span>children<span class="token punctuation">}</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>]]></content:encoded>
            <author>ivan@ivanbtrujillo.com (Iván Trujillo)</author>
        </item>
    </channel>
</rss>