<?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[Matias Navarro-Carter: The Chilean Nerd]]></title><description><![CDATA[Christian. Husband. Software Engineer. Chilean living in the UK.]]></description><link>https://blog.mnavarro.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 11:30:46 GMT</lastBuildDate><atom:link href="https://blog.mnavarro.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[On Scaling Software Companies]]></title><description><![CDATA[There are many definitions of scaling around there, but I like this very simple one:

Scaling a business means setting the stage to enable and support growth.

The goal is growth (who doesn't want the]]></description><link>https://blog.mnavarro.dev/on-scaling-software-companies</link><guid isPermaLink="true">https://blog.mnavarro.dev/on-scaling-software-companies</guid><category><![CDATA[scaling]]></category><category><![CDATA[scaling a business]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[engineering]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Wed, 15 Nov 2023 18:02:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/J0YYPmzTJfE/upload/187af72069cdbb4455575e9170d347c2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are many definitions of scaling around there, but I like this very simple one:</p>
<blockquote>
<p>Scaling a business means setting the stage to enable and support growth.</p>
</blockquote>
<p>The goal is growth (who doesn't want their business to grow?), however, the key idea here is that growth is something that needs enablement and support. The process of creating those supporting and enabling structures is called scaling.</p>
<p>In most traditional businesses, scaling is a linear equation: to get more output (growth) we need more input (people, raw materials, machines, refined processes, etc). In other words, growth is achieved through having more people and assets for production, and this relationship is directly proportional: more growth, means you need more people and assets.</p>
<p>This is obvious, for a business like McDonald's to grow, they need more restaurants in crowded areas, with proper machinery and the proper staff. That costs money, but makes more money than it costs: revenue is what matters.</p>
<p>The problem is that software companies are not your traditional company. They are a weird mix between a service and a product company. Software is, in some extraordinary ways, both tangible and intangible. The source code is tangible and it is produced once, but the result of it (the built software), makes it more like a service since it can be replicated and sold multiple times in a SaaS manner, for instance.</p>
<p>For these kinds of companies, scaling in linear terms is usually the reason for their ruin. If you are a CEO, a CFO, or a CTO of a Software company and think that to double your revenue you need to double your engineering team size, you are making the biggest mistake of your life, and it will cost you that company. This is because the engineering departments and the costs associated with it are probably the biggest hit to your revenue. Engineers are expensive (especially if you want good ones), and computing is expensive (especially if you have poorly designed software). You can't scale engineering linearly.</p>
<p>The best way of scaling a software company is exponentially: with an extra one or two engineers you can deliver 2, 5, or 10 times as much. This is not because you are suddenly hiring 10x developers, but because you have mastered the art of making what seemed complicated, simple; by means of continuous improvement.</p>
<h2>A story of two platforms</h2>
<p>I used to work for a company that was in the business of making integrations between different lenders and merchants. Version one of the platform was a monolithic application that had grown super complex over time due to poor coding standards, lack of testing, coupling, and other things. Now, the core idea of that platform was really good. It served as a hub where all the providers were implemented and setting up a connection between them usually involved copying a few classes and implementing a few interfaces, plus configuring some parameters like API keys and others. The tricky bit happened when something custom needed to be made for a particular integration and that wasn't supported by the abstractions that powered the model. But I would say that to overcome those difficulties it just needed a big refactor or probably a rewrite taking into account the new domain knowledge gained, but following the same underlying idea. The platform took you 90% there, you just needed that extra 10%.</p>
<p>Version two of the product was a suite of REST-powered microservices coordinated by a workflow engine. This was built by a team that was brought after some big round of investment. Now, every integration had a unique workflow, with unique steps and a unique UI. Technically, it solved the missing 10% problem of customization, but at a big price. Because everything was their own service, we spent ages writing glue code, API clients, and investing in expensive and complex acceptance test suites to make sure we had wired all the parts of an integration correctly, and that errors were handled properly and propagated accordingly. If that is hard enough to do in a monolith, imagine doing it in a distributed one. Distributing our services might have solved some issues, but it made delivery 10 times slower. To integrate something wasn't copying some classes anymore, but defining a workflow (it was complex enough!), its suite of services, deploying it, writing acceptance tests, and setting up observability, all this across 4 environments with multiple codebases.</p>
<p>Looking back, we should have gone the route that allowed us to do more with less effort. Sometimes that route covers 90% of the use case, and clever engineering is needed for the rest 10%. But I felt we gave up the 90% for a tenner.</p>
<p>The commercial results spoke for themselves. With its defects, the first platform still yielded most of the company revenue. The new platform had only one successful project that took almost two years and didn't provide any substantial increase in revenue, and that could have been done in the old platform anyway. It failed to deliver a big project due to overcomplexity caused by overcustomization. All this with an engineering department twice as big. Duplicated head count didn't yield the expected revenue growth, because someone got the vision and the strategy wrong.</p>
<h2>The most important metric</h2>
<p>This is why, as a CTO, your most important metric is delivery speed. How fast I can go from idea to production, is the most important thing.</p>
<p>Now, some CTOs know this, but they misread <em><strong>most important</strong></em> for <em><strong>only important</strong></em>. What I mean is that they focus <em>only</em> on delivery speed, but they never achieve it, because delivery speed is affected by a myriad of things that they are not worrying about.</p>
<p>Poor Developer Experience is probably the biggest factor. If you have a system that is hard to understand, hard to test, and hard to change, where to do something simple you need to go and figure out <a href="https://fly.historicwings.com/2013/03/more-lost-than-lieutenant-bello/">where Lt. Bello was lost</a>, then your delivery will be slow. Or if developers spend a lot of time writing boilerplate code that could be automated, that's another time waste. In short, the easier it is for developers to do their job, the better. Investing in tools to aid with setting up environments, automating trivial things, and generating boilerplate is the best investment of time you can make apart from building actual features.</p>
<p>If your codebase is frustrating to work with, you'll have high rates of engineer turnover, which in turn will affect your delivery speed. Reduce incidental complexity. Strive to make things as simple as they can be, and don't let yourself be fooled by shiny trendy stuff. I've seen the SPA + Microservices revolution, and all the complexity it brought, and now we are going the way back. Just make sure that what you are doing works for you and your product and that you are always solving the right problems.</p>
<p>Testing is another area. You need to make sure your test suite runs as fast and reliable as possible. Slow and flaky tests are extremely bad for your delivery speed. And when something breaks, the why should be extremely obvious, and not some weird stack trace full of noise that no one can make sense of. You don't need a massive QA team if you develop a product that is easier to test. Extend your testing frameworks with custom stuff so you can write more tests with less code. For instance, this test in one of my projects uses a custom PHPUnit extension that resets the database when the <code>SetupDatabase</code> attribute is present. It also uses custom assertions for testing APIs.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700064129850/05db0e8e-8c45-4265-b4ab-41c450c0720c.png" alt="Note how we never assert the contents of the response, but it's structure. This is a more robust test." style="display:block;margin:0 auto" />

<div>
<div>💡</div>
<div>Note how we never assert the contents of the response, but its structure via JSON schema. This is a more robust test.</div>
</div>

<p>Sometimes, complexity makes its way in and there is no way back. But then investment in onboarding and training should follow suit. Make sure you take proper time to explain how your system works to new joiners, why things work the way they do, and who knows, maybe they will have one idea or two to improve things. And give them the time to do so!</p>
<p>Code integration, review, and deployment should be as automated as possible through a CI/CD pipeline. Make sure it runs fast and makes extensive use of caching. If it needs to be super custom and vendor-dependent, so be it. Is better that it runs fast on one vendor than slow on any vendor.</p>
<p>But above everything else, be a problem seeker and solver. Always ask yourself the question: "What is in the way of my team delivering faster, with less effort?". That should be the question in every refinement too: "How can we do more with less?". That's the key.</p>
<h2>A theatrical analogy</h2>
<p>There is probably nothing more irritating to CEOs than spending time on things that do not deliver product features. The words migration or refactoring terrorize them to no end. And to some degree, I understand. After all, you are not delivering any features while your competitors are. But sometimes, to keep on moving, you have to take a few moments to catch your breath.</p>
<p>Let's go back to the definition of scaling given at the beginning.</p>
<blockquote>
<p>Scaling a business means setting the stage to enable and support growth.</p>
</blockquote>
<p>I have the privilege of going to London often for work and every time I go I try to squeeze in a visit to the theatre to watch a musical. I've watched Hamilton, Come From Away, and a few others (thank you lottery tickets!).</p>
<p>Can you imagine a musical that does not have a stage? Would it be the same? Would it cause the same impact? Would it convey the same meaning and emotions? I don't think so. Every musical needs a stage. Setting the stage is an integral part of the musical's success, although that does not happen during the musical show itself. While they are setting the stage, they are not getting paid. Is when people go to see the result of that effort that the revenue comes.</p>
<p>In the same way, investing in refining to the maximum your delivery is integral to the success of your software company and product. It will take time away from product work, but it will pay off. A good, smooth, delivery process will always give you the upper hand against any competition you might have.</p>
<p>If you can do more than your competition with less (less costs, less time, less effort) then you probably have 50% of the battle won. The other half is just good ideas (Product), customer relations (Sales), putting yourself out there (Marketing), and good talent to bring into those (HR). But if your engineering cannot do more than your competition with less, then it does not matter how much you pour into the other areas: your company will stagnate sooner or later because you won't be able to deliver.</p>
<h2>The Industrial Revolution</h2>
<p>Scaling is about solving problems that enable growth, not just growing. If you solve the problems, the growth will come. Let me illustrate this with another example.</p>
<p>When I was at University, one of my favorite topics was the Industrial Revolution and its causes. I was so interested in it that I wrote a few articles about it for the Uni's history magazine, most of them expounding the thesis of an author whose name and book I've long forgotten - I tried to google a bit to see if I could find the book, but I couldn't.</p>
<p>if memory serves me, in this book, this author noticed that all the prime materials and knowledge available for the revolution were in Great Britain's possession at least 400 years before the Industrial Revolution took place. They already produced iron and had people who knew how to work it, they had coal and they could burn it in a controlled fashion, and most certainly had some experience with pumping systems and mechanical concepts like cranks, con rods, rotors other things (although all these systems were human or animal powered).</p>
<p>The author's thesis is that the revolution didn't start earlier not for a lack of materials, or knowledge or skill, but rather because demand wasn't high enough. Once demand outpassed supply, highly technical people started to press on to the objective of how to produce at a higher rate without employing twice as many people so they could meet the demand. They were trying to figure out how to deliver more, with less. That's why, once the main idea was developed, they improved upon and applied the steam machine concept to every possible thing under the sun: mills, water pumps, transport, and textiles.</p>
<p>This makes the Industrial Revolution a technical victory. It wasn't triggered by scientific people, but by skilled people who were tradesmen by profession. Thomas Newcomen, who improved Thomas Savery's steam machine, was a metal worker, and an itinerant preacher.</p>
<p>No one can deny that the Industrial Revolution has been the greatest scaling phenomenon the world has ever seen. At the core of it was the need to develop a production system that would enable the production of more things with fewer people, which would allow us to move faster, with less effort. That concept is key to innovation, and innovation is key to scaling and productivity.</p>
<p><a class="embed-card" href="https://youtu.be/xuCn8ux2gbs?feature=shared&amp;t=890">https://youtu.be/xuCn8ux2gbs?feature=shared&amp;t=890</a></p>

<h2>Bottom line</h2>
<p>The bottom line of all of this is surprisingly simple and repetitive. It all comes back to Agile. Move forward, look back, improve, repeat. If you keep on refining and improving, eliminating what makes you slow and unproductive, then future iterations will be more efficient and you will be able to accomplish more with less. If you see something that slows you down or blocks your team, even if that thing is the very product you are selling, stop and improve it. Spend some time setting the stage for what is to come. Build your steam machine so you can place it in your factory. It will pay off. It has always paid off.</p>
]]></content:encoded></item><item><title><![CDATA[To Array is Human]]></title><description><![CDATA[I was just browsing LinkedIn this morning (because yeah, that's what I do on holidays apparently) and I got to this post, for which the author got a lot of undeserved criticism.
I tried to jump in def]]></description><link>https://blog.mnavarro.dev/to-array-is-human</link><guid isPermaLink="true">https://blog.mnavarro.dev/to-array-is-human</guid><category><![CDATA[dogmatism]]></category><category><![CDATA[PHP]]></category><category><![CDATA[array]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Wed, 27 Sep 2023 11:43:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1693230987834/e77a61ab-b907-48da-a5bd-e1dbeb0e2eb3.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was just browsing LinkedIn this morning (because yeah, that's what I do on holidays apparently) and I got to <a href="https://www.linkedin.com/feed/update/urn:li:activity:7101271911514411009?utm_source=share&amp;utm_medium=member_desktop">this post</a>, for which the author got <strong>a lot</strong> of undeserved criticism.</p>
<p>I tried to jump in defense of the author, mainly because he was trying to explain a pattern that is valid in a variety of circumstances, and people were trying to criticize it by pointing at all the circumstances where the pattern is not valid. Following the metaphor of tooling in software, this is analogous to say "Don't use a hammer, because you can't turn screws with it".</p>
<p>One user in particular went on to write <a href="https://davegebler.com/post/php/the-array-anti-pattern">a blog post</a> about this "anti-pattern". So well, because I also like to write and I'm in the mood to rant a little (I had too much relaxation time these holidays already) I decided to compose a response to that blog post. If you want full context, you might want to read both the LinkedIn post and the blog in response.</p>
<h2>Identifying the Real Issue</h2>
<p>The blog post is extensive, but the main ideas are that, quote "<strong>using array as a type hint is (usually) an anti-pattern</strong>". Says the main problem with using arrays as type hints, quote "is that arrays are a very broad type in PHP. They represent multiple, disparate data structures", and because of this, when you type hint array to a return function, quote "you never know what you are going to get".</p>
<p>Before anything else, a Senior Developer must clarify concepts and point at exactly the root of disagreement. Otherwise, we are doing a disservice to our profession and the people who heed our advice. So in light of that, I must ask. Is anything of what he said about arrays wrong? Not at all. All those things I quoted there from him are facts of life. They are not wrong.</p>
<p>The problem though, is that the issue discussed was not about type-hinting as arrays <em>in general</em> but type-hinting arrays <em>in a very specific context and set of circumstances</em>.</p>
<p>I can almost see the reasoning behind the critic's mind: "Arrays are bad, we shouldn't use them. This uses arrays, therefore is wrong". But an experienced person would say "Okay, I know arrays are bad for <em>these reasons</em>. Given those reasons, is this particular use of array as type-hint bad? Why? What are the pros and cons?" But there was none of that. We'll talk about why that happens in the second section.</p>
<p>The author explains, correctly I must say, that arrays are bad because they are a bag of states that can hold pretty much anything. Now, that something can hold anything is not an issue <em>per se</em>, but rather could become an issue (and most certainly will) when you <em>pass-around</em> that array to multiple functions and calls. This is the real problem with arrays. That's when is hard to keep track of the keys that may or may not be in your array, and the mutations that could happen along the call stack. This is the reason why this becomes a debugging nightmare when something fails. DTOs are much more appropriate structures to be <em>passed-around</em> application layers.</p>
<p>However, utility functions like the one demonstrated in the LinkedIn post don't fall into this category. Let's look at one of the examples I like the most. This beautiful, simple, and elegant function to cut a string in two parts.</p>
<pre><code class="language-php">&lt;?php

/**
 * Cuts a string in two by the first occurrence of substring.
 *
 * The substring is not included in the result
 *
 * @return array{0: string, 1: string, 2: bool}
 *
 * @psalm-pure
 */
function str_cut(string \(string, string \)substring): array
{
    \(len = \strlen(\)substring);
    \(i = \strpos(\)string, $substring);

    if (!\is_int($i)) {
        return [$string, '', false];
    }

    return [
        \substr(\(string, 0, \)i),
        \substr(\(string, \)i + $len),
        true,
    ];
}

$a = 'foo=bar';
$b = 'foo';

[\(left, \)right, \(ok] = str_cut(\)a, '=');
// [0: 'foo', 1: 'bar', 2: true]

[\(left, \)right, \(ok] = str_cut(\)b, '=');
// [0: 'foo', 1: '', 2: false]
</code></pre>
<p>The function's return argument is type-hinted as an array. But, does this use of array as a type-hint present the problems previously mentioned with arrays?</p>
<p>No, for two simple reasons:</p>
<ol>
<li><p>The function is pure. This means it has no side effects and given the same input, it will return the same output. In other words, the array is created inside the function, consistently. There is no possibility that this array can be in a state that we don't mean it to be.</p>
</li>
<li><p>The array is destructured immediately (it's the purpose of this API), so it cannot be <em>passed-around</em>. So the array type hint (which is not a problem in this case because it is stable) does not propagate to the rest of the codebase. It is meant to be used destructured. If you have ever used React (<code>const [state, setState] = useState()</code>) then you understand this concept very well.</p>
</li>
</ol>
<p>Some of the pros of this approach:</p>
<ol>
<li><p>You can name your variables however you like. This immediately tells other developers in the code what this value contains. So there is no ambiguity about the contents of the value.</p>
</li>
<li><p>You can benefit from type checkers like Psalm or PHPStan. Even PHP Storm will help you with this syntax. So it's pretty hard to get wrong.</p>
</li>
</ol>
<p>Some of the cons:</p>
<ol>
<li>If you don't have a modern IDE, you might need to look at the function documentation to be able to use it and see what you will get in return, otherwise, there is a chance you'll get it wrong. But if this is your case, I think you have bigger problems anyway.</li>
</ol>
<p>Now, I'm not saying this is The Only Right Way™ a function like this could be implemented. You could use an associative array with named keys or even a DTO. If you want to do that, go ahead. If I were reviewing a PR with code like that, I would certainly not fail it. But I'd probably recommend against both of those approaches because they result in more verbose client code and have slightly worse (so small that it doesn't matter much) performance.</p>
<h2>The Real Issue: Dogmatism</h2>
<p>The real issue here is <strong>dogmatism</strong>. I define dogmatism as the failure to consider the context when applying a rule, a principle, or our own experience. In this case, there is a well-known rule in the PHP world, that comes from experience, that arrays are tricky data structures to work with, and if you litter your methods and functions with them and use them all around, you are most certainly going to have issues. I find it hard to find people nowadays who wouldn't prefer a good old typed DTO instead of an array as a data transfer mechanism between application layers.</p>
<p>The issue is when we take this knowledge, and make it an absolute rule with no context: "You shouldn't use arrays in your return methods". I believe this is the "tweet" mentality in action. In every programming debate, context is key. 99% of the answers to all engineering questions are "It depends". Most of our programming wars would be much more educational for the people watching them if we just consider the context instead of assuming the other is just plain wrong.</p>
<p>In this case, the context was completely ignored. People jumped in masses to attack someone for doing something perfectly fine, with little to zero drawbacks whatsoever. You wouldn't do it the way it was shown on the LinkedIn post? Good for you, but preference doesn't invalidate other approaches. If you want to say something is wrong or an "anti-pattern", you must provide evidence that applies to the particular use case: something that was completely missing from this discussion.</p>
<p>When you hear someone saying, "You should/shouldn't do this" the most important two questions you should ask are, first: "Why?" and once you have understood the reasons behind it, the second question is even more important: "Do the reasons apply in this particular case?".</p>
<p>I mean, that's pretty much all the wisdom you need to navigate the turbid waters of engineering discussions.</p>
]]></content:encoded></item><item><title><![CDATA[A CRUD Reality]]></title><description><![CDATA[The Nasty U in CRUD
Before anything else, let's just do a quick recap on what CRUD is. CRUD stands for "Create-Read-Update-Delete" which are, in turn, the four basic operations of data storage. It's u]]></description><link>https://blog.mnavarro.dev/a-crud-reality</link><guid isPermaLink="true">https://blog.mnavarro.dev/a-crud-reality</guid><category><![CDATA[PHP]]></category><category><![CDATA[cdc]]></category><category><![CDATA[event-driven-architecture]]></category><category><![CDATA[DDD]]></category><category><![CDATA[crud]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Thu, 03 Aug 2023 11:07:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ssEQdOiKd8U/upload/fdf0c0bb16d8a74ffdd971afb1160b53.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>The Nasty U in CRUD</h1>
<p>Before anything else, let's just do a quick recap on what CRUD is. CRUD stands for "Create-Read-Update-Delete" which are, in turn, the four basic operations of data storage. It's usually used as an adjective to describe a system. For instance, I often apply this acronym to describe JSON APIs which are built with frameworks that enable all four operations with little to zero boilerplate code. These usually take your input as JSON, validate it, transform it, and apply it to the database with little effort. All you have to do is to define your models, extend a particular controller, write a bit of validation and you are good to go.</p>
<p>The fundamental issue with this approach is that is just merely providing a JSON over HTTP interface on top of a system of record. Granted, it has some authorization and validation logic added on top, but you are still just serializing JSON into the database and back.</p>
<p>This is usually enough for quick prototyping or in the early stages of a system. But for a mature application, with a complex and always-evolvable domain, this approach falls short pretty quickly, and all the speed you seemed to gain by using tools that do most of the heavy lifting for you, vanishes after you try to work around the architectural limitations of such tools.</p>
<p>In my own opinion, a domain starts to be complex when just having an interface to store and retrieve data from the database is not enough to fulfill customers' needs. Sometimes other things apart from updating the resource in question need to happen to fulfill a requirement. In other words, the moment we start shipping features whose wording is along the lines of "when x happens in the system, x, y, and z should happen too". The more you have of these kinds of requirements, the more complex.</p>
<p>This is the bottom line of the issue with CRUD. Creating, reading, and deleting resources are quite straightforward operations (actually, deleting is not so much but that could be another blog post!). However, updating a resource is much more than just replacing some fields in a table. "Account updated" is not too descriptive. We need to know what exactly has changed in the account, so just saying "something was updated" is not enough. We need to be able to say "a user was deactivated", "a ticket has been archived", "an order has been shipped" or "a refund has been processed". We need to start thinking in terms of what is called "business actions" and their effects. An update is not a business action, is just something that says "Hey! Some info about this entity was changed. I don't know exactly what so go figure yourself!" We need to build this log of business actions and their effects along with the operation. We need what is often referred to as <strong>Domain Events</strong>.</p>
<h1>Substandard Solutions</h1>
<p>When an application reaches this point and has not been architected from the beginning to support Domain Events as a first-class citizen of the domain model, two solutions are usually implemented that in my opinion are substandard, because they don't attack the root of the problem.</p>
<h2>Change Data Capture</h2>
<p>The first common solution is implemented at the database level and is called <a href="https://en.wikipedia.org/wiki/Change_data_capture">Change Data Capture (CDC)</a>. The strategy consists in using the replication protocols of the data store in question to receive state changes in real time to some other process (think Meroxa or Debezium here). That process then serializes the binary information received into a more universal format (JSON) and puts it in an event stream powered by Kafka or similar technologies. The result looks a bit like this (this is taken from Meroxa PGSQL connector)</p>
<pre><code class="language-json">{
    "schema": {
        "type": "struct",
        "fields": [
            {
         "type": "struct",
         "fields": [
             {
                 "type": "int32",
                 "optional": false,
                 "field": "id"
             },
            ...
         ],
         "optional": true,
         "field": "before"
     }
        ],
        "optional": false,
        "name": "resource_217"
    },
    "payload": {
        "before": {
            "id": 11,
            "email": "ec@example.com",
            "name": "Nell Abbott",
            "birthday": "12/21/1959",
            "createdAt": 1618255874536,
            "updatedAt": 1618255874537
        },
        "after": {
            "id": 11,
            "email": "nell-abbott@example.com",
            "name": "Nell Abbott",
            "birthday": "12/21/1959",
            "createdAt": 1618255874536,
            "updatedAt": 1618255874537
        },
        "source": {
            "version": "1.2.5.Final",
            "connector": "postgresql",
            "name": "resource-217",
            "ts_ms": 1618255875129,
            "snapshot": "false",
            "db": "my_database",
            "schema": "public",
            "table": "User",
            "txId": 8355,
            "lsn": 478419097256
        },
        "op": "u",
        "ts_ms": 1618255875392
    }
}
</code></pre>
<p>The only good thing about the approach is that it doesn't need any modifications to the application source code, but that's as far as the benefits go. You still need to process the diff between the changes in your resources to figure out what was the actual domain event that occurred and extract some meaning out of it. For instance, in the example above, we can say that the email of this user was updated. Yes, you can glance at that and figure it out, but building an algorithm to do that and other changes for every entity in your system it's no easy feat.</p>
<p>I'm getting ahead of myself here but just imagine for a second what would be the ideal JSON you would like to work with here. I don't know about you, but I would love something along these lines (this is the actual structure from the events of one of my projects):</p>
<pre><code class="language-json">{
    "event_id": 232,
    "event_name": "user_email_changed",
    "payload": {
        "user_id": 11
        "email": "nell-abbott@example.com"
    },
    "ocurred_at": 1618255874537,
    "metadata": {
        "performer": {
            "type": "user",
            "id": 11
        }
    }
}
</code></pre>
<h2>Auxiliary History / Log Tables</h2>
<p>This is another approach that is a bit suboptimal. Sometimes, in domains where historical information and audibility are essential, the need arises for some history log features. For instance, in a project management system, we want to be able to see a history tab with all the actions that have occurred on a certain ticket, when they happened, and who performed them.</p>
<p>What ends up happening is that some evaluator is built on top of the update operation. It analyses what fields have changed and creates a record of the change in a history table. This overcomplicated code is usually inserted in some random places after some operation has been performed. Because of this, the operation is oftentimes not inside the transactional boundary (if any!), meaning that there might be a possibility that the update is performed but the log is not. Lastly, the saddest thing is that this is a missed opportunity: is something built ad-hoc just for that entity rather than a feature of the system architecture as a whole.</p>
<h1>Enter the Transactional Outbox Pattern</h1>
<p>First of all, I don't like the name of Transactional Outbox Pattern. I very much prefer to call it a Transactional Event Log. Yes, the purpose of it is messaging, but also auditing.</p>
<p>The first requirement of the pattern is that your application stops thinking about state updates as just mere updates, and starts moving to the notion of commands. A command is an action (in imperative) that is being performed in a system. As a result of that action, the state of the system will change. Examples of commands include:</p>
<ul>
<li><p>Deactivate Customer</p>
</li>
<li><p>Archive Ticket</p>
</li>
<li><p>Publish Reply</p>
</li>
<li><p>Process Shipment</p>
</li>
<li><p>Issue Refund</p>
</li>
</ul>
<p>So whatever interface you have in the front of your application (JSON API, CLI, etc). You need to make sure you are not receiving CRUD resource representations from your clients, but rather commands. If you take a look at specifications like <a href="https://smithy.io/2.0/index.html">Smithy from AWS</a>, you know what I'm talking about.</p>
<p>Once you have the command, then your corresponding service will handle it. The service will perform the necessary state updates into the relevant table, but it will also add a record in the events table about the action that has been performed. This ensures both the record and the event are persisted atomically. This is an important detail of the pattern and hence the name "Transactional": consistency is key.</p>
<div>
<div>💡</div>
<div>Something I like to do along with persisting the state update and the events is persisting all the listeners that should run for that event (each listener in a row of its own), so another process can run them asynchronously. This effectively is like job processing done in a very particular way, but it's super powerful.</div>
</div>

<p>You end up with a table that contains the log of events that have occurred in your system, and then the interested parties can consume those events via a REST endpoint, directly from the database or from a message queue. The consuming mechanism is pretty much your choice.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690576936728/e2841f32-b0fa-43a4-b40e-9ddf0f8ea8cb.png" alt="" style="display:block;margin:0 auto" />

<p>One important aspect of the events is that they carry the state relevant to the event that has occurred. As I showed in the example ideal JSON for an event a few paragraphs above, the email has changed: we include the name of the email and the user id for the email that changed. This is what Martin Fowler calls <a href="https://www.youtube.com/watch?v=STKCRSUsyP0&amp;t=893s">Event-Carried State Transfer</a>: the relevant state is included in the event.</p>
<p>The benefit of this pattern is that now you have a log of all (and not just some) the events that have happened in your system. The log is persistent and immutable: you can read it anytime you want and share it with other systems using whatever mechanism you prefer, and other systems just need to keep track of the last event they have processed. The log is consistent: you'll never have an event that does not have its corresponding state update. And lastly, the log is really useful as a means of auditing tool or to build history-like auditing features.</p>
<h2>A PHP Implementation</h2>
<p>I usually implement this in PHP using Doctrine ORM and Symfony Serializer. First, let's define an interface that your application services will use:</p>
<pre><code class="language-php">&lt;?php

interface EventNotifier
{
    public function notify(Context \(ctx, object \)event): void;
}
</code></pre>
<p>Notice how the events can only be objects. Also, using a context is very useful to not pollute the method with contextual information that may or may not be there.</p>
<p>Then, let's suppose our application service uses it this way:</p>
<pre><code class="language-php">&lt;?php

/**
 * This is the event class
 */ 
class EmailChangedEvent
{
    public function __construct(
        public readonly int $userId,
        public readonly string $email    
    ) { }
}

/**
 * This is the command class. This class holds the data that we need
 * to fullfil this business action.
 */ 
class ChangeEmailCommand
{
    public function __construct(
        public readonly int $userId,
        public readonly string $email    
    ) { }
}

/**
 * This is the command handler class. 
 * This class deals with the business action and notifies the events.
 */ 
class ChangeEmailHandler
{
    public function __construct(
        private readonly UserRepository $users,
        private readonly EventNotifier $events,    
    ) { }

    public function __invoke(Context \(ctx, ChangeEmailCommand \)cmd): void
    {
        // Some data transformation and validation
        \(canonicalizedEmail = Canonical::email(\)cmd-&gt;email);
        Assert::email($canonicalizedEmail);
        
        \(user = \)this-&gt;users-&gt;ofId(\(ctx, \)cmd-&gt;userId);
        
        // The model produces the event based on the state change
        \(evt = \)user-&gt;changeEmail($canonicalizedEmail);
        
        // Here the event is notified
        \(this-&gt;events-&gt;notify(\)ctx, $evt);
        
        // The new state of user is saved
        \(this-&gt;users-&gt;add(\)ctx, $user);
    }
}
</code></pre>
<p>Both <code>UserRepository</code> and <code>EventNotifier</code> are abstractions behind an interface. Their implementation uses Doctrine under the hood, and a command bus middleware wraps this operation inside a transaction, so both the state change and the event get persisted atomically. <code>UserRepository</code> <code>ofId</code> and <code>add</code> methods are wrappers of <code>findOneById</code> and <code>persist</code> respectively. But let's look at the more interesting implementation of the <code>EventNotifier</code> with its corresponding Entity.</p>
<pre><code class="language-php">&lt;?php

#[ORM\Entity]
class Event
{
    #[ORM\Id, ORM\Column(type: "integer")] 
    public int $id = 0

    public function __construct(
        #[ORM\Column(type: "string")]
        public string $name,
        #[ORM\Column(type: "json")]
        public array $payload,
        #[ORM\Column(type: "json")]
        public array $meta,
        #[ORM\Column(type: "datetime_immutable")]
        public DateTimeImmutable $ocurredAt = new DateTimeImmutable(),
    ) { }
}

class PersistentEventNotifier implements EventNotifier
{
    public function __construct(
        private readonly EntityManager $manager,
        private readonly NormalizerInterface $normalizer,
        private readonly EventNamer $eventNamer,
    ) { }
    
    public function notify(Context \(ctx, object \)event): void
    {
        $ormEvent = new Event(
            \(this-&gt;eventNamer-&gt;getName(\)event),
            \(this-&gt;normalizer-&gt;normalize(\)event),
            [
                // We store the class as metadata for denormalizing the event
                'php.class' =&gt; get_class($event),
                // We store other metadata we are interested in
                'performer' =&gt; $ctx-&gt;value('performer');
            ]
        );
        
        // Event is persisted
        \(this-&gt;manager-&gt;persist(\)ormEvent);
    }
}
</code></pre>
<p>The end result of this is a database table along these lines:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1691051972718/88a87796-fa7d-49cb-b746-d30e0975d82b.png" alt="" style="display:block;margin:0 auto" />

<p>It's trivial to expose this table under a REST endpoint. In fact, I do this in one of my personal projects. Other systems that are interested in my system events can call the endpoint at their convenience to get everything that has occurred in the system. They just need to remember the last event id they have processed, and then keep on consuming from there using <code>?from=&lt;id&gt;</code> .</p>
<p>There is also a <code>published_at</code> column for publishing the event in a message queue or a streaming platform, which is something you can do too if you wish to push these events in real-time to consumers. You can fire these events on an SSE endpoint too. I mean, there are many, many possibilities.</p>
<h2>A Warning on Eventual Consistency</h2>
<p>Of course, any operations you perform after the event persisted are bound to be eventually consistent. This means, because they will be asynchronous in nature they will happen, eventually, but not atomically. So if some client or consumer is waiting for that state change somewhere else, that email or that notification, the worst-case scenario may take a while to be processed. But the good this is that it will because you have an immutable log of events.</p>
<p>However, this is when having an event-driven system pays off because clients who are waiting for something to happen can listen to these events and react to them when they do. UI notifications using SSE are a really good pattern to mitigate the effects of eventual consistency.</p>
<h2>A Warning on Table Size</h2>
<p>Another drawback is the potential table size and its impact on application performance. Let me offer three pieces of advice to deal with these issues.</p>
<p>First, your primary key type must be an 8-byte integer, this is <code>bigint</code> in MySQL and <code>bigserial</code> in Postgres. If unsigned, you have exactly <code>18,446,744,073,709,551,615</code> max capacity for records. You are never going to use that. Even if your primary key is just 4 bytes, you have <code>4,294,967,295</code> records until your max which is quite a lot. You'll probably run out of machine storage before hitting that max.</p>
<p>Secondly, we all know that as a table grows, full scans are very costly. The key here is that you should never do a full scan of this table, nor correct old records with update operations. Any derived state you need from this table should be computed by doing a sequential id scan and tracking the last id processed. This is a table that is meant to be processed, not queried. If you need to query, using a process that scans the table you can denormalize its information to provide a queryable representation somewhere else (this is a process known as projection in the Event Sourcing jargon). Also, it helps if you want to index the event name and the <code>occurred_at</code> fields, to provide you with some leeway for querying.</p>
<p>Third, if for some reason you do need to query and update your records (although I advise against this), you can always resort to archiving old records, especially if you have a system that is historical in nature, with "closing" cycles like accounting or legal. In those systems, some information is never touched after a while but still needs to be kept. So you can grab a bunch of it and archive it in a secondary form of persistent storage.</p>
<h1>Conclusion</h1>
<p>When an application is born it usually persists state changes directly to the database and the previous state is completely discarded. However, as the application grows in complexity is convenient to have a mechanism to react to those state changes in other parts of the system or in other systems. This will avoid too much coupling in the application, since in an event-driven architecture, systems need not know who sent a particular event: they just need the event.</p>
<p>Implementing the Transactional Outbox Pattern solves this problem very elegantly. It integrates well with the application code and doesn't suffer from the consistency problems of sending events or jobs directly to a queue. Plus, this event log you get can be used for a multitude of purposes like auditing, event streaming, and UI notifications.</p>
]]></content:encoded></item><item><title><![CDATA[The Repository Pattern Done Right]]></title><description><![CDATA[💡
This is an old article that I wrote a few years ago in one of my many blogs and got lost somewhere until someone mentioned it on Github. Since it has been useful to others, I decided to republish i]]></description><link>https://blog.mnavarro.dev/the-repository-pattern-done-right</link><guid isPermaLink="true">https://blog.mnavarro.dev/the-repository-pattern-done-right</guid><category><![CDATA[PHP]]></category><category><![CDATA[repository]]></category><category><![CDATA[DDD]]></category><category><![CDATA[activerecord]]></category><category><![CDATA[orm]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Fri, 07 Jul 2023 13:27:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/X_j3b4rqnlk/upload/84ba18cb123cf261e189c191585bf66f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div>
<div>💡</div>
<div>This is an old article that I wrote a few years ago in one of my many blogs and got lost somewhere until <a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/mtarld/apip-ddd/issues/44" style="pointer-events:none">someone mentioned it on Github</a>. Since it has been useful to others, I decided to republish it here and give it a small update. Enjoy!</div>
</div>

