<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator>
  <link href="https://mariomelo.com/en/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://mariomelo.com/en/" rel="alternate" type="text/html" />
  <updated>2026-04-29T14:53:38+00:00</updated>
  <id>https://mariomelo.com/en/feed.xml</id>
  <title type="html">Mario Melo</title>
  <subtitle>Software Developer &amp; Scrum Trainer</subtitle>

  
  
  <entry xml:lang="en">
    <title type="html">Machine vs Learning</title>
    <link href="https://mariomelo.com/en/machine-vs-learning" rel="alternate" type="text/html" title="Machine vs Learning" />
    <published>2026-04-27T00:00:00+00:00</published>
    <updated>2026-04-27T00:00:00+00:00</updated>
    <id>https://mariomelo.com/machine-vs-learning</id>
    <content type="html" xml:base="https://mariomelo.com/machine-vs-learning">
      <![CDATA[<p>A couple years ago I had an interesting conversation with a good friend of mine about… the meaning of life. Yeah, cliché, I get it. At the end of the day we came to the conclusion that it’s a very personal concept, and I left that conversation ruminating what was my own definition of meaning.</p>

<p>I noticed that everyday I learned something new was a good day for me. Any day I felt I got better at something had a special meaning to me: learning how to play a new song, learning a new chess opening, experimenting with photography, etc. At that point I felt like learning and sharing what I learned with others was something meaningful, and maybe the meaning of my life.</p>

<p>Do you know who agrees with me? <del>Neil deGrasse Tyson</del> a random 6 years old kid. 10 years ago the kid asked Neil about the meaning of life, and if this kid followed the advice he received I bet he’s very smart 16 years old today.</p>

<p><iframe src="https://www.youtube.com/embed/q_za_b6haXQ" loading="lazy" frameborder="0" allowfullscreen=""></iframe></p>

<h2 id="to-learn-or-not-to-learn-that-is-the-question">To learn or not to learn, that is the question</h2>

<p>Do you know who else likes to learn? The Machine.</p>

<p>Machine Learning is not really a new concept. I remember studying it in college and even taking a course by Andrew Ng around 2013 when I was trying to come up with a way to introduce a classification algorithm in a product my company was creating.</p>

<p>But we never had enough <del>stolen</del> data or computational availability to make something like the LLM’s we have nowadays, so the models we created back then were domain-specific and could never do what the LLM’s do today. We learned a lot while exploring the concepts, and even though the results weren’t astonishing it made us geeks quite happy.</p>

<p>What bothers me with the current scenario is that learning is losing meaning for some people because they see no point in spending their time learning a craft just to be outperformed by an LLM in a couple of seconds.</p>

<p>For example: I like to draw all images I use in this blog. It takes time, yes. But as I learned from my shrink after about 5 years of therapy: <strong>You don’t need to be productive at every moment, Mario!</strong></p>

<p><em>Why would you write code if the LLM can write it 1000x faster?</em></p>

<p>Well… Why would a <a href="https://www.youtube.com/watch?v=RVGkyWPUz1k">79 years old Drauzio Varela run a marathon</a>? He took almost 5 hours to cover that distance! Had he taken an Uber he would achieve the destination in 30 minutes! He was able to do that because he trained hard since he was 50, and during that journey his muscles, his heart and his brain learned how to endure such a strenuous effort.</p>

<p>My point is: There’s value in the journey, and learning is always a journey.</p>

<h2 id="creating-vs-reacting">Creating vs Reacting</h2>

<p>During the Regional Scrum Gathering South Africa, <a href="https://www.linkedin.com/in/chris-garvey-a988203b/">Chris Garvey</a> made a fun wordplay with the words <strong>CREATING</strong> and <strong>REACTING</strong>, and it really fit the theme of this post. He used the same letters to create two different words, and these words represent two very different ways we can work with LLMs. After all, how much can you learn when you’re just reacting to the tsunami of content generated by LLM’s nowadays? Can you use LLM’s to actually develop a craft and learn as you move forward?</p>

<p>Basically, I see two different approaches when working with an LLM:</p>

<p>1- <em>Can you write a text for me?</em> Fast. Potentially no learning involved.</p>

<p>2- <em>Hey, I wrote that. Can you give me some feedback?</em> Slow. Potentially some learning involved.</p>

<p>I use the second. I write my posts, and that gives me an incredible leverage while using an LLM to provide feedback about what I wrote. For one: If the LLM provides a feedback that doesn’t make sense, I ignore it. Or question it.</p>

<p>Besides that, I have a Claude project with all my blog posts and a <code class="language-plaintext highlighter-rouge">values.txt</code> file where I state my personal mission (the same content you can read on my <a href="https://mariomelo.com/en/about">About Page</a>). Whenever I write a new post, I ask it to:</p>

<ul>
  <li>Hold myself accountable to my values</li>
  <li>Find meaningful connections between the current post and previous posts I wrote</li>
  <li>Find typos and help me to improve my english vocabulary</li>
  <li>Check people I mentioned and suggest diverse people so I can burst my bubble and do my part in making the IT world more heterogenous.</li>
</ul>

<p>I can’t tell you how much I learned by doing that. I found many people outside the AI echo-chamber that is LinkedIn, and I got a book recommendation that changed the way I feel and relate to LLM’s in general: “<strong>The Empire of AI</strong>” by <a href="https://www.linkedin.com/in/karendhao/">Karen Hao.</a> It hits hard, and even though I knew some of the problematics behind the whole AI ecosystem the book shed light to other impacts I was previously oblivious to. In its later chapters it also showed how LLM’s and SLM’s can be created and used in a more conscious way and produce real benefits to the humanity as a whole.</p>

<p>Not because the final posts are better written (I can’t even say if they are), but because the <strong>journey</strong> of writing started making me learn more. And the same idea can be applied to programming, or drawing or whatever you find pleasure in doing, as long as you keep <strong>creating</strong> instead of just <strong>reacting</strong> to what the LLM created for you.</p>

<p>I still think that learning gives meaning to my life, and I try to do that as much as I can. It’s harder now, with all the AI noise around us, and still… not only it’s still possible to learn, but we can consciously choose to do so when we inevitably interact with the LLM’s in our daily lives. <strong>Creating</strong> is still a choice we can make, and <strong>learning</strong> is the outcome we might get out of it.</p>

<p>Most people (myself included) are learning how to deal with AI in productive ways. But notice that this is a lesson that comes with a dependency: take the LLM away, and you don’t have a valuable skill. And guess what? LLMs aren’t free. You can use them to learn how to work without them, to burst your bubble.</p>

<p>That’s what I’m trying to do: exploration. Learning for the sake of learning. I’m trying to create more, and react less.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Building" />
    
    <category term="Learning" />
    
    <summary type="html">A couple years ago I had an interesting conversation with a good friend of mine about... the meaning of life. Yeah, cliché, I get it.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Why I left Substack and what are the alternatives?</title>
    <link href="https://mariomelo.com/en/why-i-left-substack" rel="alternate" type="text/html" title="Why I left Substack and what are the alternatives?" />
    <published>2026-02-13T00:00:00+00:00</published>
    <updated>2026-02-13T00:00:00+00:00</updated>
    <id>https://mariomelo.com/why-i-left-substack</id>
    <content type="html" xml:base="https://mariomelo.com/why-i-left-substack">
      <![CDATA[<p>Last year, I tried to commit to writing more, and I did reasonably well until mid-year. I chose Substack as my platform, and I liked the idea of how it connected writers to readers.</p>

<p>But then came <a href="https://en.wikipedia.org/wiki/Enshittification"><em>enshittification</em></a>.</p>

<h2 id="metrics-always-metrics">Metrics, always metrics</h2>

<p>Substack is a platform where some authors release their content for free, while others charge for more premium pieces. So, what becomes relevant for writers?</p>

<ul>
  <li>Number of views</li>
  <li>Number of mentions</li>
  <li>Number of subscribers</li>
  <li>Number of paid subscribers</li>
</ul>

<p>And that’s all fine, perfectly normal. There’s a lot of good content there worth paying for, and many people competent enough to make a living from this model.</p>

<p>The problem isn’t <del>all</del> the authors, but what the platform does to try to make these metrics attractive enough to keep authors there and attract new writers. Over time, Substack added:</p>

<ul>
  <li>A Twitter-like feature</li>
  <li>Popups constantly asking readers to subscribe to the newsletter</li>
  <li>A default option to subscribe to <strong>ALL</strong> substacks that an author recommends when subscribing to their newsletter</li>
</ul>

<p>Reading a post on Substack became an exercise in patience, and I started feeling bad about making people who dedicate some of their time to read what I write go through that. So my desire to write there kept diminishing.</p>

<h2 id="where-i-drew-the-line">Where I drew the line</h2>

<p>As if all that wasn’t enough, the metrics made completely despicable newsletters become interesting for the business because they generate revenue for the company.</p>

<p>And that includes <a href="https://arstechnica.com/tech-policy/2025/07/substacks-nazi-problem-wont-go-away-after-push-notification-apology">Nazi newsletters</a>.</p>

<p>That’s when leaving Substack stopped being an option and became a necessity for me.</p>

<h2 id="where-did-i-go-and-where-can-you-go">Where did I go and where can you go?</h2>

<p>If sending newsletters is super important to you, <a href="https://ghost.org">Ghost</a> is the best option. It’s open-source, easy to set up, and quite lightweight. Many people have been making this transition, and in terms of features, it’s the closest to Substack.</p>

<p>If you just want to write and images aren’t very important to you, you can use <a href="https://writefreely.org">WriteFreely</a>. Since it was made in Go, it’s quite lightweight (in my server test, it consumed only about 50MB of RAM!). The writing experience is pleasant and to the point. Interestingly, WriteFreely was developed as an alternative to Medium because its founder got tired of Medium’s enshittification.</p>

<p>If you want something free, with a high level of customization and full ownership of your content, the best thing to do is use a static site generator like <a href="https://jekyllrb.com">Jekyll</a>, <a href="https://gohugo.io">Hugo</a>, or <a href="https://astro.build">Astro</a>. This blog was made with Jekyll, which is built in Ruby and has been around longer, and I ended up going that route because I had already acquired a theme that fit what I had imagined for my site. Hugo is a more modern option, and probably the best choice here, especially if you plan to write in more than one language.</p>

<p>Another advantage of static site generators is that you can host them for free on GitHub Pages, for example. You don’t even need to pay for a server.</p>

<p>If you want something to read, I strongly suggest using an RSS Reader, which is nothing more than an app where you add the blogs you like to read and it notifies you about new posts without cluttering your email inbox. RSS is also a more <strong>conscious</strong> form of reading: you need to choose what you want to read and follow, and no algorithm tries to push anything else on you.</p>

<p>Currently, the software/services I use are:</p>

<ul>
  <li><a href="https://www.scaleway.com/en/">Scaleway</a>, to host my site.</li>
  <li><a href="https://typora.io">Typora</a>, to write posts.</li>
  <li><a href="https://plausible.io">Plausible</a>, self-hosted. To collect metrics while respecting your privacy (no Google Analytics here).</li>
  <li><a href="https://procreate.com">Procreate</a>, to create the images I use on the blog</li>
  <li><a href="https://vivaldi.com">Vivaldi</a>, a browser that also has an RSS reader</li>
</ul>

<h2 id="but-what-about-the-newsletter">But… what about the newsletter?</h2>

<p>Well, for now, it doesn’t exist, but I might create one in the future. I sincerely thank everyone who subscribed to the newsletter on Substack, and I hope you’ll continue following what I write here.</p>

]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Tools" />
    
    <category term="Degoogle" />
    
    <summary type="html">I haven&apos;t written in a while, and there&apos;s a reason for that: I was feeling discouraged about continuing to publish on Substack.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Is the scrum expansion pack valuable?</title>
    <link href="https://mariomelo.com/en/is-the-scrum-expansion-pack-valuable" rel="alternate" type="text/html" title="Is the scrum expansion pack valuable?" />
    <published>2025-07-28T17:00:36+00:00</published>
    <updated>2025-07-28T17:00:36+00:00</updated>
    <id>https://mariomelo.com/is-the-scrum-expansion-pack-valuable</id>
    <content type="html" xml:base="https://mariomelo.com/is-the-scrum-expansion-pack-valuable">
      <![CDATA[<p>So, last month Jeff Sutherland and Co published an expansion pack to the Scrum Framework (I’ll call it SGEP for short). And truth to be told, it kinda flopped. We had about half a week of LinkedIn posts (mostly negative reviews) and it was over.</p>

<p>I didn’t want to write anything superficial about it, so I tried to read it carefully, with low expectations, and made some notes along the way.</p>

<h1 id="it-isnt-flawless">It isn’t flawless…</h1>

<p>Scrum is a framework and therefore is incomplete by nature. It gives us the task to complete it with practices, techniques and tools, and that’s the best part of the Scrum Framework in my opinion.</p>

<p>When I first heard about the expansion pack, I feared it would fill in the gaps and make the entire thing more prescriptive, and I think most people shared the same feeling. The authors managed to avoid that problem quite well, however, there were other problems I found.</p>

<h2 id="it-isnt-an-expansion-pack">It isn’t an expansion pack</h2>

<p>Instead of just adding new information, the authors also changed some original concepts (ex: reverting to the use of the word <strong>roles</strong> instead of <strong>accountabilities</strong>).</p>

<p>It also says that the Product Backlog Refinement might be an event, which I really don’t appreciate since in my experience this kind of language fosters a mechanical behavior.</p>

<p>It’s not a single document. As the authors state at the very beginning:</p>

<p><em>“This document is a collection of independent works. Each section retains its original license or copyright status, as indicated.”</em></p>

<p>So the reading is a road full of bumps, and sometimes repetitive.</p>

<p>Other than that, I’d say it’s pretty much harmless.</p>

<h1 id="it-actually-might-help-those-struggling-with-scrum">It actually might help those struggling with Scrum</h1>

<p>I’ve been teaching software development and Scrum since 2013, and I dare to say that a good deal of the questions people ask me during training sessions can be answered by the expansion pack.</p>

<p>And most of the time the SGEP managed to do that by expanding on the <strong>WHY</strong> of things, with a huge focus on <strong>empiricism</strong>.</p>

<h2 id="more-words-make-it-easier-to-understand">More words make it easier to understand</h2>

<p>Let me give you one concrete example: the <strong>Sprint Review</strong>. The original Scrum Guide is somewhat cryptic when it says:</p>

<blockquote>
  <p>The purpose of the Sprint Review is to inspect the outcome of the Sprint and determine future adaptations</p>

  <p><cite> Scrum Guide, 2020</cite></p>
</blockquote>

<p>It also says that <em>The Product Backlog <strong>may also be adjusted</strong> to meet new opportunities.</em></p>

<p>In my classes I often take some time to discuss that: we need to determine future adaptations, which means changing the Product Backlog somehow. Therefore, a Sprint Review that doesn’t change the Product Backlog is something that should cause some reflection. Also, if the Sprint Review is a mandatory event, it means that the Scrum Team is not passively open to change the Product Backlog: <strong>they are actively searching for these changes.</strong></p>

<p>The SGEP uses more words to describe that:</p>

<p>“<em>The Product Backlog (the what)<strong>IS</strong> adapted</em>” - Not “<em>may also be adjusted</em>”, but a strong “<strong>IS”.</strong></p>

<p>This is the kind of difference that matters to me. Reinforcing that Scrum is about learning through experimentation so we can use fresh information to develop stuff.</p>

<h2 id="focus-on-empiricism">Focus on Empiricism</h2>

<p>The main problem most people have with Scrum, sometimes even without noticing it, is that they use the framework believing it will increase development speed. That often puts Product Owner and Developers in confrontation instead of collaboration. This problem is so common that the last Scrum Guide update change the term “<em>Development Team</em>” to “<em>Developers</em>”, and the explanation on why they did that was:</p>

<blockquote>
  <p>The goal was to eliminate the concept of a separate team within a team that has led to “proxy” or “us and them” behavior between the PO and Dev Team.</p>

  <p>There is now just one Scrum Team focused on the same objective, with three different sets of accountabilities: PO, SM, and Developers.</p>

  <p><cite><a href="https://scrumguides.org/revisions.html">- Scrum Guide 2020 Revisions</a></cite></p>
</blockquote>

<p>Don’t get me wrong: I do like this change. But for beginners or even people who have been using the Scrum Framework in a dysfunctional way for a long time that’s not going to solve any problems. I mean, neither does the SGEP, but at least I think it did a better job at trying to achieve that.</p>

<p>For example, the SGEP:</p>

<ul>
  <li>
    <p>Clearly states that being a feature-factory or a discovery factory is not desirable</p>
  </li>
  <li>
    <p>Establishes that the Product Owner needs to <strong>effectively communicate outcomes</strong></p>
  </li>
  <li>
    <p>The Product becomes an artifact with outcome based metrics</p>
  </li>
</ul>

<p>The SGEP also creates the <strong>Definition of Outcome Done</strong>, and I have mixed feelings about that. On one hand it adds yet another piece to the puzzle and makes the Scrum framework more prescriptive, but in the other hand it might be specially important for those beginning or struggling with Scrum.</p>

<p>Talking about that, the SGEP also provides some valuable insights for those starting or struggling with their job as Scrum Masters.</p>

<h2 id="provides-better-directions-to-scrum-masters">Provides better directions to Scrum Masters</h2>

<p>The original Scrum Guide describes the Scrum Master in half a page. And if you have a good deal of experience with the framework that’s more than enough.</p>

<p>The SGEP however gets more into the specifics, but without limiting too much of your work. It states for example, that <strong>the Sprint Backlog should have enough work to get started, e.g., start with one or two Product Backlog Items toward the Sprint Goal</strong>. And you can read this sentence as: “there’s no Definition of Ready”.</p>

<p>Another example is the Product Backlog: while the original guide states that the Scrum Master must <em><strong>find techniques for effective Product Goal definition and Product Backlog management</strong></em>, the SGEP adds some valuable information on top of that, such as: <em><strong>A smaller Product Backlog often provides more Transparency</strong></em> or even the suggestion of using an <em><strong>Outcome Criteria</strong></em> for Product Backlog Items.</p>

<p>Then again, I know these are old news for some. Yet it makes obvious some of the things people often struggle to learn.</p>

<h2 id="so-is-it-valuable">So, is it valuable?</h2>

<p>It can be. But not for everyone. But reading it is a good exercise anyway, so go for it. The focus on empiricism is what made me like it, and it’s an <strong>expansion pack</strong>, which means… it’s optional anyways. You can also pick some of the ideas and apply them if you don’t want to add it all.</p>

<p>So, if you’re doing well with Scrum, you don’t need it. After all, you’re probably already doing most of the stuff described there.</p>

<p>If you feel the Scrum Guide is cryptic and leaves you with a feeling that it should elaborate a bit more on some aspects because you’re stuck, then the Scrum Guide Expansion Pack might be a good thing for you.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Teamwork" />
    
    <category term="Scrum" />
    
    <summary type="html">So, last month Jeff Sutherland and Co published an expansion pack to the Scrum Framework (I&apos;ll call it SGEP for short).</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">The pitfalls of AI augmented development, part 2</title>
    <link href="https://mariomelo.com/en/the-pitfalls-of-ai-augmented-development-part-2" rel="alternate" type="text/html" title="The pitfalls of AI augmented development, part 2" />
    <published>2025-06-04T09:21:57+00:00</published>
    <updated>2025-06-04T09:21:57+00:00</updated>
    <id>https://mariomelo.com/the-pitfalls-of-ai-augmented-development-part-2</id>
    <content type="html" xml:base="https://mariomelo.com/the-pitfalls-of-ai-augmented-development-part-2">
      <![CDATA[<p><strong>DISCLAIMER</strong>: This is the second post I wrote about the my talk on the Global Scrum Gathering Munich, and even though I don’t think you need to read both posts in order I strongly suggest you to read both of them to get the entirety of the ideas I’m sharing. So, here goes the link to the first one:</p>

<p>Now, let’s go back to our pitfalls and also talk about a “<em>war</em>” that’s being going on for the past 40 years: the <a href="https://en.wikipedia.org/wiki/Editor_war">Editor war</a>. It might sound like a silly war, or a simple matter of preferences, but trust me: it’s not just geek tribalism, it’s about fundamentally different philosophies of human-computer interaction.</p>

<p>I’m a NeoVim user. That means I’m one of those geeks that rather type code in the terminal istead of using something more modern like VSCode. While using NeoVim I never use my mouse or touchpad: I just type stuff and use a bunch of key combinations to navigate through the code. But I’m not alone! The first Vi editor was created in 1976 and since then its popularity has only grown between the geekiest of the software developers.</p>

<p>Why? Well, let’s explain that while talking about one of the pitfalls I mentioned in Munich:</p>

<h2 id="pitfall-4-the-coding-tunnel-vision"><strong>Pitfall 4: The Coding Tunnel Vision</strong></h2>

<p>Vi and its siblings (Vim, Neovim) became popular because they allowed developers to navigate the code faster. Instead of moving your hand to your mouse, scrolling down, selecting a part of the code you want to change and then typing the change, these editors proposed a different idea: they would have <strong>modes</strong>. While on <strong>INSERT</strong> mode, everything you type on your keyboard would appear on the screen, just like it happens on any other editor. But in <strong>NORMAL</strong> mode, each key on your keyboard can be used to navigate the code.</p>

<p>For example: if you press 3wce you would instantly change the content of the third word in that line. (Something like: Go to the <strong>3</strong> rd <strong>W</strong> ord <strong>C</strong> hange until its <strong>E</strong> nd).</p>

<p>It basically creates a dialect so you can tell your editor where you want to go and what you want to do with your code without having to do it using mouse, menus, etc. And accelerating how we navigate the code is important because <strong>software developers spend more time navigating and understanding the code than writing it</strong>.</p>

<p>A chart representing the results of a research on how developers spend their time</p>

<p>So, why are we focusing on using LLM’s to generate code when we can also use it to help us understand the code? I mean, they are great coders, I’m not denying that. But in my experience they can provide much more value explaining the code instead of just creating it.</p>

<p>Here’s a practical example on how I did that: I’m currently writing a software to improve the practical activities I run in my classes. And at some point I decided to ask Claude to explain my own architecture to me. Because Claude excels in text output I thought it would be nice to use a tool like <a href="https://mermaid.js.org">Mermaid</a>, a tool that transforms text inputs into neat diagrams. I asked Claude to explain the structure using <a href="https://www.markdown-cheatsheet.com">MarkDown</a> and <a href="https://mermaid.js.org">Mermaid</a>, and I pasted the result on a text editor compatible with both technologies called <a href="https://typora.io/">Typora</a>. Here’s the result:</p>

<p><img src="../assets/images/posts/4fad149de25d.jpeg" alt="Image" /></p>

<p>That’s a great piece of documentation that can be used to explain both the developers on my team and even the LLM itself how the architecture works! Specially because the diagram can be read by the LLM as a simple text input, minimizing the amount of tokens consumed in each interaction.</p>

<p>Thing is, no matter if you wrote the code manually or if an LLM wrote the entire thing for you, you’ll still be responsible to the consequences. Therefore, understanding what’s going on is fundamentally important.</p>

<p>Remember: <strong>if something works and you don’t know how, when it stops working you won’t know why.</strong></p>

<h2 id="pitfall-5-the-bulk-bias"><strong>Pitfall 5: The Bulk Bias</strong></h2>

<p>Some people are still complaining about the quality of the code generated by LLM’s and I strongly disagree with this take. In my experience, the code generated is actually pretty good.</p>

<p>What bothers me is the code <strong>quantity</strong>.</p>

<p>Specially because I don’t believe in “vibe coding” (that is: trusting the generated code and not even taking a look at it). I need to review the code and make sure it’s doing what it’s supposed to do because… I’m a responsible adult? So, when the LLM changes 8 files and adds 200 lines of code for each prompt I make, my job becomes extremely painful and well, unfun. I tried multiple approaches and different prompts to reduce this problem but I’m yet to find a solution.</p>

<p>To be fair Claude 4.0 presented a great improvement when it comes to this particular pitfall, and I think we’ll get a definitive solution to this one in the near future. But it’s not quite there yet.</p>

<p><img src="../assets/images/posts/eaa796ed5b4d.png" alt="Image" /><em>One prompt, MANY changes</em></p>

<p>What I feel is that instead of helping us to walk faster LLM’s are helping us to take bigger steps. Both approaches can help us to cover a longer distance in the same amount of time, but the later also comes with a high cost when you’re walking on the wrong direction. The business model also contributes to it: when I use Cursor for example, I have limited tokens/interactions, which incentivizes me to take the most out of each prompt.</p>

<h2 id="conclusion"><strong>Conclusion</strong></h2>

<p>Writing about working with LLMs is a strange thing. I wholeheartedly mean everything I wrote in this post <strong>today</strong>. But things are changing fast, and this post might age like milk or wine depending on the upcoming developments. If you value learning more about this topic, I strongly suggest you to do two things: <strong>use</strong> it to create something instead of just reading about it on LinkedIn (even better: get away from LinkedIN altogether), and try to read different takes about the subject. Karen Hao’s book “<strong>The Empire of AI</strong>” might be a good start.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="AI" />
    
    <summary type="html">DISCLAIMER : This is the second post I wrote about the my talk on the Global Scrum Gathering Munich, and even though I don’t think you need to read both posts in order I strongly suggest you to read both of them to get the entirety of the ideas I’m sharing.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">The pitfalls of AI augmented development, part 1</title>
    <link href="https://mariomelo.com/en/the-pitfalls-of-ai-augmented-development" rel="alternate" type="text/html" title="The pitfalls of AI augmented development, part 1" />
    <published>2025-05-07T17:00:08+00:00</published>
    <updated>2025-05-07T17:00:08+00:00</updated>
    <id>https://mariomelo.com/the-pitfalls-of-ai-augmented-development</id>
    <content type="html" xml:base="https://mariomelo.com/the-pitfalls-of-ai-augmented-development">
      <![CDATA[<p>My talk on the Global Scrum Gathering Munich was fast, and I said there that I would write about the subject to go deeper into this discussion, so here I am. I added a “Part 1” to the title because right now I’d like to explore three of them: <strong>Written Fixation</strong> , <strong>Monolithic Approach</strong> and <strong>Atrophy to Learn</strong>.</p>

<p>The funny thing in this conference is that I went to two subsequent talks that directly connected to what I presented: Nigel Baker and Paul Goddard talked about Pair Programming (and I’m still disappointed they didn’t mention Penn &amp; Teller in their pairing examples) and the final keynote by Henrik Kniberg that talked about agentic AI in software and agile software development. So, I’ll also connect insights from their presentations to enrich our conversation. To do that, I’ll change the order in which I initially presented the pitfalls.</p>

<h2 id="pitfall-1---written-fixation">Pitfall 1 - Written Fixation</h2>

<p>My first complaint about how most people have been using AI was about how we keep writing and using text as the <strong>only</strong> way to talk to our LLM’s. Kniberg used two different forms of communication during his presentation: <strong>voice</strong> and a <strong>napkin</strong> drawing. And that’s precisely what I was talking about: language has limitations, and these are old news. Nietzsche notoriously said that <em><strong>Every word is a prejudice</strong></em> and William James challenged our ability to comprehend the meaning behind the words with his squirrel going around the tree anecdote.</p>

<p>If you want to try how it could work, you can integrate Aider with ChatGpt to use your voice to program (and maybe that could be my next post as well). But if you don’t want to go that far, <strong>draw</strong> , take screenshots to use as examples, basically: <strong>experiment</strong>.</p>

<p>A diagram showing how the modules of my application should interact with each other</p>

<p>Now, the diagram immediately takes us to the next pitfall…</p>

<h2 id="pitfall-2---atrophy-to-learn">Pitfall 2 - Atrophy to Learn</h2>

<p><em>If an AI can code, why would I learn to code?</em> , well… that’s an interesting question. In my talk I mentioned that the code generated by the current LLM’s (like Sonnet 3.7) are actually pretty good, and often times better than what a human would write. And the LLM’s are improving faster than we are right now, so…</p>

<p>So we still need to learn. Look at the diagram in the previous section: it talks about software structure and how to organize the code. If you don’t know how to code, you can’t come with diagrams like these and <strong>your options will be limited</strong>. These limitations can lead you to dead ends and problems you’re unable to solve, and if your AI colleague is also unable to solve it then…</p>

<p><img src="../assets/images/posts/b22f19f41da8.jpeg" alt="Image" /><em>The dark side of the vibe</em></p>

<p>Like Nigel Baker and Paul Goddard said in their talk: <strong>pairing is a great way to learn</strong>. You will probably learn that different people use LLM’s in different ways, and you’ll have to figure out when to use each approach. For example: nowadays you can literally program an agent that would check everything your significant other posted on the internet and automatically buy them gifts at special dates. And they will probably be good gifts!</p>

<p>But is it a good idea? Well, I don’t think so. Simon Wardley proposes an interesting question to solve this dilemma, and by all means, if you haven’t watched his talk yet <strong>please do</strong> :</p>

<blockquote>
  <p><em>How much do you value a human involved in that decision?</em></p>
</blockquote>

<p>And sometimes, when developing software, it matters. But then again: your decision making capabilities will be limited by your knowledge. So, keep learning (and try to pair with someone else so you can learn more and faster).</p>

<h2 id="pitfall-3---the-monolithic-approach">Pitfall 3 - The Monolithic Approach</h2>

<p>I made a joke during my presentation and said that <em>Vibe Coding</em> should be renamed to <em>Conversational Reactive Assisted Programming</em>, or <strong>C.R.A.P.</strong>. Everybody laughed, and moments later we were all watching Henrik Kniberg doing an impressive demonstration using Cursor.</p>

<p>So, I think I’ll have to explain myself. :)</p>

<p>The term Vibe Coding was coined by Andrej Karpathy, and he said that the technique is “<em>not too bad for throwaway weekend projects</em>”. A key part of the definition of vibe coding is that the user accepts code without full understanding, and the AI researcher Simon Willison even said that “<em><strong>If an LLM wrote every line of your code, but you’ve reviewed, tested, and understood it all, that’s not vibe coding in my book—that’s using an LLM as a typing assistant</strong></em>.”.</p>

<p>So, by that definition of Vibe Coding, I stand by my joke. At least for now. The concept of not caring about the code generated by an LLM can be a good idea, but only if we know <strong>when to use it</strong> , and for now it shouldn’t be a 100% of the time unless you’re building a prototype.</p>

<p>The thing is, if you don’t know how to code, Vibe Coding will be your <strong>only option</strong> when using an LLM to develop software. And isn’t really <strong>coding</strong> , because it’s non-deterministic: the same prompt might generate different results. I prefer the term Simon Wardley uses: <strong>Vibe Wrangling</strong>.</p>

<p><img src="../assets/images/posts/0f708cd44fe0.jpeg" alt="Image" /><em>A slide from my talk: If you have more technical knowledge, you’ll have more options</em></p>

<p>Maybe in the future having <strong>Vibe Coding</strong> as your only option won’t be a problem, but we are not quite there yet. It might happen next year, in 2035, or it might never happen. But no matter the answer, learning to code is still relevant because it will <strong>expand your options</strong>. And that’s my main (and maybe single) critique about Kniberg’s great keynote session: I don’t think that Vibe Coding is an <strong>evolution</strong> of copying and pasting code generated by an LLM, for example. I see all these approaches being used in different contexts, and the decision will always come down to a slightly modified version of the question proposed by Simon Wardley:</p>

<blockquote>
  <p>How conscious do I need to be about the way this is going to be implemented?</p>
</blockquote>

<p>For me the answer is still “<em><strong>quite often</strong></em>”. LLM’s are biased, non-deterministic and they replicate all the problems that were present in their training data. They will make mistakes, and some of these mistakes might harm people, specially in groups that are under-represented in the data used to train the models (you can and should check Dr. <strong>Timnit Gebru</strong>’s work). When we accept AI-generated code without full understanding, we’re inheriting not just the solution but also the conceptual prejudices embedded within it.</p>

<p>So, answering that question is something we’ll start to do more and more. And going back to Nigel Baker and Paul Goddard’s session: you don’t have to answer that question alone.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="AI" />
    
    <summary type="html">My talk on the Global Scrum Gathering Munich was fast, and I said there that I would write about the subject to go deeper into this discussion, so here I am.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">What I chose not to build: Decisions I made while creating my training platform using elixir</title>
    <link href="https://mariomelo.com/en/what-i-chose-not-to-build" rel="alternate" type="text/html" title="What I chose not to build: Decisions I made while creating my training platform using elixir" />
    <published>2025-03-31T17:11:56+00:00</published>
    <updated>2025-03-31T17:11:56+00:00</updated>
    <id>https://mariomelo.com/what-i-chose-not-to-build</id>
    <content type="html" xml:base="https://mariomelo.com/what-i-chose-not-to-build">
      <![CDATA[<p>As any developer out there, I love to start pet projects. But for me they have a different weight: developing a pet project helps me to stay connected to my <a href="/en/about">personal mission.</a></p>

<p>I’m constantly teaching and coaching people on how to develop better products, be it in CSM/CSD classes, as a consultant or as a mentor. I do have my share of stories to share during these events, but you know… while these stories are new and exciting for the students, I can’t say the same after repeating them a dozen times.</p>

<p>And besides… I need an excuse to touch code. :)</p>

<h2 id="the-product">The Product</h2>

<p>As a trainer, I try to create simulations so my students can learn by their own experience most of the time. That’s why in 2019 I created the card game <a href="https://scrumchkin.com">Scrumchkin</a>, for example. But since the pandemic, most of my training sessions have been online, which makes it really hard to replicate the same dynamic environment I had with the actual Scrumchkin cards in an in-person training.</p>

<p>So, I decided that my product would try to solve that problem:</p>

<blockquote>
  <p><strong>The students should be able to learn complex subjects through dynamic experience and simulations.</strong></p>
</blockquote>

<p>It was a good fit after all: I have periodic classes where I can take the product to a field test and collect feedback and I have access to a community of trainers that could be interested in trying the product and providing a different kind of feedback.</p>

<p>As everything I needed was an excuse to start writing code, I was happy with that.</p>

<p><strong>Decision:</strong> Pick an UI component library from the beginning and stick to it. You can change the whole thing later, <strong>if necessary</strong>.</p>

<h2 id="tooling-decisions">Tooling decisions</h2>

<p>I decided to avoid using a database at first, until I figure out what kind of data I want to store and how I want them stored.</p>

<p>Elixir (my go-to language) has something that does the job quite well: GenServers. I can use them to temporarily store data without having to resource to a database. The information will be there until one of three things happen:</p>

<ul>
  <li>
    <p>I restart the server</p>
  </li>
  <li>
    <p>An error occurs and the GenServer gets restarted</p>
  </li>
  <li>
    <p>I terminate the GenServer</p>
  </li>
</ul>

<p>This approach allowed me to move faster and forget about migrations, for example.</p>

<p><strong>But, but… Mario! Isn’t it risky?</strong></p>

<p>Risk depends on context. My training sessions are short, and in the worst case scenario I would lose about 15 minutes of time and the students would have to restart an exercise if a GenServer fails during the training.</p>

<p>So, it’s a risk I’m <strong>consciously</strong> willing to take.</p>

<h2 id="talking-about-failures">Talking about failures…</h2>

<p>I can’t say I’m doing pure TDD, but I’m writing a lot of tests. Specially because I’m using Claude to generate some chunks of code for me (I’ll write later on <strong>which</strong> chunks of code Claude is writing for me).</p>

<p>It’s really hard to use TDD with an LLM. These models generate huge chunks of code at once. Meanwhile, TDD is all about that incremental rhythm: one test, make it pass, and then tackle the next one. What I’m doing is writing tests for my GenServers, asking Claude to come up with extra tests I might have forgotten and then asking Claude to implement the functions that would make the tests pass.</p>

<p>I learned that tests are now <strong>way more important than they were before AI</strong>. When a LLM makes dozens of changes in your code, it’s impossible for you to guarantee that your code still does what it’s supposed to do. And I had Claude breaking my tests more times than I could count, specially when it tried to modify a lot of files at a time.</p>

<p><strong>Decision:</strong> Using AI as copilot increases the need for automated tests. And the AI can help you writing your tests as well.</p>

<h2 id="design-decisions">Design decisions</h2>

<p>I acquired <a href="https://tailwindcss.com/plus">tailwindui</a> a long time ago and I enjoy using its building blocks to create my applications. I can use it to make my product look nice without spending much time over-refining my design.</p>

<p>Of course, being a non-designer I also struggle with the overall layout. Even though I have beautiful blocks to work with I’m still pretty capable of messing the whole thing up when putting them together. So, sometimes I use <a href="https://lovable.dev">Lovable</a> to understand better ways to visualize how the components could go together.</p>

<p><strong>Decision:</strong> Try to postpone having a database. Think about different ways to do that so you can learn more about your data before committing to a model structure.</p>

<h2 id="authentication-mechanism">Authentication mechanism</h2>

<p>When I’m in a training session, I don’t want to have my students creating accounts and remembering passwords for an experience that will last for 2 or 3 days. I also don’t want to spend time fiddling with an authentication mechanism.</p>

<p>Now, I know some of you are thinking: “ <em>Hey Mario, it’s 2025! You can set up an authentication mechanism in a couple of minutes</em> ”. Maybe yes, maybe not. But I’m positive that having a full authentication mechanism would instantly add at least a bit of complexity to everything else I want to develop.</p>

<p>So my mechanism works this way:</p>

<p>You tell me your name, I save it to your session and you’re good to go. Unless you’re the trainer, of course. Then all you have to do is enter your name as <strong>SUPER_SECRET_PASSWORD</strong> and you’ll have access to advanced features.</p>

<p>Is it safe? No.</p>

<p>Is it good enough to use in a class with 20 people? Definitely yes.</p>

<p><strong>Decision:</strong> Authentication comes in the last responsible moment. Think about it, work around it and maybe you’ll end up creating something innovative.</p>

<h2 id="deploy">Deploy</h2>

<p>I recently read the amazing book Simplicity by <a href="https://articles.pragdave.me">Dave Thomas</a>, and there’s a lot of good ideas there. One I’m particularly fond of is: <strong>automate your deployment from day zero</strong> , so you can deploy often.</p>

<p>I did that using github workflows and my dedibox in <a href="https://www.scaleway.com/en/">Scaleway</a>. Now I deploy by doing just a single:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin deploy
</code></pre></div></div>

<p>And of course, the deploy occurs only if all my tests passes. Pretty basic stuff, I know. But doing that from day one allows me to deploy often and gather feedback quickly.</p>

<p><strong>Decision:</strong> Create a hello world, deploy it and automate the entire deployment process before doing anything else.</p>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>A good pet project is a pet project you can quickly deploy and have other people to use it. In my case, as a trainer, the idea of creating a platform to simulate real life stuff during training sessions seems like a perfect fit.</p>

<p>Will I revisit some of these decisions? <strong>OF COURSE!</strong> That’s the entire idea behind each one of these decisions. One day I’ll have a proper authentication mechanism and a database, but when that day comes I’ll have a reason to implement these things.</p>

<p>As Jaqen from Game of Thrones would say:</p>

<blockquote>
  <p>What do we say to our need to implement authentication in our products? <strong>Not today.</strong></p>
</blockquote>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Building" />
    
    <category term="Product" />
    
    <summary type="html">As any developer out there, I love to start pet projects.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Language matters: A demo is not a review</title>
    <link href="https://mariomelo.com/en/language-matters-a-demo-is-not-a-review" rel="alternate" type="text/html" title="Language matters: A demo is not a review" />
    <published>2025-02-27T13:31:31+00:00</published>
    <updated>2025-02-27T13:31:31+00:00</updated>
    <id>https://mariomelo.com/language-matters-a-demo-is-not-a-review</id>
    <content type="html" xml:base="https://mariomelo.com/language-matters-a-demo-is-not-a-review">
      <![CDATA[<p>I remember when I was first introduced to semiotics in the Cynefin Virtual Basecamp during the pandemic. I was lost, I learned a lot, but back then the subject seemed abstract and I felt like it didn’t resonate with me. Oh boy, now it does.</p>

<p>Turns out language is probably one of the most mind-blowing topics I came across since I started studying philosophy, and it’s a one-way wormhole: once you start thinking about the meaning of words and symbols you can never go back. So much that when I stumbled upon Kent Beck’s last post (link below) I started to automatically reflect upon the word <strong>demo</strong>.</p>

<p><a href="https://tidyfirst.substack.com/p/the-threat-of-incremental-delivery?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web">Software Design: Tidy First - The Threat of Incremental Delivery</a></p>

<p>So, let’s try to delve into the meaning of two words we often use in software development: <strong>demo</strong> and <strong>review</strong>. Stick with me, I promise I’ll keep my feet on the ground.</p>

<h2 id="what-is-a-demo-answer-1">What is a “demo”? Answer 1:</h2>

<p>As someone who likes videogames, I remember playing a lot of <strong>demos</strong> when I was younger. The demos were basically a version of the game that had limited features, such as a single level, and there were magazines that would come with a CD-ROM containing dozens of <strong>demos</strong> so you could have a little taste of a game before committing your money and buying the full version of it. The demos still exist and are out there, they just don’t come in CD-ROMs anymore.</p>

<p><img src="../assets/images/posts/71864f3b63ae.jpeg" alt="Image" /><em>A demo works as a “teaser” to convince people to buy the product</em></p>

<p>So, a <strong>demo</strong> was a <strong>demonstration</strong> of something that was <strong>already done</strong>. Its purpose was to allow people to test something before answering a simple question: <strong>is it worth my money?</strong> On the developers side, they were trying to <strong>demonstrate</strong> that the answer should be a sound “YES!”.</p>

<p>And that’s why I don’t like using the word <strong>demo</strong> in scenarios where the customer is already committed to the product development. They already invested their money there, so… what’s the point of offering them a <strong>demonstration</strong>?</p>

<h2 id="what-else-is-a-demo-answer-2">What else is a “demo”? Answer 2:</h2>

<p>The word demo could have a different meaning. Specially in low-trust environments, where the customer needs some <strong>proof</strong> of progress. Some way to validate that what is being produced by the team is 100% coherent with the initial specification.</p>

<p><em>Here customer, if you click here a popup window opens and an error message is shown, Q.E.D.</em></p>

<p>Q.E.D - quod erat demonstrandum, meaning “<strong>that which was to be demonstrated</strong>”.</p>

<p>This time we are using a demonstration to prove something. To show the customer that we’ve been working since our last meeting and that the progress we made matches the initial expectations.</p>

<p>This meaning fits some software development teams better, but still has a problem: a <strong>demonstration</strong> is not about gathering <strong>feedback</strong>.</p>

<h2 id="what-about-a-review">What about a “review”?</h2>

<p>Re-view. To view again. Does it work?</p>

<p>“<em>Let’s look at the software we’re producing one more time and check if we’re heading to the correct destination.”</em></p>

<p>That sounds good. But I also think about when my bike undergoes its safety review:</p>

<p><em>“We have a predefined checklist, and we’ll go over every item to make sure everything is</em><strong>according to the standards</strong>.<em>”</em></p>

<p>Nope. Doesn’t work.</p>

<p>I still don’t love this word, but it’s way better than <strong>demo</strong>. At least it has a chance of actually stating what we’re trying to do.</p>

<h2 id="what-other-words-could-we-use">What other words could we use?</h2>

<p>There’s no perfect word to use. But take the Scrum framework for example: the name <strong>Sprint Retrospective</strong> makes perfect sense to me. The name <strong>Sprint Review</strong> doesn’t. Are we <strong>reviewing</strong> the <strong>Sprint</strong>? What kind of <strong>review</strong> are we doing? The good one or the bad one?</p>

<p>This conversation takes me back to when I was planning my wedding and we had to <strong>try</strong> all the fancy snacks, sweets and the cake. We would <strong>try</strong> them, and provide feedback. The buffet would be <strong>adapted</strong> according to our feedback. That experience is much more inline with what software development teams are actually trying (or should be) to do in a <strong>Sprint Review</strong>.</p>

<p>So, if I were to rename the Sprint Review I would call something on the lines of <strong>Increment Try-Out</strong> or <strong>Product Try-Out</strong>.</p>

<p>It focuses on what we produced rather than on the Sprint. And a <strong>try-out</strong> is about empiricism, it makes the need of the customer active participation more explicit.</p>

<p>Is it perfect? Well… no. But:</p>

<blockquote>
  <p><em>Every word is a prejudice</em></p>

  <p><cite>- Nietzsche</cite></p>
</blockquote>

<p>Ps: If you like this subject you’ll probably like to spend half an hour listening to this episode of <a href="https://www.philosophizethis.org/podcast/episode-178-susan-sontag?rq=178">Philosophize This! - Episode 178: Susan Sontag on Metaphors</a>. :)</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Teamwork" />
    
    <category term="Scrum" />
    
    <summary type="html">I remember when I was first introduced to semiotics in the Cynefin Virtual Basecamp during the pandemic.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Empiricism and rationalism in software development</title>
    <link href="https://mariomelo.com/en/empiricism-and-rationalism-in-software" rel="alternate" type="text/html" title="Empiricism and rationalism in software development" />
    <published>2025-02-06T19:09:26+00:00</published>
    <updated>2025-02-06T19:09:26+00:00</updated>
    <id>https://mariomelo.com/empiricism-and-rationalism-in-software</id>
    <content type="html" xml:base="https://mariomelo.com/empiricism-and-rationalism-in-software">
      <![CDATA[<h2 id="where-did-this-post-come-from">Where did this post come from?</h2>

<p>First things first: no, I’m not under the influence of any mind-altering substances. I recently started studying philosophy and developed a taste for it. While studying, my mind kept connecting philosophical concepts and questions with techniques and behaviors we’re accustomed to seeing in the software development world. I quickly made a list of potential posts I’d like to write, so this definitely won’t be my last post about philosophy and software development.</p>

<p>In other words… this trippy post won’t be the last one on this subject. :)</p>

<h2 id="descartes-was-about-50-agile">Descartes was about 50% agile</h2>

<p>Descartes would definitely write great unit tests and experiment some suffering with them</p>

<p>Descartes was a <strong>rationalist</strong>, meaning he believed that the best way to find truth was through thought. This might make us think of him as a traditional project manager, sitting at his desk thinking through every detail of the plan we must follow to develop our product.</p>

<p>But thinking of him that way wouldn’t be fair, because in his Cartesian method we can find ideas very similar to what we practice in agile software development:</p>

<ul>
  <li>
    <p>Breaking big problems into smaller problems</p>
  </li>
  <li>
    <p>Ordering problems and solving the simplest ones first</p>
  </li>
</ul>

<p>You can almost imagine him writing unit tests and breaking down Product Backlog items, right? But there’s a problem: Descartes believed we could reach ideas that were “<strong>clear, objective, and immutable</strong>”, and that we could use them like LEGO blocks to build bigger ideas.</p>

<p>It’s as if he supported writing unit tests initially to provide <strong>clarity and objectivity</strong>, but failed to see value in keeping these tests in the repository after the functions were implemented because that idea had already been validated and consolidated.</p>

<p>In other words: Descartes sought an <strong>immutable truth</strong>, but the process to reach these truths was <strong>iterative and incremental</strong>.</p>

<p>But if Descartes was partially right about method, where did he go wrong? This is where David Hume comes in with a revolutionary idea: what if experience is more important than pure reasoning?</p>

<h2 id="hume-would-have-been-an-excellent-scrum-master">Hume would have been an excellent Scrum Master</h2>

<p><img src="../assets/images/posts/88f730254217.jpeg" alt="Image" /><em>Hume would push the team to experiment more, and allow them to learn from their failures</em></p>

<p>David Hume had the advantage of being born about 120 years after Descartes and thus having more material to study and explore. He argued that real knowledge can only be obtained through experience, and that merely sitting and reflecting or studying wouldn’t generate any new <strong>facts</strong>, only mere <strong>speculation</strong>.</p>

<p>But even being a devoted fan of experiments, he knew how to recognize their limitations:</p>

<blockquote>
  <p>Though experience be our only guide in reasoning concerning matters of fact, it must be acknowledged that this guide is not altogether infallible but in some cases may lead us into errors</p>

  <p><cite>- David Hume</cite></p>
</blockquote>

<p>Through this thinking, he raised some problems (and reflected on others that had been previously raised by other philosophers) that are easily recognizable in the software development world:</p>

<p><strong>1. The problem of induction:</strong> Past experience doesn’t guarantee the repetition of future results. Also known as: if it works on my machine, it works on the server.</p>

<p><strong>2. The problem of causality:</strong> Just because event A occurred followed by event B doesn’t mean one caused the other. Also known as: to replicate the bug the customer found, just follow these steps.</p>

<p><strong>3. The fallibility of experiment:</strong> An experiment can always fail or lead us to wrong conclusions. Also known as: if we cover 100% of the code with tests, we’ll never have bugs again.</p>

<p>As The X-Files would say: <strong>The truth is out there!</strong></p>

<p>This maxim should govern Scrum teams worldwide, since the framework has Empiricism as part of its foundation. If David Hume were a Scrum Master and saw teams doing Sprint Reviews with PowerPoint presentations or Dailies that are basically Status Reports, he definitely wouldn’t sit idly by.</p>

<p>If Hume were a Scrum Master today, he would probably:</p>

<ul>
  <li>
    <p>Insist on demonstrations of working software</p>
  </li>
  <li>
    <p>Prioritize real metrics over theoretical estimates</p>
  </li>
  <li>
    <p>Question any “absolute truth” about processes</p>
  </li>
</ul>

<h2 id="cool-but-can-we-conclude-anything-useful-from-all-this">Cool… but can we conclude anything useful from all this?</h2>

<p>Well, first of all, I’m not a philosophy expert and took the utmost care not to commit any crimes when mentioning these philosophers and their thoughts. I’m comfortable with my understanding of the subject, and I believe this type of deeper understanding about the why of things always leads us to question mechanical behaviors and be more <strong>conscious</strong> about what we practice daily.</p>

<p>I think writing helps me better absorb the topics I study, and even if nobody reads it, it ends up having value for me.</p>

<p>For example, we can conclude that <strong>context matters</strong>. Descartes would probably write unit tests to validate the logic of building our product, while Hume would think about acceptance tests to evaluate customer behavior when using the product. Both approaches have value that can be greater or lesser according to the context in which they are applied.</p>

<p>If Descartes and Hume decided to do pair programming today, they would probably create <strong>DevOps</strong>.</p>

<p>Descartes would contribute with:</p>

<ul>
  <li>
    <p>Infrastructure as code (after all, it needs to be clear and objective)</p>
  </li>
  <li>
    <p>CI/CD Pipeline (order and method in action)</p>
  </li>
  <li>
    <p>Automated tests (validating fundamental truths)</p>
  </li>
</ul>

<p>While Hume would insist on:</p>

<ul>
  <li>
    <p>Constant monitoring (because experience matters and failures happen)</p>
  </li>
  <li>
    <p>Feature flags (to validate hypotheses in production)</p>
  </li>
  <li>
    <p>Culture of blameless postmortem (learning from errors and treating them as a natural part of the process)</p>
  </li>
</ul>

<p>If we understand each daily practice as an experiment that can fail, we can start to see if we achieve satisfactory results in each of these experiments:</p>

<ul>
  <li>
    <p>Why do we have daily meetings?</p>
  </li>
  <li>
    <p>Why do we do Sprint Reviews?</p>
  </li>
  <li>
    <p>How can I measure the value that a certain practice brings to my team?</p>
  </li>
</ul>

<p>And this way we start to do our work with more <strong>consciousness</strong>, always taking into account the <strong>intention</strong> of each step.</p>

<h3 id="interested-well-here-are-my-recommendations">Interested? Well, here are my recommendations:</h3>

<p>I started learning more philosophy through Stoicism, and Ryan Holiday’s <strong>The Daily Stoic</strong> is a book I’m reading for the third time and therefore never tire of recommending. If stoicism appeals to you, all of Seneca’s work might be interesting, and I recommend starting with “<strong>On the Tranquility of the Mind</strong>”.</p>

<p>Oh! If you’re not much of a book person, check out the <a href="https://www.youtube.com/@PhilosophyTube">Philosophy Tube channel</a> on YouTube. Her video on empiricism might be a good start!</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="Philosophy" />
    
    <summary type="html">&gt; Adapted from a post I originally wrote in portuguese</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">The advent of TDD: A beginners guide</title>
    <link href="https://mariomelo.com/en/the-advent-of-tdd-a-beginners-guide" rel="alternate" type="text/html" title="The advent of TDD: A beginners guide" />
    <published>2025-01-14T17:22:21+00:00</published>
    <updated>2025-01-14T17:22:21+00:00</updated>
    <id>https://mariomelo.com/the-advent-of-tdd-a-beginners-guide</id>
    <content type="html" xml:base="https://mariomelo.com/the-advent-of-tdd-a-beginners-guide">
      <![CDATA[<h2 id="starting-with-test-driven-development">Starting with Test-Driven Development</h2>

<p>How can I start applying Test-Driven Development?” This question echoes through my training sessions like a recursive function call. While my default response has always been <em>“Start with fixing bugs,</em>” I’ve discovered an even more engaging approach: <strong>Advent of Code</strong>.</p>

<h2 id="my-default-approach-fixing-an-existing-bug">My default approach: fixing an existing bug</h2>

<p>Let’s examine a simple example. Imagine you have a calculator function:</p>

<p>When someone tries to divide by zero, our application crashes <strong>unceremoniously</strong>. This presents a perfect opportunity for TDD – we can write a test expressing our <strong>desired behavior</strong>:</p>

<p><img src="../assets/images/posts/0dbccba9581c.png" alt="Test code for divide by zero scenario" /></p>

<p>My test will of course fail, because my code fails. I can now fix my code and make my test pass.</p>

<h2 id="the-gamified-approach-advent-of-code">The Gamified Approach: Advent of Code</h2>

<p>As a self-proclaimed geek with an affinity for puzzles, I’ve found <a href="https://adventofcode.com">Advent of Code</a> to be the perfect TDD training ground. Each puzzle provides:</p>

<ul>
  <li>
    <p>An input sample</p>
  </li>
  <li>
    <p>An expected output</p>
  </li>
</ul>

<p>This structure naturally guides you into the TDD mindset – you write your test based on the example before implementing your solution. It’s like having a <strong>built-in specification</strong>!</p>

<p><img src="../assets/images/posts/980611310d5a.png" alt="Advent of Code example showing input and expected output" /></p>

<p>I mean, not only it’s a good way to learn TDD but it’s also fun. You’re honing your development skills, solving a puzzle and practicing a very valuable technique.</p>

<p>As you advance through the challenges, you might start to experiment more with TDD and maybe reduce the granularity of some of your tests. For example, you might need to parse a complex text input into a Map in order to solve the problem, and then that could be a test on its own.</p>

<h2 id="tools-that-enhance-the-experience">Tools That Enhance the Experience</h2>

<p>In Elixir (my language of choice), the <strong>pipe operator</strong> (<code class="language-plaintext highlighter-rouge">|&gt;</code>) is particularly powerful for TDD:</p>

<p><img src="../assets/images/posts/ad2c4c517ce0.png" alt="Elixir pipe operator code example" /></p>

<p>That small triangle basically says: <em>take the output of the above function and pass it on to the following function.</em> This elegant syntax allows you to sketch out your solution’s high-level flow before diving into implementation details.</p>

<p>Combine this with tools like <code class="language-plaintext highlighter-rouge">mix test.watch</code>, which automatically runs tests when files change, and you’ve got a rapid feedback loop that makes TDD feel natural and intuitive.</p>

<h3 id="ready-to-begin">Ready to Begin?</h3>

<p>Pick your preferred programming language and dive in! You can explore my Advent of Code 2024 repository for inspiration:</p>

<p><a href="https://github.com/mariomelo/advent_of_code24">https://github.com/mariomelo/advent_of_code24</a></p>

<p>Remember: The goal isn’t perfection but practice. Each puzzle is an opportunity to strengthen your TDD muscles while having fun!</p>

<p><em>For deeper insights into TDD, check out</em> <em>’s excellent article on Software Design: Tidy First?</em></p>

<p><a href="https://tidyfirst.substack.com/p/canon-tdd?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web"> Software Design: Tidy First? - Canon TDD</a></p>

<p>Happy coding!</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="Testing" />
    
    <summary type="html">Starting with Test-Driven Development</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">The 3 biases of software development, part 3: Modularity</title>
    <link href="https://mariomelo.com/en/the-3-biases-of-software-development-part-3-modularity" rel="alternate" type="text/html" title="The 3 biases of software development, part 3: Modularity" />
    <published>2024-11-26T18:40:02+00:00</published>
    <updated>2024-11-26T18:40:02+00:00</updated>
    <id>https://mariomelo.com/the-3-biases-of-software-development-part-3-modularity</id>
    <content type="html" xml:base="https://mariomelo.com/the-3-biases-of-software-development-part-3-modularity">
      <![CDATA[<h2 id="what-is-the-modularity-bias"><strong>What is the Modularity Bias?</strong></h2>

<p>So far we talked about <strong>Stratification</strong> and <strong>Chronology</strong>, and we moved from the “Mario Bros approach” where we’ll always develop level 1-1 before level 1-2 to the “Megaman approach”, where we have more flexibility and can develop our modules in any order.</p>

<p>Did you notice I just used the word “<strong>modules</strong>”? That’s the problem we are about to tackle in this post: if we consider that a given part of our software is done, that means that part isn’t flexible anymore. If Stratification is about layers and Chronology about sequence, Modularity is about the boxes we put our code in - and sometimes, those boxes become prisons.</p>

<h2 id="understanding-the-modularity-bias"><strong>Understanding the Modularity Bias</strong></h2>

<p>When you beat a boss in Megaman, you gain access to a new weapon. A complete and functional weapon, but also a weapon that will never change. In software development however, if we try to finish a part of our software and state that we will never be touching that area of the code again… Well, let’s say it just doesn’t work like that. Sorry, Megaman.</p>

<p>So, which game could we use as an analogy on how to improve the MegaMan approach? Planescape: Torment! (Or any other Classic RPG for that matter).</p>

<p>In Planescape, every time you accumulate enough experience you can upgrade your character by adding points to his Strength, Wisdom, Intelligence, Dexterity, Charisma and Constitution. You gradually improve these stats, but you never <strong>complete</strong> any of them: you can always add more points to a given stat during your next “level-up cycle”.</p>

<p>Think about Megaman: when you start to play it, you can chose one of 8 stages to play. But every time you beat a stage you have less options on what to play next, up to a point where you’ll have no choice because you’ve beaten 7 stages and there’s just one remaining. You start flexible, but you lose that flexibility along the way.</p>

<p><img src="../assets/images/posts/f29db3600f80.png" alt="Captura de Tela 2024-11-26 às 16.41.30.png" /></p>

<p>In Planescape we don’t acquire new “modules” to our character. We improve their characteristics according to our needs, and our needs change as we advance through the game.</p>

<h2 id="enough-about-games-lets-talk-about-software"><strong>Enough about games. Let’s talk about software!</strong></h2>

<p>Well, technically these games are also software, but I get the point. :)</p>

<p>Let’s go back to the example we had in our last article: a Hangman game. While breaking the Chronology bias we decided to postpone the development of a “Dictionary Module” by just implementing a function that always return the same word: ELEPHANT.</p>

<p><img src="../assets/images/posts/436f8105a745.webp" alt="b8089ce3-1a92-4b29-8fbe-6c27303befb3_789x194.webp" /></p>

<p>By doing that we were able to focus on more interesting things such as the game mechanism without spending much time with the dictionary. If we think about our next step, one could say that we could implement the actual dictionary next and give our Megaman a new weapon. But by doing so we would hinder our ability do adapt to customer feedback as we reduce the amount of possibilities we could develop in the future.</p>

<p>unless we’re willing to discard some of our work and redo it according to the feedback we receive, of course. It’s actually not a crime to do that, but this kind of waste can be drastically minimized if we instead of implementing the Dictionary we ask ourselves the following question:</p>

<p><em><strong>How could we upgrade our Dictionary by a single point, like in that game Planescape?</strong></em></p>

<p>Maybe we could create a list of words and pick a random word each time the function get_word is called. This is simple, could be done in a couple minutes and would greatly improve the game.</p>

<p><img src="../assets/images/posts/a051804e0114.png" alt="Captura de Tela 2024-11-26 às 17.51.47.png" /></p>

<p>Notice that we didn’t implement the API integration initially shown on our last post, but we can do that in the future if we think it’s a good idea. Or not.</p>

<h2 id="benefits-of-breaking-the-modularity-bias"><strong>Benefits of breaking the Modularity Bias</strong></h2>

<p>Let’s say you’re developing that Hangman game using the MegaMan approach and you’re part of a Scrum Team. During the Sprint Review you show your customer what you build and you ask for feedback:</p>

<p><em><strong>So customer, we finished the Interface and the Dictionary. What do you think we should do next?</strong></em></p>

<p><img src="../assets/images/posts/52a0baca39b3.png" alt="Captura de Tela 2024-11-26 às 18.14.11.png" /></p>

<p>Well, what’s the point of asking feedback here? If the customer asks us to change something related to the Dictionary or the Interface, we’ll waste a lot of the work we’ve done, and if they limit their feedback to the remaining areas of the software we aren’t benefiting from the whole Scrum thing.</p>

<p>Now, imagine you with the Planescape approach. You improved our Dictionary and our Interface, but instead of finishing them we used the remaining time to come up with a simple Scoring System:</p>

<p><img src="../assets/images/posts/cbc13d32963f.png" alt="Captura de Tela 2024-11-26 às 18.38.27.png" /></p>

<p>In this scenario, you would be able to ask your customer a different question during the Sprint Review, such as:</p>

<p><em><strong>So customer, we based in what you saw, where should we allocate our next 3 upgrade points? And what are we trying to achieve by doing that?</strong></em></p>

<p>Notice the difference? The customer has keeps their options and even if they ask us to improve something we already worked upon, we don’t throw work away. At least not that much.</p>

<p>Also, maybe we won’t have to implement that API integration right now as the customer decides to enhance the Scoring System and implement Hint Mechanism. Meanwhile we won’t have to worry about how many API calls we’re making during the development process, create mocks and stubs to test our game or create a configuration option to make our game deployable to both staging and production server.</p>

<p>The waste we minimize isn’t just related to customer feedback, <strong>but to the entire development process</strong>.</p>

<p>Maybe we’ll never use that API. In fact, while developing this Hangman Game for a Certified Scrum Developer course I was teaching, my wife played the game and came up with an interesting idea: since the course was about Scrum, we should use words from the Scrum Guide, and by doing that we ended up with a static dictionary that had 802 different words. All related to the same subject: Scrum.</p>

<h2 id="how-can-we-avoid-that-modularity-bias"><strong>How can we avoid that Modularity Bias?</strong></h2>

<p>I’ll be direct with this one: Use the Hamburger Method. I know I could ellaborate more, but in my experience there’s no better way to tackle that bias as team than using that method. You can read more about that method here:</p>

<p><a href="https://gojko.net/2012/01/23/splitting-user-stories-the-hamburger-method/">https://gojko.net/2012/01/23/splitting-user-stories-the-hamburger-method/</a>.</p>

<p>It’s also a great way to deal with dependencies, which often pushes us towards the Modularity Bias.</p>

<p>There’s still one more thing we need to address here: <strong>The Planescape: Torment approach isn’t even our final destination</strong>. That’s because in that great game we’ll always have the same 6 stats to upgrade throughout the entire game. And if you truly break this Modularity Bias, you’ll be able to discover new areas to explore as you move forward.</p>

<h2 id="this-post-is-too-long-could-you-summarize-please"><strong>This post is too long, could you summarize please?</strong></h2>

<p>Yep! Before declaring any part of your software ‘complete’, remember: even the most powerful RPG character can still level up.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="Bias" />
    
    <summary type="html">What is the Modularity Bias?</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">The 3 biases of software development, part 2: Chronology</title>
    <link href="https://mariomelo.com/en/the-3-biases-of-software-development-part-2-chronology" rel="alternate" type="text/html" title="The 3 biases of software development, part 2: Chronology" />
    <published>2024-10-23T10:13:47+00:00</published>
    <updated>2024-10-23T10:13:47+00:00</updated>
    <id>https://mariomelo.com/the-3-biases-of-software-development-part-2-chronology</id>
    <content type="html" xml:base="https://mariomelo.com/the-3-biases-of-software-development-part-2-chronology">
      <![CDATA[<p>In my last post, I talked about how the habit of splitting software into layers can lead us to tackle one layer at a time, producing the undesired BDUF (Big Design Upfront) effect.</p>

<p>This time, we’ll talk about how an imaginary user flow can lead us to blindly follow a predefined development flow.</p>

<h3 id="understanding-the-chronology-bias">Understanding the Chronology Bias</h3>

<p>I remember the first time I played a Mario Bros game in the NES console my father gave me when I was 4. The absurdly unergonomic rectangular controller, the joy of playing a game with a character with which I shared my name… It was a blast, and it was very linear: 8 worlds with 4 stages each. You start on Stage 1-1 and finish the game after beating stage 8-4. There were warps you could take to advance forward, but you could never go back.</p>

<p>Developing software under a Chronology Bias is like playing that Mario Bros game, except it isn’t that much fun. You start developing world 1-1 because that’s what the user will play first. Then you develop world 1-2, and so on. If we follow that path, we are clearly not falling into the Stratification Bias, because we are creating every layer for each stage (we are not finishing the design of all levels before implementing the game mechanism, for example), and we would be able to gather feedback from the customer after developing each stage and use that to create better stages further on. But still… we are missing some good opportunities.</p>

<p>You know what’s funny? This Mario-style linear progression shows up everywhere in software development. Take the login screen, for example - it’s pretty much become our “Stage 1-1”. It’s almost like there’s an unwritten rule that says “Thou shalt implement authentication first” just because it’s the first thing users see. And more than often, this is the first thing a software development team will work on. Have you ever done that? I did it, countless times.</p>

<h3 id="but-whats-the-problem-with-this-approach">But what’s the problem with this approach?</h3>

<p>Problems, I would say. Plural.</p>

<p>The most obvious one is that we are not entirely benefiting from an agile approach if we are following a predefined path. After reviewing Stage 1-1, we’ll have some flexibility on <strong>how</strong> we develop stage 1-2 but not on <strong>what</strong> we should develop in our next iteration. Besides, all of our conversations about the product will leave that sour taste of wasted time because the path is already defined. This feeling is quite common among developers in Scrum Teams during the Sprint Planning and Sprint Review when they’re falling into this bias.</p>

<p>What if stage 6-2 is the most valuable one to my user? They’ll have to wait 26 iterations to finally be able to play it.</p>

<p>Another problem will be risk mitigation. If I’m building a Mario game maybe I’ll have some bold ideas I want to validate first, such as a water world, a puzzle castle or a very challenging boss. Even the final boss!</p>

<p>So the solution seems straightforward: just develop features in any order that provides the most value, right? We could build stage 4-3 before stage 1-2, following user priorities rather than sequential order.</p>

<p>Well… turns out we often hit a familiar obstacle: dependencies. But here’s where another gaming classic offers us an illuminating alternative…</p>

<h3 id="breaking-the-chronology-bias-and-the-dependencies">Breaking the Chronology Bias (and the dependencies)</h3>

<p>Going back to my childhood and my NES console, there was a game I loved even more than Mario Bros: MegaMan. In every MegaMan game you could select which stage you wanted to play, and once you had beat the stage boss you would gain access to their weapon and could use it for the rest of the game.</p>

<p><img src="../assets/images/posts/3c4a3ffcec95.jpeg" alt="Image" /><em>If you never played Megaman, stop reading and go play NOW</em></p>

<p>So, you could choose to fight Fireman first and use its fire weapon against Iceman, or the other way around. It’s up to you. There was absolutely no predefined sequence. But… what happens if we try to use the same approach on software development? Well, sometimes we’ll hear and say things like:</p>

<p><em>We can’t develop a report without creating a CRUD to insert the data first, after all there’s no report without data!</em></p>

<p>Ok, let’s challenge that: How could we develop a report without having an interface for data insertion? Well, mocking the data. Imagine we are going to build a Hangman game. One could say that the very first thing we need to do is create a dictionary of words we can use during the game, because <strong>having a word to play is a pre-requisite!</strong></p>

<p>So, if we fall into that trap, we’ll probably spend some time developing something like:</p>

<p><img src="../assets/images/posts/2a14700e04ab.jpeg" alt="Image" /></p>

<p>It doesn’t seem like much, but it required some time to research a way to generate a random word, read the API documentation, create an account, get an API key, write the code, test it and refactor it a bit. But the game mechanism is way more important, and if we could save some time here we could use that time to develop it further. And one way to do it is by establishing a simple interface.</p>

<p>When I call the function <code class="language-plaintext highlighter-rouge">get_word</code> I get a word, and I don’t really care about where it came from. If we do that, we could create our Dictionary like this:</p>

<p><img src="../assets/images/posts/7d3b4b82aafe.jpeg" alt="Image" /></p>

<p>Yes, the word will always be <code class="language-plaintext highlighter-rouge">ELEPHANT</code>. But I’m not saying we should release the game like that! All I’m saying is that now instead of showing the user a screen that generates a bunch of random words, we’ll show a fully functional Hangman game that always use the word <code class="language-plaintext highlighter-rouge">ELEPHANT</code>. And by doing that, our product review will become more interesting because now we have a very powerful question to ask:</p>

<blockquote>
  <p>What should we do next?</p>
</blockquote>

<p>We could decide to implement the Dictionary, or the customer could ask for something else, like a scoring system for the game or a hint mechanism. We’ll have options. We are not playing Mario Bros, we are playing MegaMan.</p>

<h3 id="and-how-do-i-start-to-do-it">And how do I start to do it?</h3>

<p>First of all, take notes of all your dependencies assumptions and start to question them. I like to use the <strong>How could we / without</strong> construction to do that:</p>

<ul>
  <li>
    <p><strong>How could we</strong> <em>authenticate the user</em><strong>without</strong> <em>a login screen?</em></p>
  </li>
  <li>
    <p><strong>How could we</strong> <em>generate a report</em><strong>without</strong> <em>having a way to populate the database?</em></p>
  </li>
  <li>
    <p><strong>How could we</strong> <em>show this information</em><strong>without</strong> <em>using charts?</em></p>
  </li>
</ul>

<p>Second and most important: make sure your team knows how to work with interfaces. This is paramount to avoid rework and breaking stuff.</p>

<p>Remember: in order to adapt to changes successfully, we must learn how to do that without increasing the development costs. Just like in MegaMan, the best path isn’t always the most obvious one - sometimes you need to fight Fireman before Iceman, and sometimes you need to build that scoring system before implementing the perfect word selection algorithm.</p>

<p>The Chronology Bias, much like its cousin the Stratification Bias, tricks us into following a predetermined path when we should be asking ourselves that simple yet powerful question: “<strong>What should we do next?</strong> “. After all, software development isn’t about completing levels in order - it’s about creating value in the most effective way possible.</p>

<p>Stay tuned for the final post in this series, where we’ll explore our last bias: <strong>Modularity</strong>.</p>

<p>Oh! And if you came this far, thanks for reading!</p>

<hr />

<p><em>Reflection Moment: Take a minute to think about a current project. What tasks are you doing in sequence simply because “that’s how it’s always been done”? How might you reorder them for better value delivery?</em></p>

<hr />
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="Bias" />
    
    <summary type="html">In my last post, I talked about how the habit of splitting software into layers can lead us to tackle one layer at a time, producing the undesired BDU...</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">The 3 biases of software development, part 1: Stratification</title>
    <link href="https://mariomelo.com/en/the-3-biases-of-software-development-part-1-stratification" rel="alternate" type="text/html" title="The 3 biases of software development, part 1: Stratification" />
    <published>2024-10-14T10:49:53+00:00</published>
    <updated>2024-10-14T10:49:53+00:00</updated>
    <id>https://mariomelo.com/the-3-biases-of-software-development-part-1-stratification</id>
    <content type="html" xml:base="https://mariomelo.com/the-3-biases-of-software-development-part-1-stratification">
      <![CDATA[<p>Recently, I spoke at the Regional Scrum Gathering Stockholm about the 3 biases of software development: Stratification, Chronology, and Modularity.</p>

<p>The event was awesome, as the organizers (Evelyn, Giuseppe, Khurram, and Thomas) and the volunteers did an amazing job putting it together. I left the event truly happy and with a lot of food for thought. That was my motivation to transform my presentation into three posts: one for each bias I described there.</p>

<h2 id="so-what-are-these-biases">So, what are these biases?</h2>

<p>A bias can be defined as “<em>A preference or an inclination, especially one that inhibits impartial judgment</em>”. In software development, that could be translated as modeling a software project using concepts that are hardwired in our brain, thus avoiding an alternative approach that could help us create something more flexible.</p>

<p>We do things this way because we’ve always done them this way. And that’s an infinite loop.</p>

<p>To break these biases, we must first understand them, so let’s start with the first one: <strong>Stratification</strong>.</p>

<h2 id="stratification">Stratification?</h2>

<p>Yep, I came up with these three names, and I’m not really satisfied with them. But, as Phil Karlton said: “<em>There are only two hard things in Computer Science: cache invalidation and naming things</em>”.</p>

<p>The stratification bias happens when, after splitting software into layers (let’s say: database, backend, and frontend), we immediately start to develop the basemost layer, which is often the database model. Picture this: you start with the database layer, meticulously crafting each table and relationship. Only when that’s “done” do you move on to the backend, and heaven forbid anyone mentions the frontend until the API is complete!</p>

<p>This is probably the most famous of the biases, as it’s long been coined as BDUF (Big Design Upfront) and was one of the first barriers we had to overcome to develop more flexible software. Sad thing is, it still happens. A lot.</p>

<p>There are two main problems with this approach. Number one: <strong>side-effects</strong>. A change in a single point of the uppermost layer could generate multiple changes in the lower layers.</p>

<p>Second problem: <strong>side-effects of side-effects, or bugs</strong>. Now, because you had to change the database, some part of the backend that is barely related to the initial change might be affected and also affect some frontend part that is <strong>completely unrelated</strong> to the initial change.</p>

<p><img src="../assets/images/posts/f72dc091ee58.jpeg" alt="Diagram showing side-effects of side-effects creating bugs" /></p>

<p>If you’ve been paying attention, you noticed that by fixing a bug you could trigger the exact same process again, which takes us to an infinite loop of despair, frustration and customer-angriness.</p>

<h2 id="am-i-a-victim-of-this-bias-how-do-i-escape-it">Am I a victim of this bias? How do I escape it?</h2>

<p>There are symptoms. Your customer won’t be able to provide valuable feedback because they won’t see anything usable, the amount of rework needed whenever you have to change something will be unbearable, and you might feel the urge to discard some nice ideas because of their development costs. Most importantly: your developers will be bored to death.</p>

<p>And just because this was the <em>status quo</em> not long ago, the bored developers back then decided to create something to help them out of this situation. Something that would allow the database to safely evolve over time without generating a lot of technical debt. They called it “<strong>Database Migrations</strong>”.</p>

<p>It’s beautiful, isn’t it? A technical solution created to solve a technical problem that was hindering the team’s capability to adapt to change. I’ll come back to this later after the technical example, so if you’re already familiar with the concept or if you’re not familiar with code, just skip the next section.</p>

<h2 id="getting-our-hands-dirty-with-code">Getting our hands dirty (with code)!</h2>

<p>Let’s take a look at a Database Migration using Elixir and Ecto. Imagine that you are creating a table to store the users of your system. You (and your customer) might have a lot of neat ideas of all the data you can store there: name, email, a short bio, an avatar, their birthday, and the list goes on and on.</p>

<p>If we understand that the database can evolve, we can start with something simpler. Just the username and the email, for example.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">MyApp</span><span class="o">.</span><span class="no">Repo</span><span class="o">.</span><span class="no">Migrations</span><span class="o">.</span><span class="no">CreateUsers</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">Ecto</span><span class="o">.</span><span class="no">Migration</span>

  <span class="k">def</span> <span class="n">change</span> <span class="k">do</span>
    <span class="n">create</span> <span class="n">table</span><span class="p">(</span><span class="ss">:users</span><span class="p">)</span> <span class="k">do</span>
      <span class="n">add</span> <span class="ss">:username</span><span class="p">,</span> <span class="ss">:string</span>
      <span class="n">add</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">:string</span>
      
      <span class="n">timestamps</span><span class="p">()</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Doing this first part will provide us with options for the next iteration. We can actually ask ourselves what is the most important thing to develop: the avatar? the short bio? something entirely different in another part of the system?</p>

<p>Later, if we decide to implement the user avatar and the short bio, we could just create another migration like this one:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">MyApp</span><span class="o">.</span><span class="no">Repo</span><span class="o">.</span><span class="no">Migrations</span><span class="o">.</span><span class="no">AddProfileToUsers</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">Ecto</span><span class="o">.</span><span class="no">Migration</span>

  <span class="k">def</span> <span class="n">change</span> <span class="k">do</span>
    <span class="n">alter</span> <span class="n">table</span><span class="p">(</span><span class="ss">:users</span><span class="p">)</span> <span class="k">do</span>
      <span class="n">add</span> <span class="ss">:bio</span><span class="p">,</span> <span class="ss">:text</span>
      <span class="n">add</span> <span class="ss">:avatar_url</span><span class="p">,</span> <span class="ss">:string</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>This way we can ensure that the customer’s database will always be up to date and that nobody will run the same database script twice and break the whole thing.</p>

<h1 id="there-are-technical-benefits-but-non-technical-as-well">There are technical benefits, but non-technical as well</h1>

<p>Besides the obvious benefit of creating something more flexible, there are some very interesting non-technical benefits as well. For example: because you built a lighter database, whatever the team needs to develop next will take less time just because there will be fewer fields and tables to deal with. This will also reflect on the amount of side-effects (aka bugs) your development process might generate, because the complexity of your software won’t grow exponentially like it did before. We could summarize that as: breaking the stratification bias equals saving time.</p>

<p>That time you saved could generate a butterfly effect. The team can now think about what to do with that time. Maybe learn how to write some unit tests, or take some time to experiment with a new technology. Because the answer to this question isn’t obvious, they’ll have to collaborate to find the best option. Note that everyone will have to collaborate: developers, designers, testers, business people.</p>

<p>This whole database migration concept was created because someone challenged the idea that “<strong>We cannot change the database as we please</strong>”. A technical person, with a technical solution. Because sometimes when a developer faces a challenge like this one and has the proper time and resources to deal with it, an innovation is born.</p>

<p>That’s also the case when we break the Chronology and the Modularity biases, but we’ll talk about them later. :)</p>

<hr />

<p><strong>Ps:</strong> If you want to read further about this subject, you can check Martin Fowler’s amazingly detailed blog post, here: &lt;https://martinfowler.com/articles/evodb.html</p>

]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="Bias" />
    
    <summary type="html">Recently, I spoke at the Regional Scrum Gathering Stockholm about the 3 biases of software development: Stratification, Chronology, and Modularity.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Information expires and specificity adds to its obsolescence</title>
    <link href="https://mariomelo.com/en/information-expires-and-specificity-adds-to-obsolescence" rel="alternate" type="text/html" title="Information expires and specificity adds to its obsolescence" />
    <published>2024-08-06T14:27:14+00:00</published>
    <updated>2024-08-06T14:27:14+00:00</updated>
    <id>https://mariomelo.com/information-expires-and-specificity-adds-to-obsolescence</id>
    <content type="html" xml:base="https://mariomelo.com/information-expires-and-specificity-adds-to-obsolescence">
      <![CDATA[<p>Imagine that you receive the following information: <strong>Lady Gaga is working on her next album</strong>.</p>

<p>If it’s true now, would it be true tomorrow? Probably. Chances are she’ll spend <strong>a couple months</strong> until she finishes the album, and the sentence will still be true during that period. However, if you receive a more specific information the scenario might change:</p>

<ul>
  <li><strong>Lady Gaga is working on the first song of her new album</strong></li>
</ul>

<p>For how long will this sentence be true? Maybe a couple of days or weeks.</p>

<ul>
  <li><strong>Lady Gaga is writing the lyrics for the first song of her new album</strong></li>
</ul>

<p>For how long will this sentence be true? Maybe a couple of days or hours.</p>

<ul>
  <li><strong>Lady Gaga is writing the chorus of her new album’s first song</strong></li>
</ul>

<p>For how long will this sentence be true? Maybe a couple of hours or even minutes.</p>

<p>When it comes to software, we could say the same. And Kent Beck recently reposted a nice article about that subject called “Software is Bananas” (link below).</p>

<p><a href="https://tidyfirst.substack.com/p/software-is-bananas?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web">Software Design: Tidy First? - Software Is Bananas</a></p>

<p>Thing is, different information in different contexts will have different “expiration dates”. Let’s say you have a problem, and you want to create a software product to solve that problem, so you formulate a hypothesis:</p>

<p><code class="language-plaintext highlighter-rouge">If this idea I have works, problem X will go away.</code></p>

<p>If you don’t implement your idea in, let’s say, 6 months, it might not make sense anymore even if the original problem still exists. It’s only natural: the problem is less volatile than the solution, because the later depends on the former.</p>

<p>But let’s say you decide to move forward and implement your idea. You then start to make notes on <strong>how to do it</strong> :</p>

<p><code class="language-plaintext highlighter-rouge">To implement this idea, I will do step X, step Y and step Z.</code></p>

<p>Same rule applies here. If you don’t follow the steps you established right away, you might decide to implement the very same idea in another way. The steps are more specific and therefore more volatile.</p>

<p>In summary, it’s ok to have a list of problems to solve as long as you don’t spend too much time thinking on how to solve many of them at a time. And it’s ok to discuss the implementation details of a handful of ideas, as long as you are really certain you’re going to implement them in the next few days.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Building" />
    
    <category term="Product" />
    
    <summary type="html">Imagine that you receive the following information: Lady Gaga is working on her next album.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">A reflection on my 20 years working with software development</title>
    <link href="https://mariomelo.com/en/a-reflection-on-my-20-years-of-software" rel="alternate" type="text/html" title="A reflection on my 20 years working with software development" />
    <published>2024-07-22T16:02:33+00:00</published>
    <updated>2024-07-22T16:02:33+00:00</updated>
    <id>https://mariomelo.com/a-reflection-on-my-20-years-of-software</id>
    <content type="html" xml:base="https://mariomelo.com/a-reflection-on-my-20-years-of-software">
      <![CDATA[<p>I received my first paycheck as a software developer in July 2004. It’s been 20 years now.</p>

<p>During these years I’ve been a developer, a business owner, a consultant, a trainer, and learned (mainly by making mistakes) many things about both the technical and the social side of software development.</p>

<p>What I wrote down here is based on what I lived in this market, which means: it’s based on many years of experience, but it’s also biased by these same experiences. But as I’ve seen things changing and some things not changing, I’d like to try to elaborate my reasoning on what are the causes and consequences of these outcomes.</p>

<p>So, let’s start!</p>

<h2 id="what-changed-in-20-years">What changed in 20 years?</h2>

<p>Well… Obviously, <strong>technology changed.</strong> And with that, everything changed.</p>

<p>When I started programming we didn’t have iPhones or Android phones, and curiously enough I was working with mobile computing. Pocket PC 2002 was the operational system and I was writing C++ code that needed to be highly optimized because of all the memory restrictions we had back then.</p>

<p><img src="../assets/images/posts/718c3cc53b95.jpeg" alt="Intermec mobile computers" /><em>Mobile in 2000’s: These devices could make the Nokia 3310 seem fragile</em></p>

<p>But most importantly: the <strong>organizations changed</strong>. And most of the changes I saw were caused by technology innovations.</p>

<h4 id="complicated-then-simpler-then-complex"><strong>Complicated, then simpler, then complex</strong></h4>

<p>If you ever wrote a web application using J2EE and Enterprise Beans you can remember how bureaucratic it was. The deployment wasn’t straightforward, we needed to write a lot of code to do the simplest thing and changes of a database schema were a nightmare. The thing was we were mostly creating private web applications because the web wasn’t what it is today (not even Orkut had been created back then).</p>

<p>At first, these pain points incentivized organizations to push for <strong>bigger teams</strong>, a specialized <strong>database management department</strong> and also an <strong>operations department</strong>.</p>

<p>On the other hand, developers started to create tools to solve these pain points: ORM frameworks such as Hibernate started to become popular, then frameworks such as Rails started to introduce easier ways to create evolutionary databases and also a more direct approach to create a web application.</p>

<p>These changes empowered the developers and allowed small teams to be even more productive than big corporate teams were. With that we saw a shift in the market: everybody wanted smaller teams with the so called Full-stack Developers. Cloud computing was available for everyone for less than US$5/month with Heroku, DigitalOcean and AWS, and a lot of startups started to pop up everywhere.</p>

<p><strong>But then… everything changed.</strong></p>

<p>The web evolved and what was a simple REQUEST/RESPONSE with HTML and CSS became a complex puzzle using Ajax, jQuery, and then Angular, Ember, React, Vue, Svelte. The companies started to require <strong>frontend</strong> <strong>developers</strong>.</p>

<p>On the backend, things got even more complex. The giants in the industry were facing the challenges caused by their own success: how to handle such a massive amount of simultaneous users? How to store efficiently store this massive amount of data?</p>

<p>Then again, the developers came to the rescue and created solutions such as Docker, Kubernetes, Grafana. The giants shared their success stories and the medium-sized companies decided to add all this complexity to their products in order to achieve the same results. In part, this movement was also caused by the developers: we wanted to work with the cutting-edge technology used by the giants of the market, even if it was clearly not necessary for our servers that were handling way less users than Google or Facebook.</p>

<p>Developing a simple software felt… unnecessarily complex. Most companies I worked with back then weren’t creating products for the masses, but niche products with little to no necessity of such complexity. And that’s actually when I started to work more with consultancy and training again. I was constantly advocating for simpler models whenever they were good enough.</p>

<p>I still am.</p>

<h2 id="what-didnt-change-in-20-years">What didn’t change in 20 years?</h2>

<p>Many things:</p>

<ul>
  <li>
    <p>We still need software developers</p>
  </li>
  <li>
    <p>People are still trying to figure out how to measure productivity in the software development field</p>
  </li>
  <li>
    <p>Estimates are still a problem for most people</p>
  </li>
  <li>
    <p>People are still arguing over which is the best text editor/IDE/framework/language</p>
  </li>
  <li>
    <p>And well… <strong>software development still brings me joy</strong> :)</p>
  </li>
</ul>

<p>I don’t feel I said everything I wanted to say. I still need to reflect more on how I changed during these 20 years.</p>

<p>Maybe I’ll write more about that in the future.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Building" />
    
    <category term="Career" />
    
    <summary type="html">I received my first paycheck as a software developer in July 2004.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Dependencies: Libraries or OTP applications</title>
    <link href="https://mariomelo.com/en/dependencies-libraries-or-otp-applications" rel="alternate" type="text/html" title="Dependencies: Libraries or OTP applications" />
    <published>2024-07-18T08:51:08+00:00</published>
    <updated>2024-07-18T08:51:08+00:00</updated>
    <id>https://mariomelo.com/dependencies-libraries-or-otp-applications</id>
    <content type="html" xml:base="https://mariomelo.com/dependencies-libraries-or-otp-applications">
      <![CDATA[<h2 id="the-project-scrumchkin-online">The project: Scrumchkin Online</h2>

<p>About a year ago I created a card game to teach Scrum: <a href="http://scrumchkin.com">Scrumchkin</a>. The game made the learning process more fun and was adopted by <em>Scrum Trainers</em> from several countries, until the pandemic made any in-person class unfeasible.</p>

<p>And that’s where my personal project came from: creating an online version of Scrumchkin. Which would be a great opportunity to play and learn more about <em>Phoenix Liveview</em>.</p>

<p>Initially, I thought of the following structure for the project:</p>

<p>This way, it would be possible to create games in separate processes and have a registry with unique identifiers for each game so that each match could be accessed through a different URL.</p>

<p>Example:</p>

<ul>
  <li>
    <p>The user accesses the URL <code class="language-plaintext highlighter-rouge">http://scrumchkin.com/game/abc123</code></p>
  </li>
  <li>
    <p>The web application asks the Game Registry where game <code class="language-plaintext highlighter-rouge">abc123</code> is</p>
  </li>
  <li>
    <p>The Game Registry finds the PID of the match and returns it to the web application</p>
  </li>
</ul>

<h3 id="the-game-registry-as-a-library">The Game Registry as a library</h3>

<p>Keeping in mind the <strong>single responsibility principle</strong>, the design above makes evident the existence of 3 different projects: The Game Registry, the Game Server and the Web Interface.</p>

<p><em>The next paragraphs will talk about some technical aspects of Elixir as a curiosity. If you just want to understand the difference between a library and an OTP application feel free to skip this part</em> :)</p>

<p>Technically the Game Registry is extremely simple: it links a unique ID to a match. It’s basically a dictionary that has a <em>UUID</em> as key and a <em>PID</em> of a GenServer as value for a match.</p>

<p>Initially, I created the Game Registry as a library capable of performing CRUD operations on an <em>ets table</em>:</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">GameRegister</span> <span class="k">do</span>
  <span class="k">def</span> <span class="n">init</span><span class="p">()</span> <span class="k">do</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">,</span> <span class="p">[</span><span class="ss">:set</span><span class="p">,</span> <span class="ss">:public</span><span class="p">,</span> <span class="ss">:named_table</span><span class="p">])</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">save</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">key</span> <span class="o">=</span> <span class="no">UUID</span><span class="o">.</span><span class="n">uuid1</span><span class="p">()</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">insert_new</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">,</span> <span class="p">{</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">})</span>
    <span class="n">key</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">delete</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="k">do</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="k">do</span>
    <span class="ss">:scrumchkin</span>
    <span class="o">|&gt;</span> <span class="ss">:ets</span><span class="o">.</span><span class="n">lookup</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
    <span class="o">|&gt;</span> <span class="n">format_result</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">list_all</span> <span class="k">do</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">tab2list</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">defp</span> <span class="n">format_result</span><span class="p">([]),</span> <span class="k">do</span><span class="p">:</span> <span class="p">{</span><span class="ss">:error</span><span class="p">,</span> <span class="s2">"Game not found"</span><span class="p">}</span>

  <span class="k">defp</span> <span class="n">format_result</span><span class="p">(</span><span class="n">item_list</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">item_list</span>
    <span class="o">|&gt;</span> <span class="n">hd</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p><strong>TL;DR</strong> - The library stores the current state of matches and links them to an identifier code. It is capable of listing, getting, saving and deleting matches from the registry.</p>

<h3 id="a-small-problem">A small problem</h3>

<p>For me to use the ets table, it needed to exist. This means that at some point the <code class="language-plaintext highlighter-rouge">init</code> function from the code above would need to be called by my web application.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="k">def</span> <span class="n">init</span><span class="p">()</span> <span class="k">do</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">,</span> <span class="p">[</span><span class="ss">:set</span><span class="p">,</span> <span class="ss">:public</span><span class="p">,</span> <span class="ss">:named_table</span><span class="p">])</span>
  <span class="k">end</span>
</code></pre></div></div>

<p>But this goes against the single responsibility principle I used to divide this project into smaller parts, right?</p>

<h3 id="the-registry-as-an-application">The Registry as an application</h3>

<p>But what is a dependency as a library? It’s a gear that’s part of a whole; something very similar to a Lego piece. We know where the pins and holes are and we use it to build something bigger.</p>

<p><img src="../assets/images/posts/0b40ff6369e6.png" alt="Dependencies as Libraries" /><em>The dependency on an OTP application is a bit different.</em></p>

<p>Think of a car. Usually, cars have an engine cooling mechanism that starts when you turn the key and start the car. The car depends on this mechanism to work, but it’s somewhat independent: many times it’s activated when we turn off the car (that fan noise that comes from under the hood, especially on hot days).</p>

<p>This cooling mechanism has interfaces with the car’s engine, but controls its own state. There’s a clear relationship of <strong>dependency</strong>, but not of control. The engine depends on the cooling system not to overheat, but doesn’t control it.</p>

<p>And the same needed to happen with my Game Registry, which ended up like this:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">GameRegister</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">GenServer</span>

  <span class="k">def</span> <span class="n">start_link</span><span class="p">(</span><span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">start_link</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="ss">name:</span> <span class="bp">__MODULE__</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">init</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="k">do</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">,</span> <span class="p">[</span><span class="ss">:set</span><span class="p">,</span> <span class="ss">:public</span><span class="p">,</span> <span class="ss">:named_table</span><span class="p">])</span>
    <span class="no">IO</span><span class="o">.</span><span class="n">puts</span><span class="p">(</span><span class="s2">"Scrumchkin table created"</span><span class="p">)</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">stack</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:save</span><span class="p">,</span> <span class="n">game</span><span class="p">},</span> <span class="n">_from</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">key</span> <span class="o">=</span> <span class="no">UUID</span><span class="o">.</span><span class="n">uuid1</span><span class="p">()</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">insert_new</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">,</span> <span class="p">{</span><span class="n">key</span><span class="p">,</span> <span class="n">game</span><span class="p">})</span>
    <span class="p">{</span><span class="ss">:reply</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:delete</span><span class="p">,</span> <span class="n">game_id</span><span class="p">},</span> <span class="n">_from</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="ss">:ets</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">,</span> <span class="n">game_id</span><span class="p">)</span>
    <span class="p">{</span><span class="ss">:reply</span><span class="p">,</span> <span class="ss">:ok</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:get</span><span class="p">,</span> <span class="n">game_id</span><span class="p">},</span> <span class="n">_from</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">result</span> <span class="o">=</span>
      <span class="ss">:scrumchkin</span>
      <span class="o">|&gt;</span> <span class="ss">:ets</span><span class="o">.</span><span class="n">lookup</span><span class="p">(</span><span class="n">game_id</span><span class="p">)</span>
      <span class="o">|&gt;</span> <span class="n">format_result</span>

    <span class="p">{</span><span class="ss">:reply</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">handle_call</span><span class="p">(</span><span class="ss">:list_all</span><span class="p">,</span> <span class="n">_from</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">{</span><span class="ss">:reply</span><span class="p">,</span> <span class="ss">:ets</span><span class="o">.</span><span class="n">tab2list</span><span class="p">(</span><span class="ss">:scrumchkin</span><span class="p">),</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">save</span><span class="p">(</span><span class="n">game</span><span class="p">)</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="p">{</span><span class="ss">:save</span><span class="p">,</span> <span class="n">game</span><span class="p">})</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">delete</span><span class="p">(</span><span class="n">game_id</span><span class="p">)</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="p">{</span><span class="ss">:delete</span><span class="p">,</span> <span class="n">game_id</span><span class="p">})</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">get</span><span class="p">(</span><span class="n">game_id</span><span class="p">)</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="p">{</span><span class="ss">:get</span><span class="p">,</span> <span class="n">game_id</span><span class="p">})</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">list_all</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="ss">:list_all</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">defp</span> <span class="n">format_result</span><span class="p">([]),</span> <span class="k">do</span><span class="p">:</span> <span class="p">{</span><span class="ss">:error</span><span class="p">,</span> <span class="s2">"Game not found"</span><span class="p">}</span>

  <span class="k">defp</span> <span class="n">format_result</span><span class="p">(</span><span class="n">item_list</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">item_list</span>
    <span class="o">|&gt;</span> <span class="n">hd</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<h3 id="but-what-changes">But… what changes?</h3>

<p>My web application is not responsible for creating the ets table. It just says it depends on the Game Registry and that it’s now an <strong>extra application</strong>.</p>

<p>The change in the <code class="language-plaintext highlighter-rouge">mix.exs</code> file is simple:</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="k">def</span> <span class="n">application</span> <span class="k">do</span>
    <span class="p">[</span>
      <span class="ss">mod:</span> <span class="p">{</span><span class="no">Scrumchkin</span><span class="o">.</span><span class="no">Application</span><span class="p">,</span> <span class="p">[]},</span>
      <span class="ss">extra_applications:</span> <span class="p">[</span><span class="ss">:logger</span><span class="p">,</span> <span class="ss">:runtime_tools</span><span class="p">,</span> <span class="ss">:game_register</span><span class="p">,</span> <span class="ss">:game_engine</span><span class="p">]</span>
    <span class="p">]</span>
  <span class="k">end</span>
  <span class="k">defp</span> <span class="n">deps</span> <span class="k">do</span>
    <span class="p">[</span>
      <span class="p">{</span><span class="ss">:game_engine</span><span class="p">,</span> <span class="ss">path:</span> <span class="s2">"../game_engine"</span><span class="p">},</span>
      <span class="p">{</span><span class="ss">:game_register</span><span class="p">,</span> <span class="ss">path:</span> <span class="s2">"../game_register"</span><span class="p">}</span>
    <span class="p">]</span>
  <span class="k">end</span>
</code></pre></div></div>

<p>Now, every time I start my application with <code class="language-plaintext highlighter-rouge">mix phx.server</code>, my game registry is automatically started and takes on the responsibility of creating the ets table where it will store the PIDs of Scrumchkin matches.</p>

<p>My web application <strong>depends</strong> on the Game Registry, but trusts that it can solve its problems on its own.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="Elixir" />
    
    <summary type="html">The project: Scrumchkin Online</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">The dangerous failure shaming culture</title>
    <link href="https://mariomelo.com/en/the-dangerous-failure-shaming-culture" rel="alternate" type="text/html" title="The dangerous failure shaming culture" />
    <published>2024-07-17T11:38:54+00:00</published>
    <updated>2024-07-17T11:38:54+00:00</updated>
    <id>https://mariomelo.com/the-dangerous-failure-shaming-culture</id>
    <content type="html" xml:base="https://mariomelo.com/the-dangerous-failure-shaming-culture">
      <![CDATA[<p>Michael Caine as Alfred Pennyworth</p>

<p><strong>Disclaimer</strong> : this post was first written in March 24th, 2014 and published on Medium. I think it’s still pretty relevant (maybe with some old song references here and there), so I brought it here as well.</p>

<h1 id="to-err-or-not-to-err">To err or not to err</h1>

<p><em>As humans, we’re all error prone. But some refuse to accept that.</em></p>

<p>You give your best at something just to find out it didn’t go as well as you planned. Is there some kind of punishment on the way?</p>

<h1 id="failure-shaming-environments">Failure-shaming environments</h1>

<p>Whatever your answer might be, it was at least in part created by the environments you lived so far. Were you free to <strong>fail</strong> when you were young? Do you work on a company where people get punished when they make <strong>mistakes</strong>? Are you confortable facing people you’ve <strong>let down</strong>?</p>

<p>A failure-shaming environment is a place where no one is allowed to fail, because if they do, they’ll suffer some kind of harsh penalty. Like being fired by your boss, hit by your parents or even left by your significant other. Pick your flavor.</p>

<blockquote>
  <p>You’re wrong. Shame on you.</p>

  <p><cite>- Ourselves </cite></p>
</blockquote>

<p>If you’ve ever experienced this kind of environment (and chances are that you did), you know how hard you must think before taking a single step forward. Or backward. You need to think and rethink each move because if you fail there’s somtehing bad awaiting for you.</p>

<h1 id="failure-shaming-consequences">Failure-shaming consequences</h1>

<p>Well, <em>if you look in the face of evil evil’s gonna look right back at you,</em> and by not being allowed to fail you might start to <strong>hate</strong> when people fail you.</p>

<p>That happened to me, and as I started to reverse this process I became able to perceive some consequences of this kind of culture.</p>

<h2 id="stagnation">Stagnation</h2>

<p>We often evolve by trial and error. We accept concepts learnt by practice quicker than by theory.</p>

<blockquote>
  <p>Why do we fall sir? So that we can learn to pick ourselves up.</p>

  <p><cite>— Alfred Pennyworth</cite></p>
</blockquote>

<p>Where I work, we’re constantly trying new things and brainstorming. No matter what comes to mind, everybody feels free to speak up anything to anyone. Failures are tolerable as long as we learn something from them, and that makes us evolve much quicker than one would expect.</p>

<p>If nobody had this freedom to fail, my coworkers would lose the autonomy and self-confidence to try their own ideas and we’d be stuck in 2011.</p>

<h2 id="procrastination">Procrastination</h2>

<p>I can’t fail so I need to work on that until it’s perfect, no matter how much time it takes.</p>

<blockquote>
  <p>I wanna a new mistake, losing is more than hesitate.</p>

  <p><cite>— Queens of the Stone Age</cite></p>
</blockquote>

<p>I once worked on a project that aimed to improve a certain company’s indicator to something above 90%. After 5 months, the project could improve this indicator from 10% to something above 65% <strong>if it were deployed</strong>. The responsibles didn’t want to deploy it as it was and kept looking for ways to improve that 65% to the desired 90% for <strong>2 freaking years</strong>.</p>

<p>For 2 years the company had 10% on something it could’ve had 65% because nobody wanted to say <em>Hey, I couldn’t deliver 90%, but let’s start with 65% and grow from that</em>. Chances are that if they tried, they could have figured out how to reach more than 90% in less than 2 years.</p>

<p>So, if you fail fast, you’ll evolve faster.</p>

<h2 id="lies-and-apathy">Lies and Apathy</h2>

<p>Everything is on fire, but nobody will step up to do anything. By the way, the fire-starter was thrown away because it could make someone look guilty.</p>

<blockquote>
  <p>It wasn’t me</p>

  <p><cite> — Shaggy (and 94.7% of the humanity) </cite></p>
</blockquote>

<p>It’s hard to find someone with more information about a problem than the person who first created it. If this person feels confortable enough to assume it, her/his help can be the key to fix the problem. However, if there’s no space for that a lot of important things will stay under the carpet.</p>

<p>I try to have <em>retrospective meetings</em> with my coworkers periodically. It’s healthy to have an open debate about our own flaws and to seek improvements together no matter the subject.</p>

<h1 id="tldr">TL;DR</h1>

<p>Fight for your right to make mistakes, give a try to your ideas without being afraid to fail and don’t be a bitch when you see someone else failing, even if that hurts you.</p>

<p>If you ever find yourself in a hard situation occasioned by a mistake you’ve made, take a look at <a href="https://medium.com/p/49fc07093fde/www.experienceproject.com">www.experienceproject.com</a>. You’ll find a lot of friendly people like you sharing their experiences in a very open way.</p>

<p>That’s it. Keep on failing. ☺</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Teamwork" />
    
    <category term="Culture" />
    
    <summary type="html">Michael Caine as Alfred Pennyworth</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Property based testing and the R$17.99 transfer problem</title>
    <link href="https://mariomelo.com/en/property-based-testing-and-the-17-99-transfer-problem" rel="alternate" type="text/html" title="Property based testing and the R$17.99 transfer problem" />
    <published>2022-03-28T14:48:26+00:00</published>
    <updated>2022-03-28T14:48:26+00:00</updated>
    <id>https://mariomelo.com/property-based-testing-and-the-17-99-transfer-problem</id>
    <content type="html" xml:base="https://mariomelo.com/property-based-testing-and-the-17-99-transfer-problem">
      <![CDATA[<p>A few weeks ago someone discovered that their bank would not allow them to make a bank transfer of a very specific value: <strong>R$17.99</strong> (about $3.50 USD). What happened? The bank automatically converted the transferred value to <strong>R$17.98</strong>.</p>

<p>The most curious thing is that transfers of other values worked perfectly. Well, almost all. People started discovering other specific cases where the problem occurred: <strong>R$32.23</strong> or <strong>R$155.17</strong>.</p>

<p>The idea of this post is not to debate the cause of the problem, but to show a technique that can help teams detect similar problems.</p>

<p>The text includes some code in Elixir, but also includes illustrations to explain each concept. The goal is to make this content useful for both technical and non-technical people.</p>

<h3 id="would-unit-tests-help-well-not-exactly">Would unit tests help? Well… not exactly.</h3>

<p>Don’t get me wrong: I’m a fan of unit tests and I (<em>almost</em>) always practice TDD.</p>

<p>But a conventional test for a money transfer function would probably be something similar to the example below:</p>

<script src="https://gist.github.com/mariomelo/56fa58d3515bc5c78afff7a24ded0dc6.js"></script>

<p>Isn’t it too specific?</p>

<p>Notice that the test where the transfer is possible focuses on only one case: a transfer of <strong>R$25.00</strong>. And in this case, the tests are a success:</p>

<p><img src="../assets/images/posts/e55bd026f55a.png" alt="Tests passing successfully" /></p>

<h3 id="but-we-can-write-a-test-for-the-r1799-case-right">But we can write a test for the R$17.99 case, right?</h3>

<p>Sure! <strong>After knowing about the existence of the error</strong> we could include an additional test to ensure that bank transfers of R$17.99 can also be made:</p>

<script src="https://gist.github.com/mariomelo/b3fab52e0eebccdbbe77afdfb9cdc55f.js"></script>

<p>Here we can put the famous TDD cycle (<em>Test Driven Development</em>) into action: <strong>Red, Green, Refactor.</strong></p>

<p><img src="../assets/images/posts/a1cf3f1ae6aa.jpeg" alt="TDD Red, Green, Refactor cycle" /></p>

<p>This test fails (<strong>RED</strong>), and then we can fix the problem until the test passes (<strong>GREEN</strong>). And now, having the test as a safety net we can alter the code to make it more readable without fear of breaking anything (<strong>REFACTOR</strong>).</p>

<p><img src="../assets/images/posts/6fcf1901980a.png" alt="Failing test showing balance difference" /><em>The test fails because the remaining balance was R$2.02 and not R$2.01</em></p>

<p>Done! Now when we make this test pass we’ll ensure that transfers of R$17.99 will work perfectly. But some questions remain:</p>

<ul>
  <li>
    <p>Will the transfer of <strong>R$32.23</strong> work?</p>
  </li>
  <li>
    <p>What if there are other values that generate the same error?</p>
  </li>
  <li>
    <p>What if there are values that generate a different error?</p>
  </li>
  <li>
    <p>How can we prevent problems like this from reaching our customers?</p>
  </li>
</ul>

<p>And that’s where PBT comes in — Property Based Testing.</p>

<h3 id="pbt-cleaning-where-conventional-tests-cant-reach">PBT: cleaning where conventional tests can’t reach</h3>

<p>It’s quite simple to write the R$17.99 test <strong>after</strong> we know about the existence of the error.</p>

<p><img src="../assets/images/posts/3dcaa4913450.jpeg" alt="Illustration about writing tests after discovering the error" /></p>

<p>What happens is that we write tests with cases we already have in mind, in a very <strong>linear and specific</strong> manner. But the test is so specific that it tests only one case. What if the problem continues to happen with transfers of other values?</p>

<p><img src="../assets/images/posts/52d6e20585be.png" alt="Test showing problem with R$6.05 transfer" /><em>In this case, the problem appeared only when trying to transfer R$6.05</em></p>

<p>But… how could we identify problematic values <strong>before even knowing about the problem</strong>? That’s where property-based tests come in.</p>

<p>Working with properties means not thinking about specific cases, but rather the characteristics of each variable involved in the test. In this case, we can say that:</p>

<ul>
  <li>
    <p>The initial balance of whoever is going to transfer the money can be <strong>any value greater than zero</strong>.</p>
  </li>
  <li>
    <p>The transfer value is <strong>greater than zero and less than or equal to the available balance.</strong></p>
  </li>
</ul>

<p><img src="../assets/images/posts/ad110b85f0ac.jpeg" alt="Illustration about test properties" /></p>

<p>To know if the transfer was made with the correct values, we just need to “check our work”, as we did in elementary school. :)</p>

<blockquote>
  <p><strong>Transferred value + Remaining balance = Balance before transfer</strong></p>
</blockquote>

<p>When we define the rules this way, automated testing tools are able to validate several different cases. And many times these “different cases” end up including situations we never even imagined, and therefore would never write a conventional test about them.</p>

<script src="https://gist.github.com/mariomelo/320463a24d236fd1c1f634951431f42c.js"></script>

<p>Now, when running the tests we discover that there are other values that also generate the error:</p>

<p><img src="../assets/images/posts/2df433c8c4e5.png" alt="PBT test detecting error with different values" /><em>Oops! If I have R$0.98 and try to transfer R$0.71 the problem also happens!</em></p>

<p>Ah! Notice that the testing library says: <strong>Counter example stored</strong>.</p>

<p>PBT libraries usually store the values that generated errors and use them again until the problem is fixed. That is, when the test passes it’s because the problem was solved, and not because the library selected only values for which the problem doesn’t occur.</p>

<h3 id="okay-but-what-does-this-have-to-do-with-agility">Okay, but what does this have to do with agility?</h3>

<p>Well, agility is the ability to change and generate results quickly.</p>

<p>It’s like being in a race car on a winding track: to take curves quickly and without losing much speed you’ll need a solid and well-built vehicle. Without it, you’re limited to two options:</p>

<ul>
  <li>
    <p>Take the curve veeeery slowly to ensure the vehicle doesn’t break</p>
  </li>
  <li>
    <p>Take the curve quickly and dismantle your vehicle</p>
  </li>
</ul>

<p><strong>Example:</strong></p>

<p>Imagine the bank decided to allow Bitcoin accounts. They would now have to work with a currency that has way more than two decimal places.</p>

<p>Now imagine the bank can have an application that:</p>

<p>a) Has no automated tests</p>

<p>b) Has some automated tests</p>

<p>c) Has conventional automated tests and some using PBT</p>

<p>In which scenario would the bank be able to have a functional product in production more quickly?</p>

<p>In summary: <strong>There is no agility without technical excellence.</strong></p>

<h3 id="source-code-and-final-considerations">Source Code and final considerations</h3>

<p>I wrote the code to generate the error on purpose and thus illustrate how a certain technique could help solve a problem.</p>

<p>If you’re curious, the code used in this post is available at: <a href="https://github.com/mariomelo/post_pbt">https://github.com/mariomelo/post_pbt</a></p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Coding" />
    
    <category term="Testing" />
    
    <summary type="html">A few weeks ago someone discovered that their bank would not allow them to make a bank transfer of a very specific value: R$17.99 (about $3.50 USD).</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">3 fake news you may have heard about Scrum</title>
    <link href="https://mariomelo.com/en/3-fake-news-you-may-have-heard-about-scrum" rel="alternate" type="text/html" title="3 fake news you may have heard about Scrum" />
    <published>2022-02-09T15:30:31+00:00</published>
    <updated>2022-02-09T15:30:31+00:00</updated>
    <id>https://mariomelo.com/3-fake-news-you-may-have-heard-about-scrum</id>
    <content type="html" xml:base="https://mariomelo.com/3-fake-news-you-may-have-heard-about-scrum">
      <![CDATA[<p>Scrum has become absurdly popular, and a good part of this popularity is due to its simplicity. But, as the Scrum Guide stated in its first lines of the 2017 version:</p>

<blockquote>
  <p>Scrum is simple to understand, but difficult to master</p>

  <p><cite>- Scrum Guide, 2017 version</cite></p>
</blockquote>

<p>In other words, there’s a universe of distance between understanding Scrum and truly mastering it. And that’s where the danger lies: this distance is the perfect habitat for victims of the <a href="https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect">Dunning-Kruger effect</a>.</p>

<p><img src="../assets/images/posts/cd04250d7c4b.jpeg" alt="Dunning-Kruger effect graph" /><em>Image created by <a href="http://www.investificar.com.br">www.investificar.com.br</a></em></p>

<p><strong>From Wikipedia:</strong> <em>The Dunning–Kruger effect is a cognitive bias in which people with limited competence in a particular domain overestimate their abilities. Some researchers also include the opposite effect for high performers: their tendency to underestimate their skills.</em></p>

<p>That said, let’s get to the three fake news!</p>

<h3 id="1--the-problem-with-scrum-is-that-its-too-simple">1 — The problem with Scrum is that it’s too simple</h3>

<p>Scrum is a framework, but it’s common to hear people refer to Scrum as a methodology. It may seem like nitpicking, but this simple word swap says a lot about the understanding of Scrum.</p>

<p>After all, what is a framework? Well, according to the <a href="https://dictionary.cambridge.org/dictionary/english/framework">Cambridge dictionary</a>:</p>

<blockquote>
  <p><strong>A supporting structure around which something can be built</strong></p>

  <p><cite>- Cambridge Dictionary</cite></p>
</blockquote>

<p>Scrum is a structure upon which you should build your way of working. It’s like <a href="https://rubyonrails.org/">Ruby on Rails</a>, <a href="https://expressjs.com/">ExpressJS</a> or <a href="http://hibernate.org/">Hibernate</a>: they don’t work alone, but they help you work in a more structured and productive way.</p>

<p><strong>Frameworks are incomplete by default and on purpose</strong>. They are created so you can think and expand them in the way that makes the most sense in your work context. And that’s where agile practices like Story Points, User Story Mapping, Risk x Value Prioritization, User Stories, etc. come from.</p>

<p><img src="../assets/images/posts/5a054b71daa0.png" alt="Illustration of agile practices complementing Scrum" /></p>

<p>As Scrum implements the <a href="https://en.wikipedia.org/wiki/PDCA">PDCA</a> cycle, it’s possible to adopt a certain agile practice, validate its effects and decide whether it’s worth continuing with that practice. And of course, it’s necessary to experiment with new ideas and repeat this reflection at the end of each Sprint.</p>

<p><strong>In summary:</strong></p>

<p>Scrum is simple and incomplete on purpose to make you think of ways to complement it.</p>

<p>If someone tells you that the problem with Scrum is being too simple, this person hasn’t understood anything about the framework yet.</p>

<h3 id="2--management-30-and-devops-came-to-replace-scrum">2 — Management 3.0 and DevOps came to replace Scrum</h3>

<p>In Minas Gerais (a state in Brazil) we have a commonly used expression when someone says something like this:</p>

<p><em><strong>WHAT???</strong></em> — Translation: excuse me, what did you just say?</p>

<p>This statement makes no sense if you’ve already understood the concept of a framework: Management 3.0 and DevOps come to complement, not to replace.</p>

<p><a href="https://scrumguides.org/scrum-guide.html">After all, the Scrum Guide says:</a></p>

<blockquote>
  <p>Scrum Teams are cross-functional, meaning the members have all the skills necessary to create value each Sprint.</p>

  <p><cite> - Scrum Guide</cite></p>
</blockquote>

<p>Yes, Scrum doesn’t talk about automating deploys, for example. It doesn’t talk about feedback wraps, delegation boards or intrinsic motivators.</p>

<p>Because Scrum is a… <strong>framework</strong>!</p>

<p>I believe that this visual representation used by <a href="https://twitter.com/axmagno">Alexandre Magno</a> in his training sessions illustrates this idea very well.</p>

<p><img src="../assets/images/posts/e3337e8091b0.jpeg" alt="Diagram of Scrum framework with emerging techniques" /><em>Representation of the Scrum framework completed by emerging techniques, created by Alexandre Magno</em></p>

<h3 id="3--we-dont-have-scrum-teams-anymore-we-have-squads">3 — We don’t have Scrum teams anymore. We have Squads.</h3>

<p>This one is quite interesting, and I added it here because I increasingly see organizations using terms from the famous Spotify model. And often the justification is that the teams are multidisciplinary and not segmented by areas of knowledge.</p>

<p>But, what does the <a href="https://scrumguides.org/scrum-guide.html">Scrum Guide</a> say about its <em>Scrum Team</em>?</p>

<ul>
  <li>
    <p><em>Scrum Teams</em> are cross-functional, meaning the members have all the skills necessary to create value each Sprint.</p>
  </li>
  <li>
    <p>Within a <em>Scrum Team</em>, there are no sub-teams or hierarchies. It is a cohesive unit of professionals focused on one objective at a time, the Product Goal.</p>
  </li>
</ul>

<p>The concept of Squads was born collaboratively at Spotify and was partially documented in 2012 in this pdf by <a href="https://twitter.com/henrikkniberg">Henrik Kniberg</a> and <a href="https://twitter.com/anders_ivarsson">Anders Ivarsson</a>. In the document, <a href="https://blog.crisp.se/wp-content/uploads/2012/11/SpotifyScaling.pdf">available at this link</a>, they say:</p>

<p><em>A Squad is similar to a Scrum team, and is designed to feel like a mini-startup. They sit together, and they have all the skills and tools needed to design, develop, test, and release to production. They are a self-organizing team and decide their own way of working.</em></p>

<p>It’s always worth reflecting on the model adopted by the organization:</p>

<ul>
  <li>
    <p>Does your Scrum Team have the characteristics mentioned in the Scrum Guide?</p>
  </li>
  <li>
    <p>Does your organization provide the necessary environment for the existence of Squads/Scrum Teams?</p>
  </li>
  <li>
    <p>What problem is being addressed with the adoption of Squads?</p>
  </li>
  <li>
    <p>What differentiates your Squad from a Scrum Team?</p>
  </li>
</ul>

<p>Squads made sense in Spotify’s scaling context, and they might even be compatible with your organization. But it’s essential to understand which problems Scrum and the “Spotify Model” try to solve before doing a CTRL+C / CTRL+V.</p>

<p>At the end of the day, misinformation will always exist and eventually people can spread it even with the best of intentions. The only way I know to avoid these traps is to follow the advice of the wise philosopher E.T. Bilu:</p>

<p><img src="../assets/images/posts/a88da506696d.png" alt="E.T. Bilu meme saying seek knowledge" /><em>E.T. Bilu would read the Scrum Guide before starting to use Scrum</em></p>

<p>So, shall we take some time to reread the <a href="https://scrumguides.org/scrum-guide.html">16 pages of the Scrum Guide</a>?</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Teamwork" />
    
    <category term="Scrum" />
    
    <summary type="html">Scrum has become absurdly popular, and a good part of this popularity is due to its simplicity.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Prioritization with cost of delay</title>
    <link href="https://mariomelo.com/en/prioritization-with-cost-of-delay" rel="alternate" type="text/html" title="Prioritization with cost of delay" />
    <published>2022-02-08T16:42:37+00:00</published>
    <updated>2022-02-08T16:42:37+00:00</updated>
    <id>https://mariomelo.com/prioritization-with-cost-of-delay</id>
    <content type="html" xml:base="https://mariomelo.com/prioritization-with-cost-of-delay">
      <![CDATA[<p>Prioritizing is one of the most important and difficult activities in any Product Owner’s life. Most of the time the difficulty in prioritizing occurs because people have different <em><strong>opinions</strong></em> about the impacts that each Product Backlog item can have on the final product.</p>

<p>Well, and that’s the problem. Prioritization based on <em><strong>opinions</strong></em> (which usually have a weight proportional to the weight of the badge of whoever is opining). When we somehow manage to tangibilize the value of each item in our Product Backlog, the discussion becomes much more rational.</p>

<p>One way to better understand the value of each feature comes through a simple question: <strong>how much are we losing by not having delivered this item yet?</strong></p>

<p>Answering this question is not always easy, and often involves a lot of research work. The important thing is to always remember that we’re not always looking for super precise information here. The purpose of understanding the value of each item is to help us make a rational decision.</p>

<p>For example: let’s say a certain item will earn me between $6,000 and $40,000. This range is <strong>very</strong> wide and may seem to have little value, but if I know that the cost of the item should not exceed $3,000, I can already make a decision and don’t need to invest more time refining my research to narrow this range.</p>

<p><img src="../assets/images/posts/401d8f64d35c.jpeg" alt="Different types of cost of delay" /></p>

<p>Each item can have a cost of delay in a different format: some tend to grow linearly and others exponentially. There are also those with a fixed date, like compliance with a law with a date to come into effect, and others whose cost doesn’t have such a relevant relationship with delay time. Understanding which types of items you have in your Product Backlog is the first step to rationalizing your prioritization process.</p>

<p>The most common type of item found in a Product Backlog are those whose cost of delay tends to increase over time, whether linearly or exponentially. Imagine a product with the following items in its Product Backlog:</p>

<p><img src="../assets/images/posts/6e5a2b5187d3.jpeg" alt="Table with Product Backlog items and their costs" /></p>

<p>Each item has an estimated cost per week of delay and an estimated development time. If we divide the cost of delay by the duration of each item, we arrive at the famous <strong>CD3: Cost of Delay Divided by Duration</strong>.</p>

<p>But why is this CD3 important? To answer this question, let’s try to prioritize this backlog in three different ways.</p>

<p><strong>Prioritization by size</strong></p>

<p>If we choose to deliver the smaller items first, our delivery curve would look something like this:</p>

<p><img src="../assets/images/posts/270bb0046b54.jpeg" alt="Prioritization by size graph" /></p>

<p>In the first week we would have a cost of delay equivalent to all items summed up (2,000 + 5,000 + 6,000 + 1,500), after all we haven’t delivered anything.</p>

<p>At the end of week 1 we managed to deliver the <strong>Notifications</strong> item (which was prioritized for having the shortest duration) and with that we reduced our total cost of delay by 2,000. And then we repeat this process for the next items in the Product Backlog.</p>

<p>At the end, we have the following scenario:</p>

<ul>
  <li>
    <p>1 week with total cost of delay of 14,500</p>
  </li>
  <li>
    <p>2 weeks with total cost of delay of 12,500</p>
  </li>
  <li>
    <p>3 weeks with total cost of delay of 11,000</p>
  </li>
  <li>
    <p>4 weeks with total cost of delay of 6,000</p>
  </li>
</ul>

<p>In this scenario our total cost of delay was:</p>

<p>(1 x 14,500) + (2 x 12,500) + (3 x 11,000) + (4 x 6,000) = <strong>96,500</strong></p>

<p><strong>Prioritization by value</strong></p>

<p>When we prioritize by value, things change a bit:</p>

<p><img src="../assets/images/posts/98ab79c2b24c.jpeg" alt="Prioritization by value graph" /></p>

<ul>
  <li>
    <p>4 weeks with total cost of delay of 14,500</p>
  </li>
  <li>
    <p>3 weeks with total cost of delay of 8,500</p>
  </li>
  <li>
    <p>1 week with total cost of delay of 3,500</p>
  </li>
  <li>
    <p>2 weeks with total cost of delay of 1,500</p>
  </li>
</ul>

<p>In this scenario we start working with the <strong>APP</strong> item because it has the highest cost of delay per week. At the end we have a total cost of delay of:</p>

<p>(4 x 14,500) + (3 x 8,500) + (1 x 3,500) + (2 x 1,500) = <strong>90,000</strong></p>

<p><strong>Prioritization by CD3</strong></p>

<p>Prioritization by value generated a slightly better result, but we still have room for improvement. See what happens when we prioritize by CD3:</p>

<p><img src="../assets/images/posts/a77c54287629.jpeg" alt="Prioritization by CD3 graph" /></p>

<ul>
  <li>
    <p>1 week with total cost of delay of 14,500</p>
  </li>
  <li>
    <p>3 weeks with total cost of delay of 12,500</p>
  </li>
  <li>
    <p>4 weeks with total cost of delay of 7,500</p>
  </li>
  <li>
    <p>2 weeks with total cost of delay of 1,500</p>
  </li>
</ul>

<p>(1 x 14,500) + (3 x 12,500) + (4 x 7,500) + (2 x 1,500) = <strong>85,000</strong></p>

<p>A good reduction, isn’t it? And a great example of how a person acting as Product Owner can have a very positive impact on product development!</p>

<p><strong>Conclusion</strong></p>

<p>Knowing how to prioritize well is important, and to do so you’ll always need to have a good understanding of the value of each item in your Product Backlog.</p>

<p>Formulas like the CD3 calculation can help a lot once you’ve taken the first step: having this sense of value. But this first step is very dependent on the Product Owner’s proximity to the market and a good understanding of their customers’ problems. And well, there’s no magic formula for that. :)</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Teamwork" />
    
    <category term="Prioritization" />
    
    <summary type="html">Prioritizing is one of the most important and difficult activities in any Product Owner&apos;s life.</summary>
  </entry>
  
  <entry xml:lang="en">
    <title type="html">Autonomy in the Retrospective</title>
    <link href="https://mariomelo.com/en/autonomy-in-the-retrospective" rel="alternate" type="text/html" title="Autonomy in the Retrospective" />
    <published>2022-02-07T12:04:52+00:00</published>
    <updated>2022-02-07T12:04:52+00:00</updated>
    <id>https://mariomelo.com/autonomy-in-the-retrospective</id>
    <content type="html" xml:base="https://mariomelo.com/autonomy-in-the-retrospective">
      <![CDATA[<p>The <strong>Sprint Retrospective</strong> is an event that depends heavily on the participation of team members, and sometimes whoever takes on the <strong>ScrumMaster</strong> role needs to pull a rabbit out of a hat to break the routine and avoid team passivity.</p>

<p>A simple way to do this is to have key criteria so the team can qualitatively evaluate the <strong>Sprint</strong> that has passed. But which key criteria should we use?</p>

<p><strong>Daniel Pink</strong> defines through experiments in his book <strong>Drive</strong> that Autonomy is one of the three pillars that sustain people’s motivation at work. We can leverage this concept to create a more participative retrospective model in 4 steps:</p>

<p><strong>1 — Ask the team to think of key criteria</strong></p>

<p>Set a short time limit and write together with the team which factors influence the quality of the team’s work.</p>

<p>Remember that the participation of the entire Scrum team is fundamental during all stages.</p>

<p><strong>2 — Limit the key criteria</strong></p>

<p>You can use <em><strong>dot voting</strong></em> to limit the key criteria that will be used if necessary. The ideal is to have <strong>between 5 and 10 criteria</strong> at the end of this stage.</p>

<p><img src="../assets/images/posts/e7e56cb3b051.jpeg" alt="Dot voting on post-its" /></p>

<p><strong>Important:</strong> You can choose to merge 2 or more themes if they are very similar, just remember to do this before voting.</p>

<p><strong>3 — Ask each team member to evaluate the last Sprint according to the most voted criteria</strong></p>

<p>Here we don’t need to do a super detailed analysis. We can use 3 satisfaction levels, like a traffic light.</p>

<p><strong>Example</strong>: A person can vote <strong>green</strong> for the <strong>Interruptions</strong> criterion if they believe they were rarely interrupted in the past Sprint.</p>

<p><img src="../assets/images/posts/11e1d3f5f7b4.jpeg" alt="Evaluation in traffic light format" /></p>

<p>Just pay attention to two details: make sure that <strong>no one</strong> on the team has difficulty distinguishing the selected colors and ensure that <strong>all</strong> members have evaluated <strong>all</strong> elected criteria.</p>

<p><strong>4 — Evaluate with the team the evolution across Sprints</strong></p>

<p>One of the main benefits of this technique is being able to debate with the team what has influenced the evaluation of each criterion, and having a small history can help a lot to perceive some trends and possible correlations.</p>

<p><img src="../assets/images/posts/cde391c316cd.jpeg" alt="Graph of criteria evolution across sprints" /></p>

<p>Looking at a joint evaluation of criteria that the team itself established is a great way to break the initial ice of a retrospective.</p>

<p>This can be the initial push the team needs to start proposing actions and experiments with the potential to improve their way of working.</p>
]]>
    </content>
    <author>
      <name>Mario Melo</name>
    </author>
    
    <category term="Teamwork" />
    
    <category term="Facilitation" />
    
    <summary type="html">The Sprint Retrospective is an event that depends heavily on the participation of team members, and sometimes whoever takes on the ScrumMaster role needs to pull a rabbit out of a hat to break the routine and avoid team passivity.</summary>
  </entry>
  
</feed>