<p>The repository pattern is one of the most well-established patterns in Domain Driven Design. Its origins can be traced as early as when Object Oriented Programming was born.</p>
<p>Of course, as it happens with almost every pattern or tool, you can use it terribly the first time (or even the second, or the third one). The only way to improve upon that is good literature and seeing other, more appropriate, uses of the pattern/tool. Refining your use of tools and patterns this way is, with almost all certainty, the only way to grow as a developer. Years of experience don’t count much if you have been doing the same thing, the same way, over and over again.</p>
<p>This is why I implement and use repositories very differently now than the first time I started. This is probably because of the experience (both good and bad) that I’ve accumulated over the years. I’ve also read quite a lot on the topic and certainly, I’m not the only one that has experienced issues implementing repositories in my applications.</p>
<p>So, over the years, I’ve come to a definition of repositories, and is this one:</p>
<blockquote>
<p>Repositories are a specific and immutable abstraction over a collection of domain objects.</p>
<p>~ Yours Truly</p>
</blockquote>
<p>Let me tell you what I mean by that.</p>
<h2>Warning: Active Record Users</h2>
<p>Repositories tend to work with ORMs – even though is not a requirement, it’s very common practice. However, not any kind of ORM can be used for working with repositories. I think a word of warning is necessary for users of Active Record ORMs (I’m talking about you, Yii and Laravel users). I’ve read several blog posts (like <a href="https://dev.to/asperbrothers/laravel-repository-pattern-how-to-use-why-it-matters-1g9d">this one</a>, or <a href="https://itnext.io/repository-design-pattern-done-right-in-laravel-d177b5fa75d4">this other one</a>) that promise an implementation of repositories the Laravel Way™, which is not the repository pattern, but a poorly abstracted interface over Eloquent. Don’t get me wrong: Active Record ORMs are great at what they do (which is, in my opinion, to provide an nice API over records on a database) but unfortunately, they just don’t fit the requirements for the repository pattern. Don’t try to use Active Record ORMs for repositories, they just don’t fit the use case. If you are using Active Record, embrace the fact that you already coupled your data model to your persistence layer. If you won’t take my word for it, <a href="https://laravelpodcast.com/episodes/9dafa72e?t=34m3s">take Jeffrey Way’s</a>.</p>
<h2>Repositories are Abstractions</h2>
<p>Just to continue with the thread, the main reason why Active Record ORMs don’t fit the repository pattern is because <strong>repositories are abstractions</strong>, and Active Record Data Models are not. When you create a data model in Laravel, for example, you are not fetching a <em>pure</em> data class, but a whole lot of other stuff related to persistence, like your database connections, mutators and all sorts of stuff. All that lives in your data model, and that renders it unusable for the level of abstraction required for the repository pattern.</p>
<p>To be fair with the Eloquent guys, this is true of Doctrine repositories also. If you are using doctrine repositories <em>as they are</em>, you are not abstracting anything away. You are coupled to Doctrine, which is in turn coupled to a relational database engine. That leaves you in the same place as using Eloquent (a bit better though, because your data model is a <em>pure</em> data class).</p>
<p>In the Symfony world, it’s common to see something like this:</p>
<pre><code class="language-php">&lt;?php

class SomeController
{
    public function someMethod(Request $request): Response
    {
        // This repository is the doctrine's library one
        \(repo = \)this-&gt;getRepository(User::class);
        \(users = \)repo-&gt;findAll();
        return \(this-&gt;json(\)users);
    }
}
</code></pre>
<p>If you do this, stop. You are not using a <strong>proper</strong> abstraction here. It’s true: the Doctrine repository is an abstraction over the <code>EntityManager</code>, <code>QueryBuilder</code>, <code>Connection</code> and a bunch of other stuff, but is a doctrine-specific abstraction. You need a <strong>domain-specific abstraction</strong>. One abstraction that is only yours, your <em>own</em> contract.</p>
<p>So what we should do then? We just define an interface:</p>
<pre><code class="language-php">&lt;?php

class User
{
    // This is your data class
}

interface UserRepository
{
    /**
     * @return iterable|User[]
     */
    public function all(): iterable;

    public function add(User $user): void;

    public function remove(User $user): void;

    public function ofId(string $userId): ?User; 
}
</code></pre>
<p>This is a proper abstraction. Your <code>User</code> class is a class that just contains data. Your <code>UserRepository</code> interface is your contract. You can use the Doctrine repository behind it, but it won’t matter this time, because you will type hint the interface to all other classes using it. This way you effectively decouple yourself of any persistence library/engine and get an abstraction you can use all around your codebase.</p>
<h2>Repositories are Specific</h2>
<p>Note how the <code>UserRepository</code> we defined is <strong>model specific</strong>. A lot of people like to save work by creating a generic repository that becomes no more than a query abstraction over the persistence library used. Just don’t do this:</p>
<pre><code class="language-php">&lt;?php

interface Repository
{
    /**
     * @return iterable|object[]
     */
    public function all(string $repositoryClass): iterable;
}
</code></pre>
<p>Remember one of the principles of DDD: clear language intent. One repository interface for each model conveys more meaning to that specific repository/model than a generic one. For example, only users can be filtered by email, not buildings.</p>
<p>Besides with one generic repository for everything, you won’t be able to type your concrete model classes to the return or argument types. It’s the longer route but is the most convenient and flexible.</p>
<div>
<div>ℹ</div>
<div>UPDATE: I still maintain this is not a great idea, but the typing argument is probably not as valid as it used to be since the PHP tooling ecosystem has embraced generics annotations so well that this solution is workable from a type-system point of view. Just a friendly reminder that because you can do something, it does not mean that you should.</div>
</div>

<h2>Repositories are Collections</h2>
<p>I would say that the “Aha!” moment in repositories for me is when I realized that they are just an abstraction over a collection of objects. This blew my mind and gave me a new challenge; the challenge of implementing repositories as if they were an in-memory collection.</p>
<p>For starters, I dumped all methods like <code>all()</code>, <code>allActiveUsers()</code> or <code>allActiveUsersOfThisMonth()</code>. If you have read the two famous posts about taming repositories, first the one of <a href="https://web.archive.org/web/20161007174722/http://dev.imagineeasy.com/post/44139111915/taiming-repository-classes-in-doctrine-with-the">Anne at Easybib</a> and then the one of <a href="https://web.archive.org/web/20220125115134/https://beberlei.de/2013/03/04/doctrine_repositories.html">Benjamin Eberlei in response</a>, you should know that methods like that in a repository can grow wild. Also, the specification pattern is great, but it is quite complex to implement well for this particular use case: we can do better and simpler than that.</p>
<p>Collections APIs have many distinctive features. You can <strong>slice</strong> collections, <strong>filter</strong> them, <strong>add</strong> or <strong>remove</strong> elements from them, as well as <strong>finding</strong> specific elements. But we don’t want a general collection API, remember? We want to implement a specific API for every model, so it conveys meaning.</p>
<p>So, our <code>UserRepository</code> interface could look this way:</p>
<pre><code class="language-php">&lt;?php

interface UserRepository extends Countable, IteratorAggregate
{
    public function add(User $user): void;

    public function remove(User $user): void;

    public function ofId(string $userId): ?User;

    public function ofEmail(string $email): ?User;

    public function withActiveStatus(): self;

    public function registeredAfter(DateTimeInterface $date): self;

    public function registeredBefore(DateTimeInterface $date): self;

    public function getIterator(): Iterator;

    public function slice(int \(start, int \)size = 20): self;

    public function count(): int;
}
</code></pre>
<p>Pay special attention to the last three methods. These are the only methods that could potentially be in a <code>Repository</code> base interface, because all of them will be sliceable, countable and iterable.</p>
<pre><code class="language-php">&lt;?php

interface Repository extends IteratorAggregate, Countable
{
    public function getIterator(): Iterator;

    public function slice(int \(start, int \)size = 20): self;

    public function count(): int;
}
</code></pre>
<p>So by doing this, all of your repositories will be sliceable (think pagination there), iterable and countable. The idea is that you apply the filtering methods (all the methods that return <code>self</code>) and then iterate to execute the internal query, just like an in-memory collection. You wouldn’t note the difference at all if an implementation is switched to another one.</p>
<p>This is good OOP. All the persistence details are completely hidden from us, the API is composable and fits our needs for a repository. It looks neat and using it is simple and easy to understand:</p>
<pre><code class="language-php">&lt;?php

class SomeService
{
    public function __construct(UserRepository $users)
    {
        \(this-&gt;users = \)users;
    }

    public function someMethod()
    {
        \(users = \)this-&gt;users
            -&gt;withActiveStatus()
            -&gt;registeredBefore(new DateTime('now'))
            -&gt;registeredAfter(new DateTime('-30days'));

        \(count = \)users-&gt;count();

        return $users;
    }
}
</code></pre>
<p>But here’s the question: how do we go about implementing an API like this? If you are a good observer, you might have realized that the filters return an instance of themselves, modifying the internal state of the repository. So in the next query, we will have the filters of the previous query applied, right?</p>
<h2>Repositories are Immutable</h2>
<p>Well, that could be right, if we <em>really</em> are modifying the internal state. But in reality, we are cloning the repository reference, preserving the original one not to affect subsequent queries accidentally. This is an implementation detail, but a very important one. If we change, let’s say, the state of the repository reference that lives inside our DI Container, then we are done: we cannot use that reference again. So the idea is to make it <strong>immutable</strong>.</p>
<p>Let me show you the final API, implemented in Doctrine ORM. I’m going to write some comments and doc blocks in the code explaining some things.</p>
<pre><code class="language-php">&lt;?php
declare(strict_types=1);

namespace RepositoryExample\Common;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Iterator;

/**
 * Class DoctrineORMRepository
 * 
 * This is a custom abstract Doctrine ORM repository. It is meant to be extended by
 * every Doctrine ORM repository existing in your project.
 * 
 * The main features and differences with the EntityRepository provided by Doctrine is
 * that this one implements our repository contract in an immutable way.
 * 
 */
abstract class DoctrineORMRepository implements Repository
{
    /**
     * This is Doctrine's Entity Manager. It's fine to expose it to the child class.
     * 
     * @var EntityManagerInterface
     */
    protected $manager;
    /**
     * We don't want to expose the query builder to child classes.
     * This is so we are sure the original reference is not modified.
     * 
     * We control the query builder state by providing clones with the `query`
     * method and by cloning it with the `filter` method.
     *
     * @var QueryBuilder
     */
    private $queryBuilder;

    /**
     * DoctrineORMRepository constructor.
     * @param EntityManagerInterface $manager
     * @param string $entityClass
     * @param string $alias
     */
    public function __construct(EntityManagerInterface \(manager, string \)entityClass, string $alias)
    {
        \(this-&gt;manager = \)manager;
        \(this-&gt;queryBuilder = \)this-&gt;manager-&gt;createQueryBuilder()
            -&gt;select($alias)
            -&gt;from(\(entityClass, \)alias);
    }

    /**
     * @inheritDoc
     */
    public function getIterator(): Iterator
    {
        yield from new Paginator($this-&gt;queryBuilder-&gt;getQuery());
    }

    /**
     * @inheritDoc
     */
    public function slice(int \(start, int \)size = 20): Repository
    {
        return \(this-&gt;filter(static function (QueryBuilder \)qb) use (\(start, \)size) {
            \(qb-&gt;setFirstResult(\)start)-&gt;setMaxResults($size);
        });
    }

    /**
     * @inheritDoc
     */
    public function count(): int
    {
        \(paginator = new Paginator(\)this-&gt;queryBuilder-&gt;getQuery());
        return $paginator-&gt;count();
    }

    /**
     * Filters the repository using the query builder
     *
     * It clones it and returns a new instance with the modified
     * query builder, so the original reference is preserved.
     *
     * @param callable $filter
     * @return $this
     */
    protected function filter(callable $filter): self
    {
        \(cloned = clone \)this;
        \(filter(\)cloned-&gt;queryBuilder);
        return $cloned;
    }

    /**
     * Returns a cloned instance of the query builder
     *
     * Use this to perform single result queries.
     *
     * @return QueryBuilder
     */
    protected function query(): QueryBuilder
    {
        return clone $this-&gt;queryBuilder;
    }

    /**
     * We allow cloning only from this scope.
     * Also, we clone the query builder always.
     */
    protected function __clone()
    {
        \(this-&gt;queryBuilder = clone \)this-&gt;queryBuilder;
    }
}
</code></pre>
<p>This API can be improved of course, but the main principle is the immutability of it. Note how we don’t expose the <code>QueryBuilder</code>. This is because it’s dangerous: an inexperienced developer could apply filters to it and mutate the original reference, causing a massive bug. Instead, we provide two convenience methods for child classes, <code>filter</code> and <code>query</code>. The first one takes a callable which in turn takes a cloned instance of the <code>QueryBuilder</code> as an argument. The second one just returns a cloned <code>QueryBuilder</code> so the child class can query anything.</p>
<p>Then, we use that API in our <code>UserRepository</code> and implement the remaining methods.</p>
<pre><code class="language-php">&lt;?php
declare(strict_types=1);

namespace RepositoryExample\User;

use DateTime;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\QueryBuilder;
use DomainException;
use RepositoryExample\Common\DoctrineORMRepository;

/**
 * Class DoctrineORMUserRepository
 * @package RepositoryExample\User
 */
final class DoctrineORMUserRepository extends DoctrineORMRepository implements UserRepository
{
    protected const ENTITY_CLASS = User::class;
    protected const ALIAS = 'user';

    /**
     * DoctrineORMUserRepository constructor.
     * @param EntityManagerInterface $manager
     */
    public function __construct(EntityManagerInterface $manager)
    {
        parent::__construct($manager, self::ENTITY_CLASS, self::ALIAS);
    }

    public function add(User $user): void
    {
        \(this-&gt;manager-&gt;persist(\)user);
        // I usually implement flushing in a Command Bus middleware.
        // But you can flush immediately if you like.
    }

    public function remove(User $user): void
    {
        \(this-&gt;manager-&gt;remove(\)user);
        // I usually implement flushing in a Command Bus middleware.
        // But you can flush immediately if you like.
    }

    public function ofId(string $id): ?User
    {
        \(object = \)this-&gt;manager-&gt;find(self::ENTITY_CLASS, $id);
        if ($object instanceof User) {
            return $object;
        }
        return null;
    }

    /**
     * @param string $email
     * @return User|null
     */
    public function ofEmail(string $email): ?User
    {
        try {
            \(object = \)this-&gt;query()
                -&gt;where('user.email = :email')
                -&gt;setParameter('email', $email)
                -&gt;getQuery()-&gt;getSingleResult();
        } catch (NoResultException $e) {
            return null;
        } catch (NonUniqueResultException $e) {
            throw new DomainException('More than one result found');
        }
        return $object;
    }

    public function withActiveStatus(): UserRepository
    {
        return \(this-&gt;filter(static function (QueryBuilder \)qb) {
            $qb-&gt;where('user.active = true');
        });
    }

    public function registeredBefore(DateTime $time): UserRepository
    {
        return \(this-&gt;filter(static function (QueryBuilder \)qb) use ($time) {
            $qb-&gt;where('user.registeredAt &lt; :before')
                -&gt;setParameter(':before', $time, Types::DATETIME_MUTABLE);
        });
    }

    public function registeredAfter(DateTime $time): UserRepository
    {
        return \(this-&gt;filter(static function (QueryBuilder \)qb) use ($time) {
            $qb-&gt;where('user.registeredAt &gt; :after')
                -&gt;setParameter(':after', $time, Types::DATETIME_MUTABLE);
        });
    }
}
</code></pre>
<p>The result is nice to work with. I’ve taken this approach in several projects so far and it feels great. The method names convey meaning and work well. Creating different implementations like a Doctrine Mongo ODM, Filesystem or In-Memory it’s trivial. Implementors just need to take into account the immutability aspect of it, but that’s all really.</p>
<h2><em>A Posteriori</em> Advice and Warnings</h2>
<p>If I'm writing this section now after three years, that is a good thing. First, it means that I still use this pattern all the time. Secondly, it means that I use it better than before. So, here are some nuances that I've come to consider over time.</p>
<h3>Limit these APIs to what your Command Handlers need</h3>
<p>I've come to exercise more reluctance to use my repository interfaces in every place in the codebase that I need to query for something. I think they are great for using them in my command handlers, because of the expressiveness and the richness of the API of my models. The whole point of them is to make state mutations as clear and close to the domain language as they can be.</p>
<p>However, for most <strong>read</strong> operations that will end up sending some data over the wire as JSON, I think using the repository pattern as presented here is overkill. The REST API is not a domain concern. It seems pointless to fetch primitives from a database, hydrate them into those rich domain objects (and pay the price for that in performance) to just discard all that and pass them through a serializer that will convert them into primitives again.</p>
<p>My preferred approach now for sending data over the wire as JSON representations is to have a single service that knows about the Entity Manager and does all that. Usually, that service turns off hydration and knows certain things like properties that should be not exposed, etc.</p>
<p>Maybe I do this because I've realized that querying is not a Domain concern if the results of that query are not going to be used in a business action. Again, returning records for a JSON API is not a business action, so I don't pass that through domain objects or constructs like my models and my repositories. This might be the reason why <a href="https://matthiasnoback.nl/2019/06/you-may-not-need-a-query-bus/">Matthias Noback considers query buses unnecessary</a>, and I very much agree with his reasoning.</p>
<p>However, when you need to filter and query specific things for implementing a state mutation, is when you need all the power and expressiveness that a rich domain and repositories implemented this way give you.</p>
]]></content:encoded></item><item><title><![CDATA[Naming Interfaces in PHP, Java, et al.]]></title><description><![CDATA[I've written about this already in a previous post, but I think it deserves a post of its own. I think it is time we stop appending the word Interface to our interfaces name.
It is just completely unn]]></description><link>https://blog.mnavarro.dev/naming-interfaces-in-php-java-et-al</link><guid isPermaLink="true">https://blog.mnavarro.dev/naming-interfaces-in-php-java-et-al</guid><category><![CDATA[naming]]></category><category><![CDATA[Interfaces]]></category><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Mon, 03 Apr 2023 11:00:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680087951226/b47fdcd1-e290-46c5-ab78-d3bea21ee7af.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've written about this already in a previous post, but I think it deserves a post of its own. I think it is time we stop appending the word <code>Interface</code> to our interfaces name.</p>
<p>It is just completely unnecessary.</p>
<p>The same goes for anything similar: prepending <code>Abstract</code> to abstract classes or suffixing traits with the word <code>Trait</code>, or appending <code>Exception</code> to exception classes.</p>
<p>It makes sense for three main reasons.</p>
<p>First, it makes sense from an object-oriented naming point of view. It makes sense that the most abstract thing has the most "pure" name in a cluster of implementors. For instance, Symfony Serializer has <code>SerializerInterface</code> and the default serializer implementation is called <code>Serializer</code>. Doesn't make more sense to have <code>Serializer</code> as the interface (because that is the thing being abstracted) and then call the implementation <code>DefaultSerializer</code>? Notice how instead we prepend the implementation name to say something specific about the implementation instead. It makes sense, because the implementation is specific, while the interface is generic.</p>
<p>Second, it makes sense from a screen real-estate point of view. Again back to Symfony serializer, which implements five interfaces that have the word <code>Interface</code> suffixed on their name. So we are using 45 extra characters we don't need, over half of the recommended maximum characters per line (80). And again, we don't need those characters. They are just unnecessary pollution.</p>
<p>Third, it makes sense from a modern tooling point of view. The only possibility that makes sense for keeping this practice, is that we do it to be able to easily identify what is an interface when reading our code. The problem with the argument though is that code assistance tools are pretty good at telling us what the stuff in our code is. They even put different icons on our IDE for interfaces, abstract classes and normal classes. They also autocomplete only interfaces when we type <code>implements</code> and they show what a type is when we hover over the name. I understand this could have been a good reason back in the days when we wrote software with simple text editors. But not today.</p>
<img src="https://media.giphy.com/media/xThtavV3Ds2631gcWk/giphy.gif" alt="" style="display:block;margin:0 auto" />

<p>I hope I have convinced you. Please help me stop this madness that has completely taken the PHP ecosystem (and others!) by storm. We don't need to do this.</p>
<img src="https://media.giphy.com/media/xTiTnBd7qTdhWbyqXK/giphy.gif" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[Interfacing is Decoupling]]></title><description><![CDATA[The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.

I think this is one of the most incredible]]></description><link>https://blog.mnavarro.dev/interfacing-is-decoupling</link><guid isPermaLink="true">https://blog.mnavarro.dev/interfacing-is-decoupling</guid><category><![CDATA[SOLID principles]]></category><category><![CDATA[dependency inversion]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Interfaces]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Thu, 30 Mar 2023 06:15:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680087500723/13ccfe69-5e65-427c-9e30-78e43e3683d2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.</em></p>
<hr />
<p>I think this is one of the most incredible inventions on earth.</p>
<img src="https://anglotopia.net/wp-content/uploads/2015/02/Uk_13a_double_socket.jpg" alt="UK Electrical Outlet" style="display:block;margin:0 auto" />

<p>I'm not talking about the UK electrical outlet in specific, but of the electrical outlet in general. Think about how our lives would be without electrical outlets, and just by having the cables there, ready to be used. Just like this:</p>
<img src="https://www.ul.com/sites/g/files/qbfpbp251/files/styles/hero_boxed_width/public/2020-03/electrical%20wiring%202.jpg?itok=CRHRvplR" alt="8 Signs You May Have a Problem with Your Electrical Wiring | UL Solutions" style="display:block;margin:0 auto" />

<p>We would need to wire up all the appliances in our homes manually, from cable to cable. Apart from being something extremely dangerous, it would be a slow and cumbersome process. Imagine you just need to temporarily unwire a lamp to connect a vacuum cleaner. It would take loads of time! Also, you could get the wires all mixed up: connect the ground to the live and the live to the neutral, and so on. All of our devices would be coupled together to the point of being too hard to change.</p>
<p>The convenience of the electrical outlet is that it removes all that complexity. My appliances only need to implement an interface that conforms to the outlet (the plug) to be able to be correctly connected and be easily swappable to any of the outlets in my house. It removes the need for me to have low-level knowledge about electricity and wiring. It's just so much simpler.</p>
<h2>Outlet Mentality</h2>
<p>When building software, we should be thinking like the inventor of the electrical outlet at all times. But many times we don't think like that. For instance, if our program logic requires us to write a report, we immediately write it to the filesystem. We do something like this:</p>
<pre><code class="language-php">&lt;?php

class ReportWriter
{
    public function writeReport(array $records): void
    {
        $resource = fopen('/some/file.path', 'wb');

        foreach (\(records as \)i =&gt; $record) {
            \(line = sprintf('Record %d: %s', \)i, $record['contents']);
            fwrite(\(resource, \)line);
        }

        fwrite($resource, PHP_EOL);
        \(end = sprintf('Number of records: %d', count(\)records));
        fwrite(\(resouce, \)end);
    }
}
</code></pre>
<p>The code above is like connecting the appliances in your house (your business logic) directly to the electrical wires (the filesystem). Here, we have high-level business logic (the writing and structuring of a report), depending on something low-level (the place where it is stored, the filesystem).</p>
<p>It's much better if we make an abstraction for writing (we don't care where we write), and make both our business logic and our filesystem depend on it.</p>
<pre><code class="language-php">&lt;?php

// This is the abstraction
interface Writer
{
    public function write(string $data): int;
}

// The filesystem implementing the abstraction
class PhpResource implements Writer
{
    public static function open(string $filename): PhpResource
    {
        return new self(fopen($filename, 'wb'));
    }

    private function __construct(
        private $resource
    ) { }

    public function write(string $data): int
    {
        return fwrite(\(this-&gt;resource, \)data);
    }
}

// The business logic using the abstraction
class ReportWriter
{
    public function __construct(
        private readonly Writer $output,
    ) { }

    public function writeReport(array $records): void
    {
        foreach (\(records as \)i =&gt; $record) {
            \(line = sprintf('Record %d: %s', \)i, $record['contents']);
            \(this-&gt;writer-&gt;write(\)line.PHP_EOL);
        }

        $this-&gt;writer-&gt;write(PHP_EOL);
        \(end = sprintf('Number of records: %d', count(\)records));
        \(this-&gt;writer-&gt;write(\)end.PHP_EOL);
    }
}

// This is how you bootstrap it
$resource = PhpResource::open('/some/file.path');
\(reportWriter = new ReportWriter(\)resource);
</code></pre>
<p>Now the high-level business logic does not need to know about the filesystem. And the low-level stuff (writing to a file in the filesystem) has also been simplified under the <code>Writer</code> interface. The <code>Writer</code> interface is our electrical outlet: is what makes it possible to connect our business logic to the filesystem without them knowing anything about each other.</p>
<p>This decoupling is powerful. This is what makes programs to be resilient and also easy to test. Because we don't depend on the filesystem now, while testing, we can have an in-memory <code>Writer</code> in which we can assert that the contents were written as intended.</p>
<p>This is how you decouple software components: by putting an interface in between them. Interfaces, like the electrical outlet, are one of the best inventions since Object Oriented Programming itself.</p>
<h2>Conclusion</h2>
<p>This is just a summary of the Dependency Inversion Principle in SOLID, which states that "High-level modules should not depend on low-level modules, but rather both should depend on abstractions". In our example above, high-level business logic (the writing of a report) was depending on the low-level filesystem operations (for writing a file). Introducing an abstraction that both parties rely on, making it possible to decouple them. Now our business logic can be freely used with any type that implements <code>Writer</code>.</p>
<p>Generally speaking, making your business code rely on abstractions (interfaces) is the best way to decouple it from other things. This is how I write my programs nowadays: I don't even start with the database or the HTTP framework, but rather, I design commands and handlers that rely only on interfaces to do the business actions I need, and then I implement them later. This ensures I focus on the things my business actions need. This approach has the nice benefit that it completely decouples your code from a framework or database library, making it more robust, easier to test and easier to change.</p>
<p>Just remember: interfacing is decoupling.</p>
]]></content:encoded></item><item><title><![CDATA[The Bigger the Interface, The Weaker the Abstraction]]></title><description><![CDATA[The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.

In previous articles, we have been talking]]></description><link>https://blog.mnavarro.dev/the-bigger-the-interface-the-weaker-the-abstraction</link><guid isPermaLink="true">https://blog.mnavarro.dev/the-bigger-the-interface-the-weaker-the-abstraction</guid><category><![CDATA[composition]]></category><category><![CDATA[Interfaces]]></category><category><![CDATA[PHP]]></category><category><![CDATA[SOLID principles]]></category><category><![CDATA[Interface Segregation ]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Wed, 22 Mar 2023 16:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680087232690/44d8fb76-4393-405f-8e4f-62292d56fba4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.</em></p>
<hr />
<p>In previous articles, we have been talking a bit about abstractions: specifically, how to design good ones. The last article was about keeping an eye on leaking implementation details from the public API of an abstraction (the interface definition). Today, we'll talk about keeping the size of our abstractions small, so they can be used effectively.</p>
<p>Before I continue with this article, I must give credit where credit is due. I heard this proverb actually from <a href="https://www.youtube.com/watch?v=PAAkCSZUG1c&amp;t=317s">Rob Pike in his <em>Go Proverbs</em> talk</a>. I don't know if he heard it from someone else or not, but I heard it from him. His explanation is rather short and he claims it to be "a very go specific idea" but I think this principle is quite applicable to other languages as well.</p>
<p>When I'm explaining this to other developers I always point to the <a href="https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface"><code>StreamInterface</code> in the PSR-7 standards</a>. It's a massive interface that breaks this idea from top to bottom. Here is a list of what this interface does:</p>
<ol>
<li><p>It writes (<code>write</code>)</p>
</li>
<li><p>It checks it can write (<code>isWritable</code>)</p>
</li>
<li><p>It reads (<code>read</code>, <code>getContents</code>, <code>__toString</code>)</p>
</li>
<li><p>It checks it can read (<code>isReadable</code>)</p>
</li>
<li><p>It closes (<code>close</code>)</p>
</li>
<li><p>It seeks (<code>eof</code>, <code>rewind</code>, <code>tell</code>, <code>seek</code>)</p>
</li>
<li><p>It checks it can seek (<code>isSeekable</code>)</p>
</li>
<li><p>It exposes implementation details</p>
<ol>
<li><p>You can get the underlying PHP resource (<code>detach</code>)</p>
</li>
<li><p>You can get the resource metadata (<code>getMetadata</code>)</p>
</li>
</ol>
</li>
</ol>
<p>There are several problems with this interface. First, it does too much. Sometimes we just need a thing where to write data or a thing from where to read. But now any I/O operation with this interface requires that we implement all 14 methods, even if they are not relevant to our use case. This makes composition harder because the API surface to decorate is bigger.</p>
<p>Also, the interface "lies" in a certain way. It says it reads (it has a method for it) but first you need to check if the interface supports reading by invoking <code>isReadable</code>. Same for writing and seeking. This capability checking by using methods is an anti-pattern. Types like interfaces are made to express the idea of capabilities using the type system.</p>
<p>And, because this interface leaks implementation details (it's pretty obvious that it is using a PHP resource) it can only be implemented in that way. We have covered this in the previous article by the way.</p>
<h2>Breaking Down the Monster</h2>
<p>This interface could be broken down into multiple interfaces:</p>
<pre><code class="language-php">&lt;?php

interface Reader
{
    /**
      * Reads some bytes from a source.
      *
      * @throws IOError if there is an error while reading
      * @throws EOFError if the end of file has been reached
      */
    public function read(int $bytes): string;
}

interface Writer
{
    /**
      * Writes some bytes to a target.
      *
      * @return int The number of bytes written
      *
      * @throws IOError if there is an error while writing
      */
    public function write(string $contents): int;
}

interface Closer
{
    /**
      * Closes the underlying source
      *
      * @return void
      *
      * @throws IOError if there is an error while closing
      */
    public function close(): void;
}

interface Seeker
{
    /**
      * Seeks to the specified position.
      *
      * @return int The new position of the pointer
      *
      * @throws IOError if there is an error while seeking
      */
    public function seek(int \(offset, int \)pos = SEEK_CURRENT): int;
}
</code></pre>
<p>This is only more powerful now thanks to PHP's 8.1 Intersection Types:</p>
<pre><code class="language-php">&lt;?php

class Request
{
    public string $method;
    public Uri $uri;
    // Notice how we compose the two types becasue the body of a request can only be read and be closed.
    public Reader&amp;Closer $body;
    public Headers $headers;
}
</code></pre>
<h2>Type Checking Instead of Method Calling</h2>
<p>Instead of calling a method like <code>isSeekable</code>, now we can ensure the type hints for the required behaviour. But also, we could optionally be lenient and take a <code>Reader</code> and on runtime check if we need to seek to a particular point just to be safe:</p>
<pre><code class="language-php">&lt;?php

function readAll(Reader $reader): string
{
    // Note how this is more robust and clear
    // because it uses the type system
    if ($reader instanceof Seeker) {
        $reader-&gt;seek(0, SEEK_START);
    }
    
    $contents = '';
    while (true) {
        try {
            \(contents .= \)reader-&gt;read(2046); 
        catch (EOFError $e) {
            break;
        }     
    }
    
    return $contents;
}
</code></pre>
<p>Granted: the conditional logic here would be no different than in the <code>StreamInterface</code> by using <code>isSeekable</code> instead of <code>instanceof</code>. But still, it's more powerful because of the type-system: you can enforce the <code>Seeker</code> by type hints and ensure your program will behave correctly.</p>
<h2>Think About Capabilities, Not Mere Wrappers</h2>
<p>Sometimes, when designing abstractions that may have many methods, it's more useful to think about the abstraction as a collection of capabilities rather than just a mere wrapper around an implementation.</p>
<p>I had this problem when I created a custom abstraction over certain payment gateways in a project I was working on. In the beginning, I started with a big interface called <code>PaymentGateway</code>. It seemed logical at the time:</p>
<pre><code class="language-php">&lt;?php

interface PaymentGateway
{
    public function authorize(Payment $payment): Authorization;

    public function capture(Money \(amount, Authorization \)auth): Capture;

    public function refund(Money \(amount, Authorization \)auth): Refund;
}
</code></pre>
<p>But then not all the Payment Gateways I was implementing supported deferred capture of funds, or refunds, so I ended up adding the following methods:</p>
<pre><code class="language-php">&lt;?php

interface PaymentGateway
{
    public function authorize(Payment $payment): Authorization;

    public function capture(Money \(amount, Authorization \)auth): Capture;

    public function refund(Money \(amount, Authorization \)auth): Refund;

    public function supportsCapture(): bool;

    public function supportsRefunds(): bool;
}
</code></pre>
<p>That was a bad idea. A Payment Gateway basic mission is to authorize the transfer of funds on behalf of a customer. Capturing and refunding are secondary capabilities that not all gateways possess and support. It would have been better to separate those capabilities into their own interfaces and model them as separate types.</p>
<pre><code class="language-php">&lt;?php

interface PaymentGateway
{
    public function authorize(Payment $payment): Authorization;
}

interface Capturer
{
    public function capture(Money \(amount, Authorization \)auth): Capture;
}

interface Refunder
{
    public function refund(Money \(amount, Authorization \)auth): Refund;
}
</code></pre>
<p>This way, a <code>WorldpayPaymentGateway</code> could implement all three of these methods, but others won't.</p>
<h2>Conclusion</h2>
<p>Big abstractions are weaker. They are harder to implement and often lie about the methods they support, and if you are not careful, they might even end up exposing implementation details.</p>
<p>What I've explained here is really the Interface Segregation Principle. This principle states that a client should not rely on methods they don't use. The original reason is that in certain languages this undesired dependency might trigger a chain of recompilation of other modules. But also from a maintenance perspective, big interfaces make implementation and composition much harder to do than they should be.</p>
<p>Remember then, the bigger the interface, the weaker the abstraction.</p>
]]></content:encoded></item><item><title><![CDATA[What You Really Need To Know About Testing]]></title><description><![CDATA[Sometimes discussions on testing frustrate me beyond measure. They do because everyone is assuming so much on either side. They take for granted that the world shares their notions of the differences ]]></description><link>https://blog.mnavarro.dev/what-you-really-need-to-know-about-testing</link><guid isPermaLink="true">https://blog.mnavarro.dev/what-you-really-need-to-know-about-testing</guid><category><![CDATA[Testing]]></category><category><![CDATA[Mocking]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Tue, 21 Mar 2023 09:29:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/OZcQIhidMTw/upload/76a67cf97c1071e883d1ac2dd62348f5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sometimes discussions on testing frustrate me beyond measure. They do because everyone is assuming so much on either side. They take for granted that the world shares their notions of the differences between a stub, a mock and a spy. They believe that the definition of a unit, functional, integration, acceptance or end-to-end test is obvious to everyone. They render common knowledge the fact that you should have X, Y or Z proportion of each type of test in your codebase. They battle about which testing framework to use based on their features, or what patterns to implement in their tests. Go developers still are battling between using test tables or just simple functions.</p>
<p>All this frustrates me. It does because testing discussions become focused on the details and not on the bigger picture and goal of testing.</p>
<p>The bottom line, tests are little programs that assert things about your code. There are only two main requirements for them: (1) they must run quickly and, (2) they must fail clearly and for useful reasons.</p>
<p>You might cover all of your applications with a Cypress suite, but then good luck running that on a CI: it will become your delivery bottleneck. Or try to hit the database in every single one of your tests that use PHPUnit: that's going to take a while to run. Tests are meant to give us feedback quickly. When working with a codebase, we need to know if we broke something with our changes. We can't wait 5 minutes for that.</p>
<p>Is of little use to have everything covered with integration or acceptance tests if every valid change to the codebase is going to break half of your tests. You need to think about what you are asserting on those tests. Assert structure and not just compare strings. Write validators if necessary for creating complex assertions more easily. Also, assertions need to be constructed to give the developer an accurate error message, so they can identify the source of the problem. Tests should fail <em>clearly</em>.</p>
<p>Again, <strong>make sure your tests run quickly and fail for useful reasons.</strong> Unit tests that overuse mocks tend to run very fast, but they fail often with valid code changes. Integration tests are a bit slower and rely on heavy dependencies sometimes, but tend to fail for correct reasons. End-to-end tests are expensive to run and very slow, but if you assert correctly about them, they can detect valid failures.</p>
<p>Find the test strategy that better adjusts to your team's knowledge and the kind of project you are working on. Once you have it, keep improving your testing suite by eliminating slow and flaky tests. That's all that matters really.</p>
]]></content:encoded></item><item><title><![CDATA[The Goal of Software Engineering]]></title><description><![CDATA[For almost the whole extent of my career in Engineering, I have thought about the answer to the following question:

What is the goal of Software Engineering?

When I started -- and for a good while -]]></description><link>https://blog.mnavarro.dev/the-goal-of-software-engineering</link><guid isPermaLink="true">https://blog.mnavarro.dev/the-goal-of-software-engineering</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[software development]]></category><category><![CDATA[software]]></category><category><![CDATA[pragmatism]]></category><category><![CDATA[dogmatism]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Mon, 20 Feb 2023 16:00:39 GMT</pubDate><content:encoded><![CDATA[<p>For almost the whole extent of my career in Engineering, I have thought about the answer to the following question:</p>
<blockquote>
<p>What is <strong>the</strong> goal of Software Engineering?</p>
</blockquote>
<p>When I started -- and for a good while -- I believed the goal of Software Engineering was to <strong>produce working software that was useful to their users</strong>. After all, what is the point of writing Software if is not going to be used by anyone? This is what I call the <em>pragmatic</em> goal.</p>
<p>But then, later down the line, I came to believe that the true goal of Software Engineering was to <strong>produce software that was easy to maintain and evolve by their developers.</strong> After all, what is the point of writing Software that will have to be re-written every couple of years? This is what I call the <em>dogmatic</em> goal.</p>
<p>During my career, I've met people leaning toward one side more than the other. I hate to generalise, but followers of the pragmatic goal <em>tend</em> to be very effective at accomplishing tasks and delivering value, but pay very little attention to design and evolvability, and make architectural decisions that happen to be very costly later down the line. On the other hand, followers of the <em>dogmatic</em> approach <em>tend</em> to be more focused on theory, patterns, methodologies, abstraction and processes rather than thinking about how to effectively solve a business problem and deliver value to users. They oftentimes end up coming up with over-engineered solutions that are unnecessarily complex or that solve the wrong problem because they lack user perspective.</p>
<p>This reality is engineering's own <a href="https://faculty.fiu.edu/~harrisk/Notes/Aesthetics/Apollonian-%20Dionysian%20Dichotomy.htm#:~:text=%E2%80%9CApollonian%E2%80%9D%20and%20%E2%80%9CDionysian%E2%80%9D,central%20principles%20in%20Greek%20culture&amp;text=More%20to%20the%20point%2C%20the,nearly%20opposing%20values%20and%20orientations.">Apollonian and Dionysian</a> sort of tension. I would say you can classify every engineer on earth in one of these two opposing camps, and that they usually are accompanied by other traits and characteristics opposed to the ones of the other side, in a truly remarkable way.</p>
<table><tbody><tr><td><p><strong>Pragmatism</strong></p></td><td><p><strong>Dogmatism</strong></p></td></tr><tr><td><p>User-centred</p></td><td><p>Engineer-centred</p></td></tr><tr><td><p>Focus on Usefulness</p></td><td><p>Focus on Correctness</p></td></tr><tr><td><p>Present Looking</p></td><td><p>Future Looking</p></td></tr><tr><td><p>Results Driven</p></td><td><p>Process Driven</p></td></tr><tr><td><p>Simplicity</p></td><td><p>Complexity</p></td></tr><tr><td><p>Naiveness</p></td><td><p>Pessimism</p></td></tr><tr><td><p>Emotive</p></td><td><p>Analytical</p></td></tr><tr><td><p>Delivers Value</p></td><td><p>Exhibits Knowledge</p></td></tr><tr><td><p>Seeks Freedom</p></td><td><p>Seeks Order</p></td></tr><tr><td><p>Flexibility</p></td><td><p>Uniformity</p></td></tr><tr><td><p>Concretions</p></td><td><p>Abstractions</p></td></tr></tbody></table>

<p>You might read this list and immediately identify with one side of the spectrum. Well, I'm here to tell you that if you easily identify yourself with one side, then you might want to start pushing to the other.</p>
<p>Neither of these camps is correct by itself: both put the focus on things that are true and valuable. <strong>I think the true goal of software engineering is to produce software that is both easy to use by their users and easy to maintain by their developers.</strong> And the biggest challenge is to successfully navigate the tension that exists between both.</p>
<p>For instance, let's take the pragmatic approach. You could build the most useful piece of software, but if it is poorly designed, then you can know for sure it will cease to be useful because a rewrite will be needed. I've seen systems that are awful to work with and that quickly burn out their engineers because the last thing someone thought about was how to make it maintainable. Sooner rather than later, your engineering turnover rate cost will be much more than what your business can handle. You will have a really good idea or product, but it will be impossible to scale.</p>
<p>On the other hand, you can build the most maintainable software. And you might have no issues finding engineers that want to work in a well-designed software or system. But can get so focused on correctness and maintainability, that you might be late to the market or worse even, you discover that the market has invalidated many of the hypotheses in which you built your product.</p>
<p>There is no escaping from the fact you need both. A good engineer is capable of being both <em>pragmatic</em> and <em>dogmatic</em> at the same time. And this is no easy feat: you will over-steer to one side or the other quite often, so we must be constantly reminded of this.</p>
<p>The goal of Software Engineering is then to produce software that is both easy to maintain by their developers and that is useful to their users. Is part of your job to have both things in mind when exercising your trade, and you must not compromise on any of them.</p>
]]></content:encoded></item><item><title><![CDATA[The Power of Aesthetics]]></title><description><![CDATA[Back in the day, I used to be a pretty naive fella (I would like to believe I'm a bit more shrewd now). I used to think the world and the people in it were, at their core, very simple and straightforw]]></description><link>https://blog.mnavarro.dev/the-power-of-aesthetics</link><guid isPermaLink="true">https://blog.mnavarro.dev/the-power-of-aesthetics</guid><category><![CDATA[Philosophy]]></category><category><![CDATA[aesthetics]]></category><category><![CDATA[logic]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Sun, 19 Feb 2023 10:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/qYcW08zwrwQ/upload/f6434d1897bef55fcf8836fb634941a2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Back in the day, I used to be a pretty naive fella (I would like to believe I'm a bit more shrewd now). I used to think the world and the people in it were, at their core, very simple and straightforward, and that human relations and understanding were not far for anyone to comprehend and master. I used to think in very black-and-white terms, in many areas of life. And although I still have deep convictions and beliefs about the world, human nature and relationships, I often time tread more carefully and with more nuance than in the past concerning certain topics.</p>
<p>As an example, I am a firm believer that no-fault divorce is a sin. In my days as a bible school student, I used to wonder why people would think otherwise being a topic that is so clearly and unequivocally expounded in the bible. So I used to think that all I needed to convince people that divorce was wrong, was to memorize a few verses here and there and compellingly present them, asking whether they believed them or not. It was a purely logical approach that one could call "classical apologetics". <strong>The premise is that by merely presenting solid evidence, you can convince people of a certain idea or point of view.</strong></p>
<p>I used to think being a minister or a teacher was something simple: you present people the truth, lie down the evidence, and people will believe it. I became an argument machine of some sort: I was interested to know which argument I could present to a given occasion or conflict so I could convince people of what I believed. I would like to believe that my intentions were not founded in just mere argument-winning, but in a genuine interest of leading people to a path I considered to be true and good, despite using a flawed method born of flawed assumptions.</p>
<p><strong>The lethal assumption that classical apologetics makes (or of any other logical approach for that matter) is that humans act primarily in a rational way and that they make decisions and inform their beliefs by the use of reason.</strong> Nothing, though, could be farther from the truth.</p>
<p>It is a fact of life that you and I believe and do things sometimes based on intuition, on based on how nice, good or well something feels or looks. It is not just a matter of reason and logic, it is much more a matter of taste and aesthetics.</p>
<p>For example, what logic or reason powers the repulsion we would feel to use the same toothbrush as the person we have no problem kissing many times? Where is the logic in that? Isn't just kissing someone passionately a more risky activity in terms of germs exchange than sharing a tool used to clean? I'm inclined to believe this is a purely aesthetical construct, but it is however very much embedded in our behaviour.</p>
<p>In the same way, people that believe that divorce is not a sin, do so for more aesthetic reasons than they would like to admit. We could say the same about gay marriage or transgenderism. It is not that these issues have a logical cause. People did not believe them because they were convinced by a logical argument, but rather because in their brains, they came to be plausible, nice and even desirable things. They started to look good, in comparison to the stigma they carried in the past. They became worthy of defence and pursuit. They are believed in and accepted because of aesthetics.</p>
<p>Nowadays, it does not look okay to oppose gay marriage, divorce or transgenderism. J.K. Rowling is a perfect example of the clash between logic and aesthetics. She speaks a logical language to a population that is not interested in logical arguments because something beyond logic is invested into creating the conviction: to be against transgenderism would be ugly, even if that opposition comes from logical concerns for woman's rights.</p>
<p>The bottom of the matter is that society's recognition frameworks do not function logically: they are very much aesthetical. And the massive shape in traditional western cultures and values we have experienced in the last 6 decades has not been caused by a shift in arguments and logic. Quite the opposite: it is the product of a society in which how something looks or feels has profound value.</p>
<p>Aesthetics have tremendous power in shaping a culture. If you manage to present a good story, a sugar-coated narrative that appeals to people's emotions, you can shape the culture in unimaginable ways. It does not matter anymore if God said "you shall not eat of the fruit of the tree", the serpent will always find a way to show you that "the fruit of the tree [is ...] pleasing to the eye", so then it can convince you to eat it.</p>
]]></content:encoded></item><item><title><![CDATA[Leaks Can Become Floods]]></title><description><![CDATA[The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.

So far we have talked about how we need to]]></description><link>https://blog.mnavarro.dev/leaks-can-become-floods</link><guid isPermaLink="true">https://blog.mnavarro.dev/leaks-can-become-floods</guid><category><![CDATA[SOLID principles]]></category><category><![CDATA[Liskov Substitution Principle]]></category><category><![CDATA[Interfaces]]></category><category><![CDATA[abstraction]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Wed, 15 Feb 2023 16:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680087157863/bab4ad92-f4f0-4b5e-9149-6e497809d834.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.</em></p>
<hr />
<p>So far we have talked about how we need to design having <em>change</em> in mind, and also established that the best changes are those that don't touch what already exists but add on top of it, and that we should design our applications so they can change that way. Today I would like to talk about being careful with our designs, particularly when we are designing abstractions.</p>
<h2>What is an abstraction anyway?</h2>
<p>Abstraction's only purpose is to help you simplify a problem or an API behind a stable contract. Some people see abstractions as something to be avoided like a plague and I understand where they are coming from. People who warn about hasty abstractions usually use the term abstraction meaning the extraction of a duplicated routine to keep the code DRY. This is not the definition of abstraction I have in mind.</p>
<p>The definition of abstraction I will use here relates more to <strong>contract definition</strong> than avoiding code duplication. In other words, this is an abstraction:</p>
<pre><code class="language-php">&lt;?php

interface TemplateRenderer
{
    public function render(string \(template, array \)data = []): string;
}
</code></pre>
<p><code>TemplateRenderer</code> is an interface, and as such, <strong>it is an abstraction over rendering a template</strong>. It does not specify <em>how</em> a template is rendered though (that's why is an abstraction), it just cares about the methods an implementation should have to be able to render a template.</p>
<p>Of course, abstractions are not only interfaces. Abstractions can be concrete classes too that assume an implicit "contract". But I'm more interested in interfaces this time.</p>
<h2>Leaky Abstractions</h2>
<p><strong>The golden rule of designing interfaces as abstractions is that you should be able to swap implementations without needing to modify client code.</strong> So, if I have a <code>TwigTemplateRenderer</code> and a <code>NativePhpTemplateRenderer</code> implementing the <code>TemplateRenderer</code> above, I should be able to swap one for the other without changing anything in the code that uses the interface. If I need to change something, then I'm dealing with what is called a <em>leaky abstraction</em>.</p>
<p>We call leaky abstractions those abstractions that, intentionally or unintentionally, <strong>expose implementation details</strong> to client code. The fact that they expose implementation details forces you to change those details when you change the implementation.</p>
<p>There are two main ways in which this happens, at least in PHP, and that's through method arguments or exceptions. Let's suppose you have the following code using our above defined <code>TemplateRenderer</code>:</p>
<pre><code class="language-php">&lt;?php

use Twig\Error\LoaderError;

class SendWelcomeEmail
{
    private TemplateRenderer $renderer;
    private Mailer $mailer;

    public function __construct(
        TemplateRenderer $renderer,
        Mailer $mailer
    )
    {
        \(this-&gt;renderer = \)renderer;
        \(this-&gt;mailer = \)mailer;
    }

    public function handle(UserRegistered $evt): void
    {
        try {
            \(body = \)this-&gt;renderer-&gt;render('emails/welcome.twig', [
                'username' =&gt; $evt-&gt;username,
                'name' =&gt; $evt-&gt;name,
            ]);
        } catch (LoaderException $e) {
            throw new LogicException('Template does not exist', previous: $e);
        }

        $email = (new Email())
            -&gt;withBody($body)
            -&gt;withSubject('Welcome')
            -&gt;withFrom('My Awesome App &lt;noreply@awesomeapp.com&gt;')
            -&gt;withTo(sprintf('%s &lt;%s&gt;', \(evt-&gt;name, \)evt-&gt;email))
        ;

        \(this-&gt;mailer-&gt;send(\)email);
    }
}
</code></pre>
<p>So this code is a classical event listener for sending an email upon registration. You have a <code>Mailer</code> abstraction and a <code>TemplateRenderer</code> one. Can you spot the two problems with the <code>TemplateRenderer</code> one? I'll give you a clue. It has to do with the parts of the code that reference <code>Twig</code>.</p>
<p>The underlying problem here is that, although we are using an abstraction over rendering templates, the fact that we are using Twig as the internal engine leaks in this piece of code. It's pretty obvious to the code that this is using Twig. It has the Twig way of defining a template name (with slashes and with the <code>.twig</code> extension at the end) and it catches possible Twig exceptions. If I create another implementation of <code>TemplateRenderer</code> that does not use Twig but a native PHP renderer, I would need to change this code too.</p>
<p>This might sound like nitpicking, but it does have a big impact when your abstraction is widely used throughout the system. Although modern IDE tools would aid in changing all those references, not all developers have them. Plus, not all developers might know this is widely used and might just change the implementation anyway.</p>
<h2>Fixing Leaks</h2>
<p>You need to make sure that when you design an abstraction like a <code>TemplateRenderer</code> one, you think carefully about your use case. So let's fix this. First, it seems we need an error of our own to indicate that an irrecoverable failure happened when attempting to render a template. So let's define our own <code>RenderError</code> exception. And secondly, we need to make the way of identifying a template a bit more universal. Let's use dots and remove the extension.</p>
<pre><code class="language-php">&lt;?php

use My\Namespace\Template\RenderError;

class SendWelcomeEmail
{
    private TemplateRenderer $renderer;
    private Mailer $mailer;

    public function __construct(
        TemplateRenderer $renderer,
        Mailer $mailer
    )
    {
        \(this-&gt;renderer = \)renderer;
        \(this-&gt;mailer = \)mailer;
    }

    public function handle(UserRegistered $evt): void
    {
        try {
            \(body = \)this-&gt;renderer-&gt;render('emails.welcome', [
                'username' =&gt; $evt-&gt;username,
                'name' =&gt; $evt-&gt;name,
            ]);
        } catch (RenderError $e) {
            throw new LogicException('Welcome email template could not be rendered', previous: $e);
        }

        $email = (new Email())
            -&gt;withBody($body)
            -&gt;withSubject('Welcome')
            -&gt;withFrom('My Awesome App &lt;noreply@awesomeapp.com&gt;')
            -&gt;withTo(sprintf('%s &lt;%s&gt;', \(evt-&gt;name, \)evt-&gt;email))
        ;

        \(this-&gt;mailer-&gt;send(\)email);
    }
}
</code></pre>
<p>That's it. No trace of Twig anymore. Is up to the implementations now to catch the errors and transform them into <code>RenderError</code> and to modify the template name to change dots for slashes and add the file extension at the end.</p>
<p>So, when designing abstractions, take special care with the kind of arguments you are taking and ask yourself if they expose any of the internal details. And also, define exceptions that you are interested in communicating and make them part of the abstraction contract, so your consumers know what to catch and implementers know what to wrap.</p>
<h2>Conclusions</h2>
<p>I have done it again. This is the <a href="https://stackify.com/solid-design-liskov-substitution-principle/">Liskov Substitution Principle</a> applied to interfaces. Although this principle was first thought of in the context of subtyping with inheritance (the typical Square-Rectangle example) and modern OOP does not focus too much on inheritance anymore, it is still useful when considering interfaces, as they are a particular form of subtyping.</p>
<p>Abstractions that leak implementation details are one of those things few people pay attention to. Because it seems something so small and so trivial, is often dismissed or ignored. This might be the right response if the abstraction is not widely used. But if the abstraction turns out to be one of the centrepieces of your application, that leak can flood the rest of the application triggering a chain of change that could be hard to deal with.</p>
<p>So, keep an eye on your leaks, because they might become floods.</p>
]]></content:encoded></item><item><title><![CDATA[Dealing With Imposter Syndrome]]></title><description><![CDATA[Have you ever thought that your "success" is mostly because of luck or good timing? Or that you got that promotion because maybe no one else wanted to take it? Do you live in fear, constantly trying t]]></description><link>https://blog.mnavarro.dev/dealing-with-imposter-syndrome</link><guid isPermaLink="true">https://blog.mnavarro.dev/dealing-with-imposter-syndrome</guid><category><![CDATA[impostor syndrome]]></category><category><![CDATA[work]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Mon, 13 Feb 2023 16:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/boOX0FQuHuw/upload/6405112e30eb52e8190f1629fef4d498.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever thought that your "success" is mostly because of luck or good timing? Or that you got that promotion because maybe no one else wanted to take it? Do you live in fear, constantly trying to show your peers and superiors that you are not underqualified? Do you think the praise you receive at work is because you are a nice gal or fella and not so much because it is a job well done? Let me tell you, you are not alone.</p>
<p>It's the secret best kept in the professional world: the vast majority of adults in the UK (85%) experience intrusive thoughts that make them feel inadequate or underqualified for their position, despite their experience. This is called Imposter Syndrome. Broken down by gender, 80% of men experience it versus 90% of women. These numbers come from an <a href="https://www.thehubevents.com/resources/impostor-syndrome-survey-results">independent survey</a> and based on my own personal, biased and, of course, limited experience, they are probably not too far from reality.</p>
<p>I have experienced it myself too and still do, although probably in a different way than you do. The way it manifests in me is that sometimes I think I've had some degree of success in life because I'm a pretty chilled, easy-going white fella with an education who can speak with enough confidence and think with enough substance. I do hope that I have some reasonable degree of self-awareness that those things I think of myself are true (I'll let other people judge that). However, true or not, the subtle spurious thought slides in one way or another and whispers: "that's <em>the reason</em> why you are where you are".</p>
<p>Have you ever felt the same? Are you feeling like that right now? Do you ever have thoughts suggesting that you are not good enough? Are you having them right now but suppressing them with affirmations? Well, I want to share with you what helps me when I feel this way. I'm no psychologist, and this is certainly not therapy, but I know a thing or two about the way people think, and about human nature. What I will say comes from that experience.</p>
<p>Imposter Syndrome can manifest in different ways, but it always starts with those spurious throughs about your inadequacy. Some people have the luck of having good mental coping mechanisms, so they can dismiss those thoughts promptly as they appear (but notice that the thought is always there). For other people, those thoughts can trigger subsequent thoughts that can quickly lead to anxiety. If that is your case, I would recommend you seek counselling from a mental health professional focused on helping you develop those coping mechanisms.</p>
<h2>Is About Quality, Not Quantity</h2>
<p>The sort of standard way I've heard people recommend to deal with this is to (a) seek words of affirmation from others and/or (b), affirm yourself. But affirmation is like treating a headache with morphine: you will feel good immediately, then you will crave it, and soon you would not be able to live without it. I don't know about you but I would rather have my sense of value lie in a more stable foundation than the amount of affirmation I receive. There is gotta be something better, right?</p>
<p><strong>What helps me is to recognize the truth that I have never been and will never be adequate for any of the things I've done or will do.</strong> I cried my eyes out on my first day of school. I was terrified of giving my first kiss and making a fool of myself. When I switched schools, I wondered if I was going to fit in or be bullied again. When it was time to go to Uni and choose a career I had no idea how the world worked, and I thought I was not ready to choose something for life. When I had my first formal job I didn't know if I was going to live up to the challenge. When I left that job in my mid-twenties crisis I had no idea what I was going to do (it seemed I had returned to my seventeens in a very real way!). When my brother asked me if I could help him with a programming project I told him he was crazy and that it was too complex for me. When I got married I was not sure if I was prepared to selfishly love and care for someone else (I could barely do that for myself!). Now that we are seriously thinking about children, I do not feel capable at all to guide, nurture, care and be an example for a little human being, but somehow I still want to be a father.</p>
<p>In all these things I was never "adequate", "ready" or "prepared". Nope. No one prepares you for what is to come, because no one knows what might come and in what form. We are all learners, facing first-time challenges.</p>
<p>You might say "Yes, but some people have more experience because they have been in more jobs and roles, and they are educated, and they know what they are talking about". Indeed, but as every role, situation or organisation is different and every context unique, their experience might prove not adequate to that particular context. People might have different amounts of experience, but no one ever has the right one. No one. Is not a question of quantity, but quality. And on that, we all fall short.</p>
<p>One of the companies I worked for brought this high-profile executive role person. There was quite the hype and expectation before she joined us because of her credentials and the places where she had contributed previously (mostly fortune 500 companies). Everyone was looking forward to working with her. But after three months of her joining, everyone was pretty much hoping she would leave. And she did. Was she extremely qualified and experienced? Yes, very much so. Was her experience the right one in our context? Not at all.</p>
<p>So remember: you are not adequate for your role. That might seem bad news, but the good news is that no one is. Freed now of that weight, we can move on to the next step.</p>
<h2>Break It Until You Make It</h2>
<p>Some have a "Fake it until you make It" mentality. They seem to know very well that everyone is inadequate but no one seems to openly recognize it. They conclude, therefore, that everyone is faking to some degree and pretending to be something they are not. It follows that those who can fake it the best are the ones who will succeed. It is all about marketing and how you present that fake image of yourself.</p>
<p>You might have struggled with Imposter Syndrome before and maybe have received that recommendation. They seem to start under the right premise we have discussed so far: everyone is inadequate. However, the proposed approach is not just ethically questionable, but mentally taxable. Are you seriously telling me that my life needs to be about pretending to be something I'm not if I want to get somewhere? Who has the mental fortitude to do that?</p>
<p>Mark Zuckerberg once said, "move fast and break things". I'm not elevating Mark as a hero or a figure I look up to, but I think it is fair to say he gets a few things right here.</p>
<p>I think this quote is brilliant. In my view, it means that, since we were not born with experience and knowledge, but rather we acquire it along the way, we should try multiple things in short intervals of time and not be afraid of getting it wrong. After an iteration, you can adjust the course and try again. This is extremely liberating. You may be agreeing with the approach now but I assure you you still haven't got the depths of it.</p>
<p>He's saying that you are free to <strong>experiment</strong>. That means actively doing something trying to find out what works best, evaluating results, and correcting your course based on results. This is the classical methodology of investigation. And although some of us can apply this to our jobs somewhat well, when we apply this to our personal experiences, our emotions get massively on our way.</p>
<p>This is because experimenting often leads to one's admission that our original hypothesis was wrong, and that we have some stuff we need to correct. While most of us might be willing to acknowledge that an approach we tried might be wrong, fewer of us could admit that something we did might be wrong, and even fewer of us, something we believe in or we think about or ourselves.</p>
<p>You need to believe this: a "mistake" is just a verified hypothesis. A failure is just discarding a wrong path. There is way more value in recognizing that we need to change the erroneous course than remaining in the same course because we don't want to admit we went the wrong way. If you live pretending that you are capable, smart, well-prepared and experienced, you will have a hard time admitting you have made a mistake; for the simple reason that your inner self draws its value from the adequacy of the image you present.</p>
<p>If you embrace the learner's path, it frees you, it liberates you. You don't need to know everything. You don't need to be always right. You are constantly learning and discovering better ways. You place more value in other people's approaches and experiences and demonstrate a genuine interest in learning how they came to acquire it. You become more focused on refining your trade than pretending you are a master at it. And that, my dear friend, has way more value in the workplace than all the fancy titles, certifications, skills and recommendations you might amass. I'd rather have one learner, than a thousand pretenders. So move fast and break things. Break it until you make it.</p>
<h2>Closing Thoughts</h2>
<p>This turned out to move in a different direction than I originally intended, and way too long too. But sometimes is good to write words that come straight from the heart. I guess that, in a nutshell, what I intended to convey was that you must not be afraid to acknowledge your inadequacy. First, because no one is adequate; but secondly, because doing so will free you to use the power that honestly embracing one's limitations can exert on your development and of those around you.</p>
]]></content:encoded></item><item><title><![CDATA[Adding is Better Than Changing]]></title><description><![CDATA[The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.

In the previous article of this series, I ]]></description><link>https://blog.mnavarro.dev/adding-is-better-than-changing</link><guid isPermaLink="true">https://blog.mnavarro.dev/adding-is-better-than-changing</guid><category><![CDATA[software development]]></category><category><![CDATA[software design]]></category><category><![CDATA[SOLID principles]]></category><category><![CDATA[wisdom]]></category><category><![CDATA[Open Closed Principle]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Fri, 03 Feb 2023 16:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680087092145/ee60c89b-e336-4ea0-aa70-21917f4a1db7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.</em></p>
<hr />
<p>In the previous article of this series, I touched on the subject of <em>change</em>. I mentioned change as the number one enemy of any software project, and I showed how we can defeat change by isolating the things that <em>could</em> change so that when change shows its ugly face, it does not affect the whole of our program. <a href="https://www.oreilly.com/library/view/97-things-every/9780596809515/ch76.html">This is the Single Responsibility Principle slightly rephrased</a>.</p>
<p>In this article, I will go beyond that idea and say that well-designed and robust code does not need changing. A well-designed system allows for improvements to be made and new features to be coded without modifying existing code but creating new code. Let me explain what I mean by that.</p>
<p>Let's come back to our <code>Pipeline</code> example from the previous article. In it, we defined an interesting interface we didn't touch much upon.</p>
<pre><code class="language-php">&lt;?php

interface Step
{
     public function process(array $record): void;
}
</code></pre>
<p>We made the <code>Pipeline</code> class use this interface to process a record, but we didn't define such a process; that's the point behind an abstraction. Anyhow, let's pretend we implement a step that writes records somewhere.</p>
<pre><code class="language-php">&lt;?php

class WriterStep implements Step
{
    private Writer $writer;
    
    public function __construct(Writer $writer)
    {
        \(this-&gt;writer = \)writer;
    }

    public function process(array $record): void
    {
        \(this-&gt;writer-&gt;write(\)record);
    }
}
</code></pre>
<p>For the sake of the exercise, let's pretend that <code>Writer</code> just writes records to a database or some other form of persistent storage. The writer is not the important part here.</p>
<p>So, so far so good. This <code>WriterStep</code> is pretty neat. It does what it says it does. Until someone says: "We need to log the id of every record we are going to write". So, you might be tempted to do something like this:</p>
<pre><code class="language-php">&lt;?php

class WriterStep implements Step
{
    private Writer $writer;
    private Logger $logger;
    
    public function __construct(Writer \(writer, Logger \)logger)
    {
        \(this-&gt;writer = \)writer;
        \(this-&gt;logger = \)logger;
    }

    public function process(array $record): void
    {
        \(id = (string) (\)record['id'] ?? 'unknown');
        \(this-&gt;logger-&gt;log("Writing record of id '\)id'");
        \(this-&gt;writer-&gt;write(\)record);
    }
}
</code></pre>
<p>The problem with this approach is that it has "touched" existing code and code that was working perfectly fine without the <code>Logger</code> being in there. Is not that we are afraid of bugs: we have tests for that. But we have added another responsibility to the <code>WriterStep</code>. Now, it not only writes, but it also logs stuff. This class has two reasons to change now. What happens when we need to log the id in some of the pipelines and not others? Both <em>writing</em> and <em>logging</em> are <em>coupled</em> now, and they are impossible to separate.</p>
<p>When you modify a piece of code that was doing a perfectly fine job as it was, is usually an alert. There is almost always an alternative to this. The best changes in a software project are those changes that don't touch what is already there but build on top of it. <strong>Adding new stuff is much better than changing existing stuff</strong>.</p>
<p>A system must be well-designed to allow for that to happen. If the system you are working on is poorly designed you might not be able to follow this principle, and it might be a good idea to consider <em>refactoring</em>. However, when you are the one designing the system, you must make sure to provide for this kind of change: it usually involves designing and using good interfaces or abstractions.</p>
<p>In this case, the design we defined in the previous article allows for this without a problem. It is perfectly possible to add logging without even touching the existing <code>WriterStep</code> class. For this, we use a technique called <strong>composition</strong>. This is how it looks:</p>
<pre><code class="language-php">&lt;?php

// The WriterStep stays exactly the same
class WriterStep implements Step
{
    private Writer $writer;
    
    public function __construct(Writer $writer)
    {
        \(this-&gt;writer = \)writer;
    }

    public function process(array $record): void
    {
        \(this-&gt;writer-&gt;write(\)record);
    }
}

// The new LoggerStep wraps a Step and it is also
// a step itself. This is composition.
class LoggerStep implements Step
{
    private Step $next;
    private Logger $logger;

    public function __construct(Step \(next, Logger \)logger)
    {
        \(this-&gt;next = \)next;
        \(this-&gt;logger = \)logger;
    }
    
    public function process(array $record): void
    {
        \(id = (string) (\)record['id'] ?? 'unknown');
        \(this-&gt;logger-&gt;log("Writing record of id '\)id'");
        
        // We pass to the next step, that could be the WriterStep
        \(this-&gt;next-&gt;process(\)record);
    }
}

// Instead of passing the WriterStep as is to the pipeline, you pass a compisition of both the WriterStep and the LoggerStep.
$pipeline = new Pipeline(
    new LoggerStep(
        new WriterStep($writer),
        $logger,
    ),
);
</code></pre>
<p>This achieves the requirement of logging every id that is going to be written, but it keeps logging and writing as completely separate steps. Going back to the first principle, changes in one class should not affect the other. But now we have gone even further: we have delivered a new feature or capability without touching existing code.</p>
<p>I need to make a disclaimer here. It stands to reason that this principle does not mean that a codebase should not have any changes at all; that would be silly. As we have seen, the bootstrapping code in our above example (the code that created the pipeline) changed. And this is fine because this code does not contain our business logic, it's just glueing things together.</p>
<h2>Summary</h2>
<p>I think I got you again! What I have explained here is just the <a href="https://blog.cleancoder.com/uncle-bob/2014/05/12/TheOpenClosedPrinciple.html">Open-Closed Principle</a> rephrased. Many people think that this principle has exclusively to do with <em>inheritance</em>, but it can also be applied using <em>composition</em> as we have seen here. And it applies not just to classes, but to systems as well (i.e. pluggable architectures). Any sort of technique that lets you add extra behaviour to a program without modifying it, would be following this principle. This means the system would let you add behaviour (here lies the <em>openness</em> of it) but without modifying it (here lies the <em>closeness</em>).</p>
<p>So remember to design classes and systems that allow their functionality to be augmented, not by modifying what already is there, but by adding new things that are not there. Adding is much better than changing.</p>
]]></content:encoded></item><item><title><![CDATA[Isolating Your Enemy Wins You The War]]></title><description><![CDATA[The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.

Is kind of von Clausewitz's wisdom that to]]></description><link>https://blog.mnavarro.dev/isolating-your-enemy-wins-you-the-war</link><guid isPermaLink="true">https://blog.mnavarro.dev/isolating-your-enemy-wins-you-the-war</guid><category><![CDATA[single responsibility principle]]></category><category><![CDATA[change]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Fri, 27 Jan 2023 14:25:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680086994366/79b47a38-753c-485d-93c0-591c6753a32a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>The Coder's Proverbs is a series where I summarize some lessons and principles I've learned over my career by using a memorable and simple saying of wisdom.</em></p>
<hr />
<p>Is kind of <a href="https://en.wikipedia.org/wiki/On_War">von Clausewitz's</a> wisdom that to win a war you must weaken your enemy. The prime way of doing it is by isolating them: cutting supply lines, so they cannot receive ammo, food, clothing and other assets; or cutting their communication channels, so they cannot receive instructions or situational updates. Isolating your enemy is key to winning a war.</p>
<p>We can apply this principle to Software Engineering so we can win the war that (sometimes) is writing maintainable and robust code. But, who is our enemy?</p>
<p>I can say with full confidence that the number one enemy of Software Engineering is <em>change</em>. Not the project people, not the product people, not the less inexperienced members of your team, not your language of choice, none of that. The vast majority of your challenges come from <em>change</em>.</p>
<p>Think about it. You would not be working on that feature if a client had not requested it. You wouldn't be struggling with that integration if your users had not demanded it. You would not be fixing that bug if it had not been reported. You would not be refactoring the module you wrote last week if the requirements had not been refined. The sad reality for us (and also the blessing) is that Software is never static: it evolves and is constantly changing. If the software is not changing, then there is no one writing code, and then no suffering developer. Change is an unavoidable reality in Software and the number one cause of rot. Entropy, I think, is the correct term to define this reality.</p>
<p>So, to <strong>win</strong> in the Software Development war -- Oh dear, I sound like one of those LinkedIn influencers! -- you must isolate your enemy. In other words, you must isolate the things that can, might or will change in your code.</p>
<p>Take a look at the following piece of PHP code.</p>
<pre><code class="language-php">&lt;?php

function importCountries()
{
    $url = 'https://restcountries.com/v3.1/all';
    \(contents = file_get_contents(\)url);
    \(data = json_decode(\)contents, true);
    foreach (\(data as \)country) {
        // Real code will do something more meaningful here
        echo $country['name'].PHP_EOL;
    }
}
</code></pre>
<p>Now, there is a bunch of stuff that could be wrong with that code, depending on how possible is for it to change. Remember, <em>code</em> is not the enemy: it is <em>change</em>! If this is code for some automated routine for your toy scrapping project, then it is fine. If this is part of a data-importing application pipeline, then this is severely wrong.</p>
<p>Let's enumerate the possible things that might change in that context.</p>
<ol>
<li><p>What happens if I want to make the data source dynamic and not just get country data from Rest Countries?</p>
</li>
<li><p>What happens if the format then, changes? Can I consume YAML, CSV or XML?</p>
</li>
<li><p>What happens if the action I want to perform on the data changes according to the data?</p>
</li>
<li><p>What happens if I want to take note of the records whose action has failed?</p>
</li>
<li><p>What happens if I want to apply transformations and actions that are repeatable?</p>
</li>
<li><p>What happens if I need to import 500,000 records? Will the system run out of memory?</p>
</li>
</ol>
<p>It is clear that this code is far from ready to handle all those possible scenarios or requests. It needs to isolate the things that might change so it can support the actual change. And the number one way of isolating something in programming is by creating an abstraction for it. This is how it would look like:</p>
<pre><code class="language-php">&lt;?php

interface Step
{
    public function process(array $records): void;
}

class Result
{
    public readonly array $record;
    private ?Throwable $error = null;

    public function __construct(array $record)
    {
        \(this-&gt;record = \)record;
    }

    public function withError(Throwable $e): void
    {
        \(this-&gt;error = \)e;
    }

    public function isSuccess(): bool
    {
        $this-&gt;error === null;
    }

    public function getError(): Throwable
    {
        if ($this-&gt;error === null) {
            throw new RuntimeException('No error');
        }

        return $this-&gt;error;
    }
}

class Pipeline implements Step
{
    private Step $step;

    public function __construct(Step $step)
    {
        \(this-&gt;step = \)step;
    }

    /**
     * @param Traversable&lt;int,array&gt; $source
     * @return Generator&lt;int,Result&gt;
     */
    public function run(Traversable $source): Generator
    {
        foreach (\(source as \)record) {
            \(result = new Result(\)record);
            try {
                \(this-&gt;process(\)record);
            } catch (Throwable $e) {
                \(result-&gt;withError(\)e);
            }

            yield $result;
        }
    }
    
    public function process(array $record): void
    {
        \(this-&gt;step-&gt;process(\)record);
    }
}
</code></pre>
<p>So, let's enumerate what we have done here:</p>
<ol>
<li><p>By accepting any <code>Traversable</code> that returns <code>array</code> on every iteration, we have abstracted away the source. Now, we don't care if the source is JSON, XML, or any other. We are going to iterate over a collection of arrays. It is up to the source class to fetch the corresponding records.</p>
</li>
<li><p>By creating an interface called <code>Step</code> we can now abstract away the action we want to perform in every record, and we can create implementations that will do common tasks.</p>
</li>
<li><p>By creating the <code>Result</code> object we can report whether every record was successfully processed or not, and what was the error.</p>
</li>
<li><p>By using <code>Generator</code>, we can process any data-set of any size without worrying about memory consumption.</p>
</li>
</ol>
<p>If you are thinking "Great, this is five times more lines than the previous approach and it does not even contain the code for reading JSON" you are looking at the problem from the wrong angle. The problem in the first place was not that the code was hard to grasp. In fact, anyone would understand what the previous code did. The problem was that <strong>it was not resistant to change</strong>. Making code more robust, code that isolates the things that change, by definition is going to take more lines of code. The price you pay is more lines of code, but the benefit you get is immensely superior. I would say that is a pretty good tradeoff.</p>
<p>Moreover, is not <em>always</em> true that abstraction requires more code. Designing abstractions is very similar, in a way, to search algorithms. In searching algorithms, if your list is small, you can use <code>O(n)</code> approaches and don't even worry. However, as your list grows, using a <code>O(log n)</code> approach will make a difference. In abstractions, you don't feel the benefit of it if your codebase is small, but as your use cases grow and the abstraction proves itself, it requires exponentially less code to do more things with that abstraction.</p>
<h2>Conclusion</h2>
<p>What I've given you here is really the Single Responsibility Principle. Many people believe the principle is "A class should have only one responsibility" or "A module should do only one thing". That's technically incorrect. The original wording of the principle <a href="https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html">given by Uncle Bob</a> was that "a class or module should have only one reason to <em>change</em>". By isolating the things that change, our pipeline has just one reason to change: the change in requirements. The <code>Pipeline</code> class does not change its logic if the data source changes, or if the steps change: it will always remain the same.</p>
<p>Isolate the things that change behind abstractions, so those things can change freely and leave the rest of your code untouched. That will make your code more robust, and resistant to change.</p>
]]></content:encoded></item><item><title><![CDATA[My Top 3 PHP Naming Pet Peeves]]></title><description><![CDATA[I've been writing PHP for quite a while now, but I do not write PHP the same way as when I started. In the beginning, like every developer, I just started by mimicking what other developers did: no su]]></description><link>https://blog.mnavarro.dev/my-top-3-php-naming-pet-peeves</link><guid isPermaLink="true">https://blog.mnavarro.dev/my-top-3-php-naming-pet-peeves</guid><category><![CDATA[PHP]]></category><category><![CDATA[naming]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Thu, 26 Jan 2023 09:20:53 GMT</pubDate><content:encoded><![CDATA[<p>I've been writing PHP for quite a while now, but I do not write PHP the same way as when I started. In the beginning, like every developer, I just started by mimicking what other developers did: no surprise there. But along the way, I started to question why I was doing certain things that way and realised that some of the things I did when writing PHP were completely unnecessary.</p>
<p>One of those is naming things. There are a whole lot of assumptions I made when naming stuff. Now I do things differently and have become a bit vocal about it, to the point that I'm actively pushing people to not do these things. It is not that it annoys me -- the title is just clickbait, people! -- but rather that we all should be quicker at honing the most important skill of a software engineer: to question ourselves constantly about why we do things a certain way, and to find better ways of doing them.</p>
<p>And just in case you are wondering, I have way more pet peeves than these three, but these are the ones I could think of related to naming, because:</p>
<blockquote>
<p>There are only two hard things in Computer Science: cache invalidation and naming things.</p>
<p><cite>~ Phil Karlton</cite></p>
</blockquote>
<h2>Interface Suffix</h2>
<p>This one is probably one of the ones I don't really understand, but it is so embedded into the PHP community that getting rid of it is going to be almost impossible. I'm talking about the practice of suffixing every interface definition with the word <code>Interface</code>.</p>
<p>First of all, why? It is not in any PSR or official PHP standard, nor it is explicitly endorsed by anyone I know. It is not that we suffix our classes with the word <code>Class</code> either. It is just simply done, by everyone.</p>
<p>Some people say that is a practice taken from Java, and I can see that but that does not really explain why Java people started doing it in the first place. Some argue that this is so you can easily distinguish what types are an interface, and I ask, in what context? Your IDE puts different icons on the files accordingly in the file browser. If you are looking at a class and you see <code>implements</code> next to the type, you know is an interface. And if you are looking at the FQCN in the code, a simple hover tells you what it is. I can understand the practice as valuable in days where IDEs where not a thing. But in this day an age, we have a million ways to know what types are an interface.</p>
<p>But maybe some of you don't like change, and are asking, why not? Well, a strong reason is that those are 9 extra characters that you don't need to type and that don't need to be polluting your source code. Take a look at the definition of the Serializer class of Symfony Serializer (@<a href="https://github.com/symfony/serializer/commit/1e69e2fc852463dd5262189027b9542d7a10688f">1e69e2f</a>):</p>
<pre><code class="language-php">&lt;?php

class Serializer implements SerializerInterface, ContextAwareNormalizerInterface, ContextAwareDenormalizerInterface, ContextAwareEncoderInterface, ContextAwareDecoderInterface
</code></pre>
<p>Now, take a look at the simplified definition, without suffixing:</p>
<pre><code class="language-php">&lt;?php

class Serializer implements Serializer, ContextAwareNormalizer, ContextAwareDenormalizer, ContextAwareEncoder, ContextAwareDecoder
</code></pre>
<p>Much shorter huh? We have removed 45 characters from that line, which is a ton considering that is more than half of the recommended characters per line (80) -- not that I agree with that recommendation though. And not only in this source file but on every single file that references the interface -- and interfaces are referenced a lot! -- But the bottom line is that less <em>unnecessary</em> pollution in your source code is always going to be a good thing!</p>
<p>If you are a good observer, you'll realise that my suggestion leaves the code in an incorrect state. We have a name clash. We are defining a class called <code>Serializer</code>, that implements an interface called exactly the same. You might think this is a drawback, but it is not. You see, one of the benefits of having an interface without a suffix is that now the implementations can describe better what they do. I would rename the <code>Serializer</code> class to <code>DefaultSerializer</code> or <code>MainSerializer</code> to indicate that this is sort of the class that glues the whole library together. This would be the final result:</p>
<pre><code class="language-php">&lt;?php

class DefaultSerializer implements Serializer, ContextAwareNormalizer, ContextAwareDenormalizer, ContextAwareEncoder, ContextAwareDecoder
</code></pre>
<p>Think about this: the interface is an abstract thing, and therefore it makes sense it has the purest, unsuffixed name of what it is representing or abstracting. Concrete implementations should be the ones prefixed with what kind of implementation are they providing and its usually tied to their dependencies. Here are some examples:</p>
<table><tbody><tr><td><p><strong>Interface</strong></p></td><td><p><strong>Implementations</strong></p></td></tr><tr><td><p><code>MessageQueue</code></p></td><td><p><code>RabbitMessageQueue</code>, <code>SqsMessageQueue</code>, <code>RedisMessageQueue</code>, <code>FilesystemMessageQueue</code></p></td></tr><tr><td><p><code>KeyValueStore</code></p></td><td><p><code>RedisKeyValueStore</code>, <code>NatsJetstreamKeyValueStore</code>, <code>EtcdKeyValueStore</code></p></td></tr><tr><td><p><code>IdentityProvider</code></p></td><td><p><code>PdoIdentityProvider</code>, <code>DoctrineIdentityProvider</code>, <code>OauthIdentityProvider</code></p></td></tr></tbody></table>

<p>Examples of interfaces names and implementations</p>
<p>I hope this is reason enough for you to start dumping <code>Interface</code> as a suffix for your interface names. Same goes for <code>Abstract</code> prefixing abstract classes or <code>Trait</code> suffixing traits.</p>
<h2>Naming after Patterns</h2>
<p>Another naming related. Similar to the one before, this refers to the bad practice of suffixing or prefixing class names with the name of the pattern you are implementing in that type. It fills your codebase with class names called <code>LoggerHttpTransportDecorator</code>, <code>CompositeIdentityProvider</code>, <code>IdentityProviderAdapter</code> or <code>EventDispatcherSingleton</code>. I mean, I know you know your design patterns -- as you should! -- but come on, you don't have to shove it on everyone's face! Do I need to know if that specific class is a decorator, an adapter or a singleton? Not really!</p>
<p>Don't get me wrong: you <em>must</em> know how to identify whether a particular class is implementing a certain pattern just by glancing at it. But you don't need to name them like that. It's just extra <em>unnecessary</em> noise to the source code.</p>
<p>This happens not with just the classical design patterns, but with objects describing their role, like <code>MoneyValueObject</code>, <code>RestRequestTransfer</code>, <code>CustomerDTO</code> or <code>UserEntity</code>. Just don't do it. You don't need it. The fact that a class is a DTO should have nothing to do with its name. Naming should be short and clear. If the name is ambiguous, then the namespace is there to provide context. Remember that <strong>a class name is its full name</strong>, not just the last bit after the <code>\</code>. This brings me to my next point.</p>
<h2>Superfluous Namespacing</h2>
<p><a href="https://blog.mnavarro.dev/2020/07/20/namespace-taxonomy-syndrome/">I've written about this before</a>. <strong>Namespaces' role is to prevent name collisions, not create taxonomies.</strong> Of course, because of code organisation, you will still have some degree of taxonomisation, but you should still strive to keep things short. There are two common mistakes here. One is using namespaces to describe what things inside them are, and another is abusing them by repeating words or concepts inside them.</p>
<p>The first manifests when you have a namespace called <code>Exceptions</code>, <code>Interfaces</code>, <code>Components</code>, etc. This is a very common way of organising namespaces that people use when working on a project in a framework. I'm more of the opinion that you should use namespaces to group things under the same <em>concern</em>, and not to group things under the same <em>role</em> in a codebase.</p>
<p>For instance, compare these two directory structures:</p>
<pre><code class="language-plaintext">App/
├── Controllers/
│   ├── UserController.php
│   ├── RoleController.php
│   ├── TokenController.php
│   ├── PaymentController.php
│   └── OrderController.php
├── Entities/
│   ├── User.php  
│   ├── Role.php
│   ├── Token.php
│   ├── Payment.php
│   └── Order.php
└── Exceptions/
    ├── UserNotFound.php
    ├── TokenNotFound.php
    ├── ControllerError.php
    └── PaymentError.php
</code></pre>
<pre><code class="language-plaintext">App/
├── Security/
│   ├── UserController.php
│   ├── RoleController.php
│   ├── TokenController.php
│   ├── User.php
│   ├── Role.php
│   ├── Token.php
│   ├── UserNotFound.php
│   └── TokenNotFound.php
├── Checkout/
│   ├── PaymentController.php
│   ├── OrderController.php
│   ├── Payment.php
│   ├── Order.php
│   └── PaymentError.php
└── ControllerError.php
</code></pre>
<p>The first iteration uses namespaces as a way of categorising by role. In other words, we put all the controllers in a single place, all the entities in a single place, etc. This makes it very hard to determine dependencies and is a very framework-based way of organising namespaces.</p>
<p>The second iteration is categorised by concern. We put all the stuff related to checkout together, and then all the things related to security. Things that are particular to everything, go a level under -- like the controller error. It is much easier to track dependencies here.</p>
<p>Another way of misusing namespaces is to make them too long by repeating stuff in them. Take, for instance, one of my favourite examples from the Laravel codebase: <code>Illuminate\Broadcasting\Broadcasters\Broadcaster</code>. That is a lot of repetition! This interface could very well have been named <code>Illuminate\Broadcaster</code>. You don't need all the taxonomy fluff. If a namespace repeats something, then it is superfluous. Once again you must pay attention to how you are breaking down your code.</p>
]]></content:encoded></item><item><title><![CDATA[Messaging Guarantees]]></title><description><![CDATA[The Two Generals Problem
Let’s suppose you are a general in command of a medieval army, and you find yourself in the following situation.
You must siege and capture an enemy settlement. The only way t]]></description><link>https://blog.mnavarro.dev/messaging-guarantees</link><guid isPermaLink="true">https://blog.mnavarro.dev/messaging-guarantees</guid><category><![CDATA[messaging]]></category><category><![CDATA[distributed system]]></category><category><![CDATA[TCP]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Tue, 22 Nov 2022 09:53:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680087375191/2abdd526-c7d8-4525-9a0f-e63e603956f6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>The Two Generals Problem</h2>
<p>Let’s suppose you are a general in command of a medieval army, and you find yourself in the following situation.</p>
<p>You must siege and capture an enemy settlement. The only way to do it successfully is to coordinate a simultaneous attack along with the forces of another general on the opposite side of the settlement, so you can attack from both flanks. You need to devise a way of coordinating such attack.</p>
<p>You both agree that you will send a message to your fellow general at the time of the attack. And to be sure that the messenger has not been intercepted on its way and the message has made it safe to your fellow general, he will send another message back acknowledging receipt of the first one.</p>
<p>You are about to sign off on the plan, but then your fellow general asks: “How would I know that the confirmation has arrived to you?”. He’s worried, and with good reason. This is because if the messenger carrying the confirmation is intercepted, he would find himself attacking the settlement alone with the prospect of a terrible defeat. That is not a good position to be in!</p>
<p>He proposes that you send an acknowledgement of the acknowledgement, to prevent him from attacking by himself. You are about to agree with his reasonable request, but then you realise something: “Wait a minute! What would happen if my acknowledgement is intercepted? Then you won’t do anything and I’ll be the one attacking by myself!”</p>
<p>The generals have a problem. It should be fairly obvious by now that stacking acknowledgements is not going to help anyone. This problem is impossible to solve. There is no way they can devise a mechanism by which they can coordinate <em>reliably</em> because the medium of their message is fallible.</p>
<h2>The Impossibility of Exactly-Once Delivery</h2>
<p>This story is fundamental to understanding distributed systems and their challenges. The moral of the story is that is impossible to guarantee the delivery of a message via unreliable transport, no matter the technique we use (like acknowledgements). The internet protocol is an unreliable transport, since connections can be broken, faulty or temporarily lost. Packet loss is an unavoidable consequence.</p>
<p>This has tremendous implications for our applications built on top of TCP or HTTP. For instance, sending a message to a queue can fail. How we handle this failure is crucial to our system architecture.</p>
<p>One option is to retry sending the message. The problem with retrying though is that the <em>effects</em> of the operation being retried could be applied twice or more. For example, if I publish a message to a queue but the publish fails because I didn’t receive any ACK from the message queue, what was the problem? Was my message lost trying to reach the server or was the acknowledgement of the server lost on its way to me?</p>
<p>Remember the two generals' problem? If the acknowledgement was lost on its way to me, then the queue has already processed my message. If I retry the operation, the queue could receive the same message again and the <em>effects</em> of that action could run twice — and that better not be charging a customer! There is no way for me, the producer of messages, to know for sure if the server has effectively processed my requirement or not.</p>
<h2>Message Delivery Guarantees</h2>
<p>Most people don’t try to solve this problem and are happy with offering their customers the easiest and weakest of message delivery guarantees: <strong>at-most-once delivery</strong>. This means, that you will send the request only once, but if it fails, you won’t retry. It may or may not be sent once, but you can be sure it won’t be more than once.</p>
<p>When message loss is unacceptable, exponential backoffs with retry logic are implemented. But as soon as you retry, you are embracing an <strong>at-least-once delivery</strong> guarantee. This means that you will keep trying to send this message until you receive an acknowledgement, but that might send the message more than once if an acknowledgement is lost on its way back to you, the producer.</p>
<p>Bottom line, you can either choose between <strong>at-most-once</strong> or <strong>at-least-once</strong> message delivery guarantees, but <strong>exactly-once</strong> is a technical impossibility.</p>
<p>If you have chosen to support an <strong>at-most-once</strong> guarantee, you can relax and sit in your nice home office setup in peace. If loss of messages is unacceptable for you and you need to support an <strong>at-least-once</strong> model, but don’t mind receiving duplicates of messages, then you can get away with exponential retry logic with no problem and still sit pretty. But if duplicates are not an acceptable trade-off either (ejem! payments) then you are in for some fun problem to solve.</p>
<h2>Looking at TCP: Exactly-Once Processing</h2>
<p>So, is there anything we can do to deal with these unavoidable duplicates? We should look a lower level protocols to rescue some ancient ideas to deal with this.</p>
<p>If you know about internet protocols a bit you will know that TCP is an acknowledgement-based protocol. Every packet sent by the client needs to be acknowledged by the server. This brings us back again to The Two Generals problem. What happens if an acknowledgement is not received by the client? In the case of TCP, then the client sends the same packet again.</p>
<p>But wait!? What if that acknowledgement was lost on its way back to the client and the server did receive the message? Well, simple: the server will receive a duplicate message. It will receive the same packet again.</p>
<p>So, how does TCP deals with this? We could say that — simplifying the actual inner workings of TCP — this problem is solved by using <em>state</em>: the server stores the “ids” of the packets it has seen for that connection and simply ignores and skips any duplicates.</p>
<blockquote>
<p>This is actually an oversimplification of the way TCP works and deals with deduplication and ordering. For an exact explanation, you might want to google two key concepts: the Transmission Control Block and Sliding Window on TCP.</p>
</blockquote>
<p>Looking at TCP we can actually find a solution to the exactly-once delivery impossibility. We need a way to identify the same message in the context of a retry, keep a list of the seen ids and discard the ones that have been seen already. This technique is commonly known in web services as <strong>idempotency</strong>. Some other people call it <strong>deduplication</strong>. I like to call it <strong>exactly-once processing</strong>.</p>
<p>It requires the client to “assign” a unique identifier — sometimes called the Idempotency key — to every message. But it also requires the server to “track” which ids have been processed so they can be ignored if sent twice. Using this technique is possible to process a message once and only once and avoid the effects of an operation being accidentally executed twice.</p>
<p>Of course, there must be a limited window of time the server has to store the tracked ids (since it would be wasteful and inefficient to store every possible seen id) and if you have multiple servers processing the message, it also has to be a centralised form of storage.</p>
<h2>Conclusion</h2>
<p>Distributed systems are composed of a group of processes that need coordination and whose sole way of communication is via the network. But as the network is fallible, is impossible to guarantee that a message will be delivered successfully. Understanding this problem, its tradeoffs and how to mitigate it is essential when designing and developing distributed systems.</p>
]]></content:encoded></item><item><title><![CDATA[Codebases are Pets, Not Cattle]]></title><description><![CDATA[If you have been around in Software Engineering for the last 5 years, then you have been part of the wider DevOps revolution and all the things that came with it. It is also likely you have heard one ]]></description><link>https://blog.mnavarro.dev/codebases-are-pets-not-cattle</link><guid isPermaLink="true">https://blog.mnavarro.dev/codebases-are-pets-not-cattle</guid><category><![CDATA[best practices]]></category><category><![CDATA[Devops]]></category><category><![CDATA[code]]></category><category><![CDATA[Microservices]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Fri, 11 Nov 2022 10:31:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/9UUoGaaHtNE/upload/cc6df17737b2de96bbd7f3dcacbb6172.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have been around in Software Engineering for the last 5 years, then you have been part of the wider DevOps revolution and all the things that came with it. It is also likely you have heard one of the most famous aphorisms in the DevOps culture: that you should treat your services like cattle, not pets.</p>
<p>I live in Northern Ireland, so I know a few farmers here and there. In fact, I helped John (a family friend) milk his cows at his farm in mid-Ulster a few times back in 2015 and 2017. I had so much fun doing it and I learned a lot about the process, and it helped me understand the DevOps cattle and pets metaphor in very real terms.</p>
<p>For all the purposes of maintaining the cattle on his farm, milk farmers like John treat their cows <em>in batches</em>, with no special relationship to any single one of them. They have tooling and processes in place for cleaning them, vaccinating them, milking them and breeding them, and those involve a big chunk of them at the same time. No cow gets special attention or treatment -- unless they are sick or pregnant -- but even then there is some sort of emotional detachment.</p>
<p>Think about pets now. We name them, play with them, take them on walks or holidays, feature them in our <em>insta</em> and, if you are like me, you probably speak to them as if they were a 5-year-old who speaks your language. My wife and I have such a strong bond with our cat Pua, that we brought her from Chile in the middle of a global pandemic when we moved to the UK.</p>
<p>Back to DevOps world. The metaphor means that in scaled software organizations with a bunch of microservices running there is no time to give each process the special "care" and "attention" they need. You don't deploy them manually, and if they fail you certainly do not restart them manually, and if they need maintenance you do not run the scripts and tasks needed manually. There is no time for that when you have too many services. All those things should be done automatically. Those running processes should be disposable, easily restartable and stateless, <a href="https://12factor.net/">among many other things</a>.</p>
<p>But, I'm afraid that this very much-needed shift in managing <em>services</em> has just somehow transpired to managing <em>codebases</em> when it should not be that way. You see, a service is a running process or workload in a server. A codebase is source code in the form of readable plain text. They are very different things.</p>
<p>Codebases need care. They are pets, not cattle. They need all the attention and care you can give them. You have to name them properly, care for them individually, fix them if they are broken, cure them if they are rotting, and upgrade them if they are outdated. You need to design them properly, document them well, write their lines clearly, and structure them simply. Codebases are like that high-maintenance girlfriend, and you should be that loving and caring partner to them. The compiled runtime product that comes from a codebase -- the running process -- is a whole different story: it should be disposable.</p>
<p>Of course, some of the tasks related to a <em>codebase's</em> maintenance can still be automated, but the love and tender care they need is there nonetheless. I still love my cat even though I automate her feeding twice a day with the exact amount of food she needs with <a href="https://uk.petlibro.com/products/automatic-feeder?variant=43108712382718&amp;currency=GBP&amp;utm_medium=product_sync&amp;utm_source=google&amp;utm_content=sag_organic&amp;utm_campaign=sag_organic&amp;gclid=Cj0KCQiA37KbBhDgARIsAIzce16S8gsG2uQuO09lOQyzfD8qRYUgDdhPpf_46ycd7qnRE51IuEwU1WgaAte5EALw_wcB">this amazing automatic cat feeder that I recommend everyone who has a cat to get</a>. Codebases are like that too. Although we automate their build, testing and deployment, and maybe some routines in development, every single one of them needs a slightly different CI pipeline, test suite, dependable configuration or Makefile targets.</p>
<p>I think the industry has missed this important distinction, and good things and practices like incremental refactoring, good application of software design principles, robust testing suites, flawless development experience and strategic upgrading paths are at risk of being disregarded even more than they are today. They are slowly being replaced by inflexible templated approaches and blueprints or all-invasive frameworks that try to abstract away the tedious parts or make up for the lack of design. V2 or v3 rollouts of the same service or thing are frequent in this kind of environment, because now the codebase is seen as cattle, and something quite disposable. Sooner or later an explosion of codebases is added, on top of an explosion of services. Is easy to automate managing services and workloads -- thank you K8S -- but you cannot really manage or grow codebases automatically -- at least not today. So, a growing number of codebases is a real scaling problem you don't want to have.</p>
<p>Source code is the biggest asset of a software company -- no matter how much low-code advocates rant about the contrary. We should treat our code how it deserves: with the special care of a pet, and not with the disregard for cattle. Clean code scales; you just need to invest the time and care to produce it.</p>
]]></content:encoded></item><item><title><![CDATA[Globals are bad, but!]]></title><description><![CDATA[When I started writing PHP and learning my first OOP concepts and patterns, I remember being dazzled by the singleton pattern. I used it so much! I think I fell in love with its convenience. Just make]]></description><link>https://blog.mnavarro.dev/globals-are-bad-but</link><guid isPermaLink="true">https://blog.mnavarro.dev/globals-are-bad-but</guid><category><![CDATA[PHP]]></category><category><![CDATA[oop]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Sat, 05 Nov 2022 10:44:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/nXt5HtLmlgE/upload/1d81af819937fa00b0baef273152d513.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I started writing PHP and learning my first OOP concepts and patterns, I remember being dazzled by the singleton pattern. I used it so much! I think I fell in love with its convenience. Just make something a singleton, and you can grab it and use it from anywhere you want.</p>
<p>I'm sure you know how they work already. The classical implementation is to make a static property and method called <code>instance</code>, and if the property is not null, return it. Otherwise, create the instance and store it in the property, so then you can return it.</p>
<pre><code class="language-php">&lt;?php

class Singleton
{
    private static Singleton $instance = null;

    public static function instance(): Singleton
    {
        if (self::$instance === null) {
             self::$instance = new Singleton();
        }

        return self::$instance;
    }
}
</code></pre>
<p>You can optionally make <code>__clone</code> and <code>__construct</code> private, to prevent more than one instance can exist.</p>
<h2>Because You <em>Can</em> Doesn't Mean You <em>Should</em></h2>
<p>Sometimes we developers refer to code like that as <em>globals</em>. Is a short way of saying <em>globally accessible</em>. By <em>globally</em> we mean, from anywhere in the source code. The singleton above <em>can</em> be accessed from anywhere because of its static method. Convenient, isn't it?</p>
<p>My story with singletons is like the story when you find a really cool album or band, and put it on repeat forever, every day -- yes, I do that. It is good for a while, but that sentiment quickly evaporates and suddenly you don't find it as good anymore.</p>
<p>For me, that sentiment came when I started to learn about testing, and writing my first tests. I still remember how hard it was to write my first tests because I had made everything globally accessible. It was impossible to test the controller without a real database connection, third-party API calls and a queue. I gave up pretty quickly.</p>
<p>Eventually, you realise that when something is convenient in programming, it is so at the cost of making other things harder. Singletons make access to other routines in code very convenient, at the cost of an extreme coupling that makes it unbearably hard to test your code units in isolation.</p>
<p>Be careful. Some people like to promote things like these by proclaiming them as <em>simple</em>. Don't be deceived! In engineering, is very common to see simplicity disguised as her shallow cousin: convenience.</p>
<p>After a while, I gave up using globally accessible stuff in my code and moved on to better patterns, like Dependency Injection. Just because you can globally access something from anywhere does not mean you should.</p>
<h2>Because You <em>Shouldn't</em> Doesn't Mean You <em>Won't</em></h2>
<p>But, here is the grain of salt. I do believe singletons and other kinds of <em>globals</em> have their place in a codebase. I think that place is the bootstrapping code.</p>
<p>You can call all singletons you like, as long as you pass them as arguments in the constructor for another class, for instance. In the code that bootstraps your application, you can access all kinds of <em>globals and that is fine</em> because the bootstrapping code is the code that is <strong>coupled to all the dependencies</strong> of your program. As long as those <em>globals</em> don't leak anything to the rest of the application code, you'll be perfectly fine.</p>
<p>I've found myself writing more Singletons than before because they are more convenient in bootstrapping code. As a library author, you can provide Singletons with sensible defaults for your users, while still giving them the possibility of bootstrapping their instance with custom values.</p>
<p>Overall, I think we need to get better at testing. Promoting testing everywhere will only do good to the PHP community because developers will quickly realise when they are writing hard-to-test code.</p>
]]></content:encoded></item><item><title><![CDATA[HELM vs Kustomize]]></title><description><![CDATA[Not too long after Kubernetes became popular, it became evident rather quickly that maintaining all the manifests involved in the deployment of a single application was going to be a cumbersome proces]]></description><link>https://blog.mnavarro.dev/helm-vs-kustomize</link><guid isPermaLink="true">https://blog.mnavarro.dev/helm-vs-kustomize</guid><category><![CDATA[Helm]]></category><category><![CDATA[Kustomize]]></category><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Sun, 21 Aug 2022 09:51:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Sq0L3SPWLHI/upload/67d886118d6abd4f386fea7f24885697.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Not too long after Kubernetes became popular, it became evident rather quickly that maintaining all the manifests involved in the deployment of a single application was going to be a cumbersome process. Having a different set of manifests for every environment you want to deploy to is simply unacceptable. People quickly realised that applying some DRY to the problem was very much needed.</p>
<p>That’s how HELM was born. The idea of HELM was to create highly-configurable “packages” that would contain all the dependencies of a particular application. So, if you wanted to deploy your own self-managed instance of Gitlab, the HELM chart for it would contain everything you needed: the database, the main application, the runners, the exporter, Gitaly, etc. You just needed to tweak some configuration values and that was it. Configurable and DRY Kubernetes was born.</p>
<p>HELM achieved this by making Kubernetes manifests a template (specifically, a Go template) and interpolating variables to render the actual manifests to be used by Kubernetes.</p>
<p>Quickly, we realized that there are several issues with this approach.</p>
<h2>Increased learning curve</h2>
<p>The first evident problem is that you are introducing a layer of abstraction on top of another layer of abstraction -- this is how Software works anyway. Now, you need to understand not only the something you are abstracting (in this case, k8s and manifests, which are quite full of learning already) but also the abstraction itself and its inner workings.</p>
<p>New concepts are introduced like Charts and Repositories. Now you need to learn how a chart is structured so you can build your own and then learn Golang template syntax if you don’t know it already. All these things, although not a major burden, hinder adoption by steeping the learning curve a bit.</p>
<h2>Templating limits customisation</h2>
<p>It should be fairly obvious that, in any solution to this problem that involves templating, only the values that are parametrised are the values that you can configure. Unfortunately, you can’t change the rest. Since every organisation or team has different needs, everyone needs to customise different aspects of the Chart. But again, the chart has to be parameterised for that specific thing you need to configure. In other words, if you want full control, a chart should parametrise every single possible <code>yaml</code> value, which is almost impossible and also very impractical. Suddenly, HELM charts that could have been simple K8s manifests become <a href="https://github.com/bitnami/charts/blob/master/bitnami/wordpress/templates/deployment.yaml">something unbearable to read</a>.</p>
<p>This problem above is why you have like 20 different HELM charts per application. Everyone needs to customise different things or do things slightly differently.</p>
<h2>Charts make choices for you</h2>
<p>Because every chart has to contain all the units to make an application work, and because you cannot parametrise everything, then unavoidably some choices are made for you. Some charts deploy a Postgres instance using a <code>StatefulSet</code> with the official Postgres image, but your setup needs probably a <code>PostgresCluster</code> resource coming from the great <a href="https://github.com/CrunchyData/postgres-operator">Crunchydata Postgres Operator</a>. Or maybe you have a database already available in Aurora and don’t need the chart to create one for you, but you cannot disable it.</p>
<p>Again, the impossibility to control these and other aspects of a chart is what leads to a chart explosion for the same applications. This for me is the strongest statement of the failure of HELM to solve the DRY problem Kubernetes Manifests have. It has created more complexity.</p>
<h1><a href="https://kustomize.io/">Kustomize</a>: A better alternative</h1>
<p>The Kubernetes team understood this quickly and moved to embrace a better approach natively inside <code>kubectl</code>. The <code>kustomize</code> tool proved to be simpler, more transparent and more effective at solving this problem than HELM.</p>
<p>The paradigm behind <code>kustomize</code> is that, instead of having a manifest template, we would have a normal Kubernetes manifest with some sensible defaults that we would use as <em>a base</em>, and then, in another manifest called <em>overlay</em>, we would apply operations to the base manifest to add, remove or change its values, or whole nodes of information if we so desire.</p>
<p>Kustomize does this by the use of common standards like <a href="https://datatracker.ietf.org/wg/jsonpath/about/">JSON Path</a> and <a href="https://www.rfc-editor.org/rfc/rfc6902">JSON Patch</a>.</p>
<p>This change of paradigm (towards composition) has several advantages over a templated approach.</p>
<p>First, base manifests do not need to contain every possible configuration and its parametrised form. In fact, the shorter they are, the better. Second, overlays only change and touch what is needed, which also keeps them thin. And third, overlays can be stacked one on top of the other to increase reusability.</p>
<p>Another benefit is that you don’t need another binary to use Kustomize. It is supported natively by using the <code>-k</code> flag on <code>kubectl apply</code> or the <code>kustomize</code> subcommand in <code>kubectl</code>.</p>
<h2>Kustomize drawbacks</h2>
<p>Not all that shines is gold. There are still some drawbacks to this approach, as with everything in engineering.</p>
<p>For starters, you need to learn how Kustomize reads your <code>kustomization.yml</code> files placed in your manifests, but also learn how JSON-Path and JSON-Patch work. So there is a cognitive load that increases the learning curve.</p>
<p>Having said that, this is much easier to make sense of than HELM. JSON Path is a very simple spec, as Json Patch is too -- you can learn both in less than a day. Also, only engineers involved in customisation need to know the advanced stuff; the application engineers can write their Kubernetes manifests as they see fit aided by the Kubernetes documentation. This will be overridden by the CD tool using Kustomize. This closes the gap between Development &amp; Operations (SRE), furthering the DevOps culture across the organisation.</p>
<h1>Final Thoughts</h1>
<p>I greatly encourage you to give it a go, especially if you have a HomeLab Kubernetes cluster. I recently ported all stuff in my cluster from Helm to Kustomize and I’m enjoying how much simpler my cluster git repository is.</p>
]]></content:encoded></item><item><title><![CDATA[Considerations before jumping into Microservices]]></title><description><![CDATA[Disclaimer: A few years ago I wrote this piece. It came out very passionately then due to frustrations experienced in a microservices project. I have matured and grown since then, and in many ways, th]]></description><link>https://blog.mnavarro.dev/considerations-before-jumping-into-microservices</link><guid isPermaLink="true">https://blog.mnavarro.dev/considerations-before-jumping-into-microservices</guid><category><![CDATA[Microservices]]></category><category><![CDATA[Monoliths]]></category><category><![CDATA[System Architecture]]></category><category><![CDATA[System Design]]></category><dc:creator><![CDATA[Matías Navarro-Carter]]></dc:creator><pubDate>Thu, 05 May 2022 10:06:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ug0gPPYvG1M/upload/5ef85b5216105f4e11fe4f35f14fef71.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Disclaimer: A few years ago I wrote <a href="https://www.notion.so/Going-back-to-the-monolith-well-bb66882fcd3b4810932882ffa8b15e44">this piece</a>. It came out very passionately then due to frustrations experienced in a microservices project. I have matured and grown since then, and in many ways, this article is a more nuanced refinement of those ideas and an attempt to correct my misconceptions at the time.</p>
</blockquote>
<h2>Knowing the Monolith</h2>
<p>I think before I say anything about this topic, a proper definition of the concept of a <em>monolith</em> is needed. A <em>monolith</em> is usually defined as a piece of software (usually in a single codebase) that has grown so complex and has accumulated so much technical debt over the years that now is extremely hard to change, hard to understand and therefore easy to break. Developers dread the day they have to make a change or implement a new feature, and when they do, unexpected things happen all over the place. The system is so big, so complex and so glued together, that no one knows where to look to fix the issues. This in turn leads to poor development times, a lot of “I’m sorry that can’t be done” and tons of burned-out engineers due to the pressure for delivering and the frustrations and fear of unexpected issues. In terms of the business, the client’s trust is harmed because of the many issues and poor response times.</p>
<p>There are mainly three major things characteristic of monoliths, and their causes are usually related to violations of best practices in OOP.</p>
<p>Monoliths are <strong>rigid</strong>, which means, they are hard to change. The reason why they are hard to change is because of coupling. Usually, this manifests itself in not abstracting away the details that change (a violation of the Dependency Inversion principle), sticking all the logic in a single place (a violation of the Single Responsibility principle), or because almost every modification requires changing existing code instead of adding a new one (a violation of the Open-Closed principle).</p>
<p>You can get a measure of the rigidness of the system using automated tools that perform code analysis, like cyclomatic complexity, code duplication, test coverage, number of lines per class or module, file churning, ABC, etc. But these metrics, even when you have them, need proper interpretation by a human, preferably a consultant that can analyze the codebase for things that cannot be picked up by code analysis tools, like SOLID violations or lack of use/misuse of design patterns. Some of these are also measures of our next point.</p>
<p>Monoliths are <strong>complex</strong>, which means, they are hard to understand. It might be due to their size, or maybe because information about the system has been lost (lack of documentation), or maybe because the code is written in a very dirty way. Sometimes, in the life of a system, so-called shortcuts are done to overcome a design limitation, and the people that implemented them are long gone, and their knowledge of the system shortcut is gone with them. Maybe the system is complex because it does things unconventionally. For instance, I have seen many systems myself that, when you change something (say, add a field to a payload) you need to do something else somewhere else on the system so that the change can behave properly. The problem is you need to <em>know</em> that.</p>
<p>There are many, many reasons for complexity. One of the best ways to measure complexity is how long would take a new engineer to get the system up and running in their development machine, get a grasp of it, understand where the critical parts are and be able to make meaningful changes without much aid from anyone else. Of course, that is also a measure impacted by the engineer’s experience. There is also, as I mentioned before, automated tool analysis.</p>
<p>Monoliths are <strong>fragile</strong>, which means, they are easy to break. Due to all the reasons mentioned above, the system breaks pretty easily, and for the weirdest of reasons. Even skilled engineers fail into their traps and introduce unexpected and accidental side-effects or bugs. Again, this is probably due to the inherent coupling of the components of the system, plus its complexity of it.</p>
<p>You can measure fragility by getting a sense of how afraid are developers, even experienced ones, of making any change to the system. Also, by how many regressions the release of a new functionality causes. By using static analysis tools you can pick potential sources of breakage due to typing too.</p>
<p>Monoliths are a sad tragedy to be in. We wanted a <strong>flexible</strong>, <strong>simple</strong> and <strong>robust</strong> system, but somehow we ended up with a <strong>rigid</strong>, <strong>complex</strong> and <strong>fragile</strong> one.</p>
<h2>The Principal Architect™</h2>
<p>So, we have enumerated the issues with monoliths. They are <strong>rigid</strong>, <strong>complex</strong> and <strong>fragile</strong>. Our organisation is struggling to deliver and customer confidence in our capabilities of delivering a quality product is decreasing dramatically.</p>
<p>But, fear not! We have identified our problems to solve! So the Principal Architect at the company says:</p>
<blockquote>
<p>Let’s come up with a strategy to incrementally refactor our monolith to make it more <strong>flexible</strong>, <strong>simple</strong> and <strong>robust</strong>.</p>
<p><cite>~ The Wise Principal Architect 🦫</cite></p>
</blockquote>
<p>A good approach. Not so fast and requires skilled engineers in the art of refactoring plus the ones who know the system well. But it can be done for sure. Or maybe it can’t; maybe you are past the point of refactoring (in terms of cost) or you don’t have “surgeon engineers” at your disposal, so maybe they say:</p>
<blockquote>
<p>Let’s take all the knowledge we have so far and build a second version of the system that is more <strong>flexible</strong>, <strong>simple</strong> and <strong>robust</strong>.</p>
<p><cite>~ The Bold Principal Architect 🦅</cite></p>
</blockquote>
<p>A bolder approach, but faster than the former. You can do this with mid-skilled engineers under the supervision of the ones who know the system well. You need to put extra effort into not repeating the mistakes of the first system though, otherwise, your effort is pure waste.</p>
<p>However, you know they don’t say that, don’t you? That’s why you are reading this blog post! What they say is:</p>
<blockquote>
<p>It is time for us to split our monolith into microservices like Netflix or others are doing!</p>
<p><cite>~ The Foolish Principal Architect 🐥</cite></p>
</blockquote>
<p>If you are there when that happens...</p>
<img src="https://media.giphy.com/media/3o7ZeEZUzRjyvWuuIg/giphy.gif" alt="Run Monty Python style!" style="display:block;margin:0 auto" />

<p>On a more serious note, I think this comes to pass because we have a misconception of what microservices are and therefore, we are unable to see the real problem.</p>
<h2>Misconceptions on Microservices</h2>
<p>There are a lot of misconceptions about microservices. They are usually hard to spot because there are some elements of truth in them (hence the name, misconceptions).</p>
<p>One of the most famous ones is that they are a way of “splitting the monolith”. This is quite misleading because suggests the main problem with a monolith is its size. If you add that to the fact of how the pattern is named (<em>micro</em>-services) then you understand the cause of confusion. People bring the reasonings of <a href="https://medium.com/@SoftwareDevelopmentCommunity/what-is-service-oriented-architecture-fa894d11a7ec">SOA</a> and apply them to this problem. Thus, the following way of thinking becomes the common argument for implementing this pattern:</p>
<blockquote>
<p>If we split this big thing into smaller chunks, then it would be easier to manage.</p>
<p><cite>~ An Engineer. </cite> <em><cite>Famous Last Words.</cite></em> <cite> Circa 2018.</cite></p>
</blockquote>
<p>This looks reasonable, and it is indeed (in the appropriate contexts). This is the principle of modularity: separating things into smaller components that then can be combined to form a larger whole. The idea is that at any time you can pull out one component and replace it with another without breaking the whole system. And it is also easier to make sense of smaller pieces than a big ones, right? So far, so good.</p>
<p>In pre-microservices SOA, this separation usually fell into the runtime space. This means these modules interacted between them in the safe realm of random access memory. Changes would be made in a single place (the application code) and then shipped in a single executable without major hassle. Adapting to changes in the public API of one module usually involved correcting the consuming services in the same PR. This is one of the victories of object-oriented programming.</p>
<p>However, as we will see further, there is a whole range of complexity introduced when we apply this principle to services running as separate applications communicating over TCP networks. I’ll get there in the next section. I want to stress something else first.</p>
<p>Our long introduction on what a monolith is had a very special purpose that will come to light now. If you look again at the reasoning justifying the splitting of the monolith into smaller services, hopefully, you will realise that fundamental problems somehow escaped the reasoning backing the proposed solution. This is extremely important.</p>
<p>True, size might be a factor in the complexity of a system, but it is not the most important factor, and certainly not the only one. It is not just complexity due to size, but rather any <strong>complexity</strong>, anything that causes <strong>rigidness</strong>, and anything that makes things <strong>fragile</strong>. If you have <strong>complexity</strong>, <strong>fragility</strong> and <strong>rigidness</strong>, it does not matter if you have one big large service or many small ones. You will suffer anyways.</p>
<h2>“Estimate the Cost. Sit down and consider.”</h2>
<p>Actually, no, I lied. It does matter. Is better to have a monolith than a distributed mess. Here is the big takeaway of this article: <strong>if you implement microservices for the wrong reason and if you are not ready to tackle the challenges that come with them, then you will be in a worse place than when you started</strong>.</p>
<p>As usual, the scriptures bring untimely wisdom in this matter (and in any other matter regarding life really). Jesus is trying to explain to people that following him is very demanding and that they should consider whether they can do it or not before blindly jumping on the bandwagon (let’s remember these are the popular times of Jesus’ ministry). He uses two wonderful metaphors. Here is what he says:</p>
<blockquote>
<p>Suppose one of you wants to build a tower. Won’t you first sit down and <strong>estimate the cost</strong> to see if you have enough money to complete it? For if you lay the foundation and are not able to finish it, everyone who sees it will ridicule you, saying, ‘This person began to build and wasn’t able to finish.’ Or suppose a king is about to go to war against another king. Won’t he first <strong>sit down and consider</strong> whether he is able with ten thousand men to oppose the one coming against him with twenty thousand? If he is not able, he will send a delegation while the other is still a long way off and will ask for terms of peace. In the same way, those of you who do not give up everything you have cannot be my disciples.</p>
<p><cite>~ The Holy Bible. Luke 14:28-33 (emphasis mine)</cite></p>
</blockquote>
<p>We are not builders nor kings, and maybe you do not follow Jesus, but surely we both can relate to this. Prudence and consideration is a scarce gift in a world that encourages you to take any opportunity you have in front of you.</p>
<p>The first thing you should think is, do you have the resources to maintain all those microservices? Is hard enough to maintain one service, let alone fifty. You need to have the workforce in place for that effort. Otherwise, don’t do it.</p>
<p>Of course, maintaining involves many things. For instance, each part of the development lifecycle needs to be properly automated. You cannot test all of your microservices manually. You need to rely on automated testing and quality checking (Continuous Integration) and try to also automate the release process (Continuous Deployment). If you don’t do that, better not to jump in the effort. You will be crushed under the weight of manual deployment and testing work. You can’t treat your services like pets anymore, giving them all the care and attention they need individually: now they should be treated as cattle.</p>
<p>Some companies develop their own semi-automated release process. It is automated up until the last mile after which there is some manual work to be done for release. This is another challenge: making sure you can come up with a process that is simple to learn and properly documented, so it can be quickly grasped by any engineer in the company. If you fail to do that, there will be trouble.</p>
<p>If keeping one application up to date with the latest framework, language version, or standard is hard enough, imagine doing that for thirty, or forty. It is not fun. True, there are things like dependable or language-specific tooling to upgrade from one version to another, but yet is another automated process you have to implement, maintain, document and ensure that runs smoothly.</p>
<p>Things get tricky if you implement custom, in-house tooling, frameworks or libraries to accelerate the development effort. The reason why you have to accelerate it though is because you brought that extra work when you decided to bring microservices in. Every new project implies a setup cost that you don’t have to pay if the project is already there and the tooling is in place. No mention, you have to keep that tooling nice, sharp and well documented and make sure every project is using an updated version. And don’t dare to break BC!</p>
<p>Dealing with the data dichotomy is also something a lot of teams don’t consider. When you had the monolith, it was all there in the same database, so it was easy to share data between services. But now (hopefully) every service has its own database and a very narrow REST interface. But they still have to share data. How do we do that? If you just create a network of interconnected REST calls, you will end up with a very complex system, and changes in one place could and will break stuff in other places. Services will be coupled together and you will end up with a distributed monolith. Sure, you can implement observability systems to detect when things break, but that is half of the problem. The problem is that now the other affected service is in another project, in another repo (maybe in another language!), that you need to clone, set up and understand before you can make a fix there. In the monolith, at least, it was in the same source code.</p>
<p>Maybe you did your homework and decided you will communicate your microservices using an event-driven approach, but that has also challenges and pitfalls of its own. Tracing where an event goes and what services reacted to it is hard, and it requires a particular set of skills and engineers with the right experience to develop event-driven systems. They are not easy to find, and if you do find them, they are not cheap to hire.</p>
<img src="https://media.giphy.com/media/UpWDPgxcHiR1e/giphy.gif" alt="You need to hire like 20 Liam Nesons." style="display:block;margin:0 auto" />

<p>The ability now of going polyglot is another factor to consider. Now you can have 2, 3 or even 4 languages with a presence in your company. There is a constant tooling and language war over which one should we use. Tooling has to be built in 2, 3 or 4 different languages. More sooner than later you will end up feeling the huge maintenance burden they cause.</p>
<p>If the technical challenges are big, the people's challenges are monumental. Suddenly your company has hired twice the people to be able to cope with the extra amount of work you have brought into yourself. New people, with new experiences and new ideas, come to the table. Sometimes they could bring change just for the sake of changing something. For instance, someone had a bad experience with GraphQL on their previous job, or someone likes Postgres over MySQL or Golang over PHP (imagine that! 😜). More people means really, more diversity of experiences and opinions. And while that is a good thing, you still need to be able to filter what makes sense from what is just pure noise.</p>
<p>To keep this under control, you implement a process heavy-culture that focuses a lot on uniformity and consistency, so your company does not become the wild west. Although you gain in that area, process overloading brings problems of its own: new engineers have to learn your processes, and they might be not the best choice sometimes or fall outdated pretty quickly. Also, processes need to be properly documented and simple. Otherwise, they will not be followed. More extra work!</p>
<p>Maybe your monolith was maintained by one or two teams, but now you have 7 teams working on your suite of microservices. Communication is suddenly more important than ever, and it is even more if your services are coupled with direct request-response calls. One team’s work can break the other’s, or one team can be blocked waiting for the implementation of another feature by another team. Sitting time is great for engineers: they can read Reddit, or Twitter, or maybe write long boring articles like this one. It is not great for your company though: you are losing money.</p>
<p>Honestly, I could go on and on with more and more things you need to consider before you make this move, and I still will have the stuff to say. There is abundant literature and media out there that deals with the pitfalls of microservices, so make sure to take a look at it! I leave you with my personal favourite here:</p>
<p><a class="embed-card" href="https://www.youtube.com/watch?v=r8mtXJh3hzM">https://www.youtube.com/watch?v=r8mtXJh3hzM</a></p>

<h2>Final words</h2>
<p>Maybe you read all this and say: “but all those things are solvable!” And yes, you are correct, they are! Every single one of those problems has a solution and can be addressed effectively. But if you are asking that I think you might be missing the point. The question is not whether they are solvable. The question is, do you need to solve them? Do you need to bring all that complexity in to have a successful business? Do you need to add another suite of technical problems to solve on top of your business problems? Do you <em>really</em> need microservices, or do you only want them?</p>
<p>Don’t get me wrong. The benefits of microservices are great. But you only reap the benefits if they are correctly implemented and you have what it takes to do so. If not, again, you could end up worse than before you started.</p>
<p>The bottom line is to estimate the cost, sit down and consider, and formulate a plan for your transition (if you <em>really</em> need to transition!). If you fail to plan, you plan to fail.</p>
]]></content:encoded></item></channel></rss>