<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Sami Birnbaum</title>
    <atom:link href="http://samibirnbaum.com/feed.xml" rel="self" type="application/rss+xml"/>
    <link>http://samibirnbaum.com/</link>
    <description>Sami Birnbaum&apos;s Portfolio | Projects | Podcasts | Live Streams | Case Studies | Posts | Contact | About</description>
    <pubDate>Sat, 13 Jun 2026 23:46:48 +0000</pubDate>
    
      <item>
        <title>AI-led or Human-led Coding? We have to choose.</title>
        <link>http://samibirnbaum.com/2025/04/24/AI-led-or-Human-led-Coding-We-have-to-choose.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2025/04/24/AI-led-or-Human-led-Coding-We-have-to-choose.html</guid>
        <description>&lt;p&gt;It is time we take a closer look about how we code with AI and the ramifications on our industry.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;i-should-never-have-clicked-the-button&quot;&gt;I should never have clicked the button&lt;/h2&gt;

&lt;p&gt;Something really challenging happened to me at the back end of last week. In retrospect it probably wasn’t surprising, but it was challenging nonetheless.&lt;/p&gt;

&lt;p&gt;I had been working on a feature to add some permissions to a codebase, a relatively trivial feature. It was a codebase that I only started working on a couple of weeks ago so I took the time to understand the problem and get familiar with some of the architecture.&lt;/p&gt;

&lt;p&gt;Within 3 hours I had a PR up and was confident in my changes.&lt;/p&gt;

&lt;p&gt;As I went to close the corresponding GitHub issue I saw a button that I had not seen before on the GitHub UI: “&lt;strong&gt;Code with Copilot Agent Mode&lt;/strong&gt;”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://images.thoughtbot.com/jg4jqxxr3o7ciojzzhcktl8wfix6_10cf08f51904cd9896466b29f7db08d2.jpg&quot; alt=&quot;A picture of a man standing next to a button with a sign saying not to push the button&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I should never have clicked it! I had completed the feature anyway and was only on GitHub to close the issue, but my curiosity got the better of me…&lt;/p&gt;

&lt;p&gt;And so I clicked the button. Little did I know that this would lead to a weekend of ruminations, questions of self-worth and angst.&lt;/p&gt;

&lt;p&gt;Instantly, GitHub opened a new tab in the browser to an online instance of Vistual Studio Code for the given codebase. But it didn’t stop there. The editor then gave birth to a right-sided panel with Github Copilot in &lt;strong&gt;Agent Mode&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I watched aghast as the GitHub issue description was injected into the right-sided panel prompt and the Copilot Agent proceeded to get to work creating files, editing files and running terminal commands to add the same
feature that had taken me hours, in &lt;strong&gt;minutes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Queue existential crisis and a long weekend of ruminating about how life would never be the same.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://images.thoughtbot.com/vklzs9qqao3lonc1bgi5o2j8mtew_images.jpeg&quot; alt=&quot;A picture of a penguin looking thoughtfully into the distance&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I should add one caveat here that technically speaking the Copilot Agent did not complete the task, it did get close but it required me making some changes and prompting it a few times here or there.&lt;/p&gt;

&lt;p&gt;However, I could not shake the question, &lt;strong&gt;should I be using a Coding Agent going forward?&lt;/strong&gt; I know it would take some time getting used to but maybe with enough context and prompt engineering this is the new way to code!&lt;/p&gt;

&lt;p&gt;I ruminated on this for far too long over the weekend, but I decided to collate my thoughts so hopefully it prevents someone else having to ruminate in the future.&lt;/p&gt;

&lt;h2 id=&quot;ai-is-not-going-away&quot;&gt;AI is not going away&lt;/h2&gt;

&lt;p&gt;My initial reaction was to try and negate AI entirely. My mind considered AI to be a threat and so it felt reassuring to try and remove AI entirely from the picture.&lt;/p&gt;

&lt;p&gt;I did this by conjuring up thought processes about AI just being some sort of hype or even better the world simply running out of energy to support AI infrastructure allowing the way we code to return to what it once was.&lt;/p&gt;

&lt;p&gt;Whilst this felt reassuring, the sense of calm was short-lived because this did not seem realistic or likely.&lt;/p&gt;

&lt;p&gt;I therefore had to come terms with AI being a part of how we code. The horse has bolted and cannot be returned to the stable.&lt;/p&gt;

&lt;h2 id=&quot;so-what-are-my-options&quot;&gt;So what are my options?&lt;/h2&gt;

&lt;h3 id=&quot;human-led-coding-with-ai-support&quot;&gt;Human-led coding with AI support&lt;/h3&gt;

&lt;p&gt;This acceptance allowed me to reframe my concerns.&lt;/p&gt;

&lt;p&gt;I probably will be using AI when I code, but perhaps there are different ways or methodologies of coding with AI.&lt;/p&gt;

&lt;p&gt;I thought about how I currently use AI when I code, before I clicked that dreaded Copilot Agent button.&lt;/p&gt;

&lt;p&gt;I tend to take time to understand a problem so I can consider an appropriate solution whilst taking into account the bigger picture and overall code architecture. We can call this the planing phase.&lt;/p&gt;

&lt;p&gt;I then utilise &lt;a href=&quot;https://thoughtbot.com/upcase/testing&quot;&gt;TDD&lt;/a&gt; and &lt;a href=&quot;https://thoughtbot.com/upcase/videos/outside-in-testing&quot;&gt;outside-in testing&lt;/a&gt; to consider the best place to write my first test that will help me drive towards the most efficient solution. We can call this the implementation phase.&lt;/p&gt;

&lt;p&gt;In either of these phases I may reach out to an LLM to ask a question about a concept I do not understand or to help me with some syntax, but it is &lt;strong&gt;I&lt;/strong&gt; who chooses to reach out when &lt;strong&gt;I&lt;/strong&gt; feel the LLM will best benefit me.&lt;/p&gt;

&lt;p&gt;I like to think of this as &lt;strong&gt;Human-led coding with AI support&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://images.thoughtbot.com/nn56evwbz662qydp4v6x3q2vh9yz_ChatGPT%20Image%20Apr%2023%2C%202025%2C%2005_15_11%20PM.png&quot; alt=&quot;A coder controlling a small robot like a puppeteer&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ai-led-coding-with-human-support&quot;&gt;AI-led coding with Human support&lt;/h3&gt;

&lt;p&gt;The other, recently discovered, way of coding with AI using the Copilot Agent looks rather different. It tends to start with an AI prompt and the AI sits in the driving seat going through the planning and implementation phase simultaneously.&lt;/p&gt;

&lt;p&gt;Your role is to check over the AI’s work and make corrections here or there.&lt;/p&gt;

&lt;p&gt;A helpful way to think of this is &lt;strong&gt;AI-led coding with Human support&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://images.thoughtbot.com/j0rbvqgm18frdaho9fjl6ne0hzxs_ima123ge.png&quot; alt=&quot;A robot controlling a coder like a puppeteer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Being able to verbalise and conceptualise these 2 different ways of coding was really helpful. I could now see two approaches to coding with AI.&lt;/p&gt;

&lt;p&gt;Human-led or AI-led.&lt;/p&gt;

&lt;h2 id=&quot;but-which-one-will-you-choose&quot;&gt;But which one will you choose?&lt;/h2&gt;

&lt;p&gt;It is important to acknowledge that both options are valid.&lt;/p&gt;

&lt;p&gt;Both can be used and will be used by different people. They are both options available to software developers, and like any choice about tools and implementations both have their advantages and disadvantages.&lt;/p&gt;

&lt;p&gt;However, on a very practical level, one needs to make a decision about which one to use. This was my next conundrum to grapple with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I be a Human-led or AI-led developer?&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;do-i-have-to-choose&quot;&gt;Do I have to choose?&lt;/h2&gt;

&lt;p&gt;But before I answer that question I think it is worth considering why you need to make a choice. Why do we have to be the ones to make a choice about how we code?! Surely we can just ride the wave and see where things go?!&lt;/p&gt;

&lt;p&gt;The answer to this question hinges on the assumption that AI companies have our best interests in mind.&lt;/p&gt;

&lt;p&gt;They don’t.&lt;/p&gt;

&lt;p&gt;Let me use a social media example for a moment.&lt;/p&gt;

&lt;p&gt;Whilst social media does a lot of good, the companies behind many of these platforms are primarily interested in money and this often correlates with screen time. They are not producing these applications for the betterment of society but rather to increase screen time of their users.&lt;/p&gt;

&lt;p&gt;Social media is neither inherently bad or good. However, the onus is on us as individuals to decide how we incorporate social media into our lives. If you use social media without clear boundaries or choices you will
probably find yourself using it in unhelpful or unhealthy ways.&lt;/p&gt;

&lt;p&gt;The same, I believe, is true for coding with AI.&lt;/p&gt;

&lt;p&gt;AI is encroaching more and more into our craft and the way we work. It will continue to do so, for the same reason social media continues to do so, money. It will not be done with deep thought for the betterment of
software, our craft, or the craftspeople.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://images.thoughtbot.com/zjgi6qk0n8q1i6pvdccd6c5ndvjd_3a676706-30c6-4998-949a-0ca5f6637854_368x317.jpg&quot; alt=&quot;A meme with two men labelled &amp;quot;Big Tech&amp;quot; and &amp;quot;VC&apos;s&amp;quot; shoveling money into a furnace labelled &amp;quot;AI&amp;quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Therefore, making a decision about how to use AI becomes a choice you have to make, boundaries you have to consider, it cannot be something that is left to prolificate unattended.&lt;/p&gt;

&lt;h2 id=&quot;should-i-be-human-led-or-ai-led&quot;&gt;Should I be Human-led or AI-led?&lt;/h2&gt;

&lt;p&gt;It is a difficult question to answer because I can only do so based on the knowledge I have in front of me now in an ever changing landscape. It is also difficult because very often in coding the answer is “it depends”.&lt;/p&gt;

&lt;p&gt;Whilst these are both true I think it is helpful to establish a general rule, notwithstanding the exceptions.&lt;/p&gt;

&lt;p&gt;I believe we can do this by looking at key values within software development.&lt;/p&gt;

&lt;h3 id=&quot;speed-️&quot;&gt;Speed 🏎️&lt;/h3&gt;

&lt;p&gt;I think about what life would look like as an AI-led developer. Immediatley, I think about completing features far quicker, the speed with which code could be written and features could be shipped.&lt;/p&gt;

&lt;p&gt;But I wonder if, in this case, looks can be deceiving.&lt;/p&gt;

&lt;p&gt;Because AI code requires checking, a craftsperson who cares about their work and the impact on the wider codebase as a whole will not be able to avoid having to understand the problem properly and the ramifications of the solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I don’t think you can avoid that “planning phase”. All you can do is delay it until later.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Arguably, it is harder to understand a problem or a solution after it has been written (think code reviews and understanding old code).&lt;/p&gt;

&lt;p&gt;However, AI-led development lends itself to this.&lt;/p&gt;

&lt;p&gt;Human-led development is arguably less cognitively intense as it allows the planning phase to happen sequentially and not retroactively.&lt;/p&gt;

&lt;p&gt;And be careful not to misunderstand me here, Human-led development still involves the use of AI. I am not arguing to down AI tools. However, Human-led development allows you to utilise the speed of AI for smaller tasks along the way which shouldn’t require intense checking.&lt;/p&gt;

&lt;h3 id=&quot;knowledge-&quot;&gt;Knowledge 🧠&lt;/h3&gt;

&lt;p&gt;I don’t have a metric for this but I believe my assumption is reasonable.&lt;/p&gt;

&lt;p&gt;Imagine an AI-led developer who spends most of their time doing code reviews and making tweaks. They are working with a preconceived notion of how to solve a problem and are evaluating that specific problem. They are utilising different parts of their brain in comparison to the Human-led developer.&lt;/p&gt;

&lt;p&gt;The Human-led developer has to start the process with creativity and critical thinking. They may have 5 different options of how to build a feature in front of them. Some of those may involve different technologies and
perhaps architectural changes.&lt;/p&gt;

&lt;p&gt;In order to make an informed decision they will have to have a broad enough knowledge-base to weigh up the best approach.&lt;/p&gt;

&lt;p&gt;This sort of creative and broad thinking, I believe, forces a developer to have a better understanding and deeper knowledge of the whole software ecosystem.&lt;/p&gt;

&lt;p&gt;AI-led development does not lend itself to this as it proposes a solution which will naturally create a bias towards pursuing that solution.&lt;/p&gt;

&lt;p&gt;In smaller features this may not have an impact but overtime I believe there will be a vast knowledge gap between AI-led and Human-led developers that will be fairly self-evident and when it comes to working on bigger, more diverse software projects. You will want that broad-knowledge and versatility which AI-led development does not foster.&lt;/p&gt;

&lt;p&gt;As I said, it is a hard metric to quantify but I think over the next couple of years we will see the impact of this within the software developer community.&lt;/p&gt;

&lt;h3 id=&quot;prompt-quality-️&quot;&gt;Prompt Quality ✍️&lt;/h3&gt;

&lt;p&gt;The knowledge factor also plays a big role in the quality of your AI prompts.&lt;/p&gt;

&lt;p&gt;You may have heard people say that an LLM is only as good as the dataset it was trained on. Whilst this is true, there is another truism that should not be ignored.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The output of an LLM depends on the quality of the prompt.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the following 2 prompts for a performance issue:&lt;/p&gt;

&lt;p&gt;“I have a query that is slow, how can I make it faster?”&lt;/p&gt;

&lt;p&gt;“I have a query that I believe is slow. I am not sure if the slow performance is happening in application memory or at the database level with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SQL&lt;/code&gt; query. Here are the results of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXPLAIN ANALYZE&lt;/code&gt; query I ran. I would like to first be able to benchmark the query at the application and database level so I can determine where the transaction is the most expensive and also so I can measure any improvements. I am also wondering if there are some other options available within Postgres, perhaps creating a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;View&lt;/code&gt;, because the table I am querying has lots of records, what do you think?”&lt;/p&gt;

&lt;p&gt;As you can see, there is a major difference between the 2 prompts. The former is not a bad prompt and will likely yield some results, but the focus is more narrow on the database component.&lt;/p&gt;

&lt;p&gt;However, the latter utilises a broad knowledge base to include the application speed and also opens up the LLM to using a different approach.&lt;/p&gt;

&lt;p&gt;This is another reason why knowledge is important and my theory is that Human-led developers will write better prompts because they have maintained a broader understanding and critical thinking habits.&lt;/p&gt;

&lt;h3 id=&quot;scale-️&quot;&gt;Scale 🏗️&lt;/h3&gt;

&lt;p&gt;But lets say you really love doing code reviews and reading through legacy code and you enjoy the path of least resistance, so you are willing to forgo the knowledge gains.&lt;/p&gt;

&lt;p&gt;I still feel that at some point you will run into limitations with AI-led development.&lt;/p&gt;

&lt;p&gt;Anecdotally, I have played with AI-led development on a personal side project and what I found is that the complexity of the code increased as the codebase got bigger and more features were added.&lt;/p&gt;

&lt;p&gt;As a consequence, the LLM started to provide less accurate results and solutions that did not work. This led to even more complex code and a codebase that was very difficult to work with.&lt;/p&gt;

&lt;p&gt;From my experience, this forces you, at some point, to return to Human-led development.&lt;/p&gt;

&lt;h3 id=&quot;code-quality-&quot;&gt;Code Quality 🧑‍💻&lt;/h3&gt;

&lt;p&gt;I have often considered why this is and I think it comes down to the biggest challenge of writing software.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The biggest challenge is not writing code, it’s writing code that is resilient to change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just ask &lt;a href=&quot;https://sandimetz.com/products&quot;&gt;Sandi Metz&lt;/a&gt; who has written books dedicated to this topic.&lt;/p&gt;

&lt;p&gt;At some point the requirements will change and therefore the code that you (or someone else) has written will be required to change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The biggest cost will be your ability to make that change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you ever heard someone say we need to rewrite this software all over again?!&lt;/p&gt;

&lt;p&gt;The reason rebuilds are required is because the &lt;strong&gt;cost of change outweighs the cost of a rebuild&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means your codebase is so complex and convoluted that it is struggling or unable to adapt to requirement changes.&lt;/p&gt;

&lt;p&gt;This is a bad place to be.&lt;/p&gt;

&lt;p&gt;Kent Beck and Martin Fowler touch on this in their book Planning Extreme Programming (XP Series), where they talk about the different levers you can pull to increase your development speed:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The other lever is internal quality. This reflects the quality of the internals of the system: how well it is designed, how good the internal tests are, and so on. This is a very dangerous lever to play with if you allow internal quality to drop you’ll get a small immediate increase in speed, rapidly followed by a much bigger decrease in speed. As a result you must keep an eagle eye on this lever and make sure it is always up as far as it can go. Nothing kills speed more effectively than poor internal quality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And I believe that AI-led development puts code quality at risk.&lt;/p&gt;

&lt;p&gt;There are three main reasons why I think this is:&lt;/p&gt;

&lt;h4 id=&quot;1-narrow-vision&quot;&gt;1. Narrow vision&lt;/h4&gt;

&lt;p&gt;In my experience LLMs tend to focus on fixing the issue at hand based on the prompt provided. This naturally lends itself to a narrower vision.&lt;/p&gt;

&lt;p&gt;In contrast a human can take into account the bigger picture, the codebase as a whole, wider business requirements as well as intuition about what the future holds.&lt;/p&gt;

&lt;h4 id=&quot;2-refactoring&quot;&gt;2. Refactoring&lt;/h4&gt;

&lt;p&gt;One of the most important things you can do as a developer is refactor as you develop new features. This was captured by Kent Beck when he said:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;First make the change easy, then make the easy change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Humans are good at this, we start to build a new feature and notice a code smell or some code that doesn’t seem to be a part of a given object and would be better placed elsewhere.&lt;/p&gt;

&lt;p&gt;These small incremental refactors are what keeps the whole codebase ticking along and resilient to change. It is the versatile midfielder in the middle of the pitch keeping the rest of the team in good shape so they are ready for the next phase of play.&lt;/p&gt;

&lt;p&gt;In my experience LLMs are not good at spotting these changes and making them unless actively prompted to do so with some good old Human-led development.&lt;/p&gt;

&lt;h4 id=&quot;3-technical-debt&quot;&gt;3. Technical Debt&lt;/h4&gt;

&lt;p&gt;Have you ever thought about what the biggest contributor to technical debt is?&lt;/p&gt;

&lt;p&gt;In my experience it is speed.&lt;/p&gt;

&lt;p&gt;There seems to be a correlation between moving quickly and accruing technical debt.&lt;/p&gt;

&lt;p&gt;Unfortunately, AI-led development lends itself to coding faster but speed is not always the best thing because it comes with consequences and one of those consequences is technical debt.&lt;/p&gt;

&lt;h3 id=&quot;slowly-does-it-&quot;&gt;Slowly does it 🐢&lt;/h3&gt;

&lt;p&gt;There is another more subtle consequence of everything happening very quickly.&lt;/p&gt;

&lt;p&gt;Have you ever noticed what happens when you are working on a feature but not writing code. The pauses in between, perhaps when you run your specs or just stare at the trees in the wind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pauses or moving slowly allow space for thought.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These moments are sometimes the most important as they are the moments when your brain is allowed to wonder and you think about a new edge case that no one else has thought of, or a better architecture that unblocks future development.&lt;/p&gt;

&lt;p&gt;Numerous times whilst working on a feature I find myself creating cards for tangential improvements that have risen to the surface along the way.&lt;/p&gt;

&lt;p&gt;Moving slowly comes with this benefit, time allows the brain to absorb information and for thoughts to rise to the surface.&lt;/p&gt;

&lt;p&gt;Human-led development allows for these moments.&lt;/p&gt;

&lt;h3 id=&quot;enjoyment-&quot;&gt;Enjoyment 😄&lt;/h3&gt;

&lt;p&gt;This sounds obvious. It is important for us to enjoy what we do.&lt;/p&gt;

&lt;p&gt;Perhaps AI-led development is more enjoyable for you but I’ve always enjoyed the craft.&lt;/p&gt;

&lt;p&gt;For me the enjoyment is sometimes less about the destination and more about the journey.&lt;/p&gt;

&lt;p&gt;I like being in the weeds of the code, going deep into a bug and the root cause. I find the process engaging and stimulating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But it goes deeper then just having a good time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Humans need joy to be productive. We think and perform at our best when we are happy. The inverse is true for demotivated people.&lt;/p&gt;

&lt;p&gt;If AI-led development is not enjoyable for you then human nature is to be less creative and struggle to maintain high levels of care and attention because you are not enjoying your modus operandi.&lt;/p&gt;

&lt;p&gt;If AI-led development makes you feel this way then you should feel &lt;strong&gt;empowered to choose&lt;/strong&gt; Human-led development for its enjoyment and the way that contributes to yours and your teams productivity as a whole.&lt;/p&gt;

&lt;h2 id=&quot;so-whats-it-gonna-be&quot;&gt;So what’s it gonna be?&lt;/h2&gt;

&lt;p&gt;As I said before both AI-led and Human-led development are valid options and there are tradeoffs between the two.&lt;/p&gt;

&lt;p&gt;But I believe that we have to choose.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://images.thoughtbot.com/kczoqhucz2i44u42804gil18hg1i_ChatGPT%20Image%20Apr%2024%2C%202025%2C%2002_45_43%20PM.png&quot; alt=&quot;A coder thinking about whether to be an AI-led developer or Human-led developer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At this stage in history we don’t have quantitative metrics that tell us which way to choose, I believe it will take a few years for those to arrive. However, we can use our experience.&lt;/p&gt;

&lt;p&gt;We have to carve out a way that works for us, and in order to do this we must create boundaries and make a choice about how we want to incorporate AI into our lives and into our industry, because the AI companies will pursue their own agendas which may be different to ours.&lt;/p&gt;

&lt;p&gt;We care about what it takes to build great software of the highest quality which can stand the test of time.&lt;/p&gt;

&lt;p&gt;I take pride in Human-led development.&lt;/p&gt;
</description>
        <pubDate>Thu, 24 Apr 2025 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Stubbles - Stubbing and Doubles innit. 🧔</title>
        <link>http://samibirnbaum.com/2023/03/02/stubbles.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2023/03/02/stubbles.html</guid>
        <description>&lt;p&gt;Confession: I’ve always struggled to understand the difference between stubbing and doubles…&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;As you start to get more familiar with automated testing, at some point you will likely hear other developers say things like:&lt;/p&gt;

&lt;p&gt;“You know you can just stub that method, right?!”&lt;/p&gt;

&lt;p&gt;“This is a great candidate for a double!”&lt;/p&gt;

&lt;p&gt;And at the beginning these things can be confusing to understand. 😕&lt;/p&gt;

&lt;p&gt;So let’s start by defining each term, followed by their practical use, in specific relation to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rspec&lt;/code&gt; within a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rails&lt;/code&gt; project.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;definitions-&quot;&gt;Definitions 📖&lt;/h3&gt;

&lt;p&gt;One of the tricky things I have seen when these concepts are defined is that they are often defined within the context of testing.&lt;/p&gt;

&lt;p&gt;For me, that just adds a layer of complexity.&lt;/p&gt;

&lt;p&gt;It is true that these concepts are often used within the context of testing, but they don’t have to be.&lt;/p&gt;

&lt;p&gt;So let’s take a stab &lt;em&gt;or should I say stub&lt;/em&gt; 😆 at defining them without talking about tests.&lt;/p&gt;

&lt;h5 id=&quot;stubbing-&quot;&gt;Stubbing 🔪&lt;/h5&gt;

&lt;p&gt;Stubbing is just a term for defining a method on an object.&lt;/p&gt;

&lt;p&gt;However, it indicates the short-term nature of that method.&lt;/p&gt;

&lt;p&gt;If you stub a method on an object, your intention is that it exists for a short period of time and most likey returns a simple hard-coded value.&lt;/p&gt;

&lt;p&gt;You may use a stub to define a method that does not exist yet on an object or to override an existing method to get it to return a value you desire.&lt;/p&gt;

&lt;h5 id=&quot;doubles-&quot;&gt;Doubles 🎲&lt;/h5&gt;

&lt;p&gt;A double, is simply an object that is a double of another object.&lt;/p&gt;

&lt;p&gt;You may be thinking, “but why would you do that?!”, but lets put that question to one side for now
just so we can understand the concept in its purest form.&lt;/p&gt;

&lt;p&gt;A double of something is just a copy of that thing.&lt;/p&gt;

&lt;p&gt;If I have one chocolate and I double that chocolate I now have two of the same chocolate.
We can call the first chocolate the original and the second chocolate a double of the original. yum. 🍫&lt;/p&gt;

&lt;p&gt;Great Success!! We made it this far and we haven’t talked about tests!&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;testing-&quot;&gt;Testing 🧪&lt;/h3&gt;

&lt;p&gt;Hopefully now that we understand these concepts independent of testing we can talk a little bit about
how they can be helpful tools to use when testing.&lt;/p&gt;

&lt;h5 id=&quot;stubbing--1&quot;&gt;Stubbing 🔪&lt;/h5&gt;

&lt;p&gt;Sometimes when you are testing a method, the method under test will send a message to another object in order to retrieve some value.&lt;/p&gt;

&lt;p&gt;That sounds confusing but look at this example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EasyMath&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SumFeature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;available?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt; message is being sent to another class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SumFeature&lt;/code&gt; in order to return the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we come to test the behaviour of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt; method, it would be really useful if we could just worry about
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a + b&lt;/code&gt; without having to be concerned with what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt; method does. At the end of the day, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt;
method belongs to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SumFeature&lt;/code&gt; class and has nothing to do with us over here and we can assume it is tested in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SumFeature&lt;/code&gt;
class where it is defined.&lt;/p&gt;

&lt;p&gt;Well thankfully we have a tool in out arsenal called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stubbing&lt;/code&gt; that will allow us to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stub&lt;/code&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt; method so
it always returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;. This is great! We can now focus on testing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a + b&lt;/code&gt; whilst relying on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt; to always
return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ok, but what does this look like in a test?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#sum&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;adds two numbers together and returns the total&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;easy_math&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EasyMath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SumFeature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:available?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;easy_math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;See that line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allow(SumFeature).to receive(:available?).and_return(true)&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt; method has now been stubbed out to always return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No matter how many times you call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SumFeature.available?&lt;/code&gt; in your application code, it will always return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We did a thing! We stubbed a method! And as you can see it had nothing to do with doubles! 💥&lt;/p&gt;

&lt;h5 id=&quot;doubles--1&quot;&gt;Doubles 🎲&lt;/h5&gt;

&lt;p&gt;Ok if you have made it this far, then stay with me as we are nearly there..&lt;/p&gt;

&lt;p&gt;Let’s take the same example we used above with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt; method, but tweak it slightly, to see how we could use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EasyMath&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;likes_math?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once again we are sending a message &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;likes_math?&lt;/code&gt; somewhere else in order to retrieve a value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Similarly we only want to concern ourselves with the behaviour of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a + b&lt;/code&gt; without having to worry about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;likes_math?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Given what we know so far, we might suggest stubbing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;likes_math?&lt;/code&gt; method in the same way we stubbed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allow(user).to receive(:likes_math?).and_return(true)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, whilst a class method like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;available?&lt;/code&gt; can be stubbed without the need for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt;, an instance method does require
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; before it can be stubbed. (There are exceptions to this by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;any_instance_of&lt;/code&gt; but it is &lt;a href=&quot;https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/any-instance&quot;&gt;not recommended&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In other words we first need to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user&lt;/code&gt; object before we can stub the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;likes_math?&lt;/code&gt; method on it, to
always return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for us.&lt;/p&gt;

&lt;p&gt;Now hold on one second!! Why am I talking about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stubbing&lt;/code&gt; alongside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doubles&lt;/code&gt;? Didn’t I kind of say I didn’t want to do that?!&lt;/p&gt;

&lt;p&gt;Ok hear me out on this one…&lt;/p&gt;

&lt;p&gt;Whilst &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stubbing&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doubles&lt;/code&gt; are completely separate concepts, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; is only &lt;strong&gt;meaningful and useful&lt;/strong&gt; once you &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stub&lt;/code&gt; methods on it.&lt;/p&gt;

&lt;p&gt;This is because when you create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; you are creating a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; of that object without any methods on it.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; is just a plain Ruby &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Therefore, in reality, although &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stubbing&lt;/code&gt; is used on its own, when you are using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; you will likely need to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stubbing&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;Ok so lets see how the code would look for testing our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#sum&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;adds two numbers together and returns the total&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;easy_math&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EasyMath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user_double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:likes_math?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;and_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;easy_math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
    &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;See how we first create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; like this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user_double = double&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And on the next line we &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stub&lt;/code&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;likes_math?&lt;/code&gt; method on to our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; like this: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allow(user_double).to receive(:likes_math?).and_return(true)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It might be helpful to think about it this way:&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; is a useful tool to help you to be able to easily &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stub&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;And that’s really all there is to it folks!&lt;/p&gt;

&lt;p&gt;But before I go, let’s wrap up with some helpful tips.&lt;/p&gt;

&lt;h3 id=&quot;take-away-tips-&quot;&gt;Take-Away Tips 🪶&lt;/h3&gt;

&lt;h5 id=&quot;stubbing--2&quot;&gt;Stubbing 🔪&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;Stubbing has nothing to do with doubles.&lt;/li&gt;
  &lt;li&gt;It helps us to force the return value of a method we don’t care about in our test because it is tested elsewhere.&lt;/li&gt;
  &lt;li&gt;A class method can be stubbed without the need for a double.&lt;/li&gt;
  &lt;li&gt;An instance method will need a double (unless you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;any_instance_of&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;doubles--2&quot;&gt;Doubles 🎲&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;Doubles are a useful way to create an object that acts as a double of another object.&lt;/li&gt;
  &lt;li&gt;The most basic way to create a double in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rspec&lt;/code&gt; is to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; method.&lt;/li&gt;
  &lt;li&gt;Another option is to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_double(User)&lt;/code&gt;. This is the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; but will verify that any methods you stub exist on the class you are doubling.&lt;/li&gt;
  &lt;li&gt;If you are using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FactoryBot&lt;/code&gt; you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_stubbed(:user)&lt;/code&gt; which will create an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_double&lt;/code&gt; but with the methods stubbed out as set in the factory. It also has the added advantage of stubbing out associated objects and created timestamps.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h3&gt;🧔&lt;/h3&gt;

</description>
        <pubDate>Thu, 02 Mar 2023 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Tips for joining an existing project 💡</title>
        <link>http://samibirnbaum.com/2022/07/15/joining-tips.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2022/07/15/joining-tips.html</guid>
        <description>&lt;p&gt;I don’t like change!…&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Joining an existing project is daunting at the best of times. 
There are a lot of things to try and wrap your head around and it takes a lot of mental and emotional energy.
Most human beings by nature do not like change (I’m one of them 🙂), it is uncertain and requires expending more effort than staying put does.&lt;/p&gt;

&lt;p&gt;However, change is inevitable and positive. A new project brings new experiences and sometimes a change of scenery can bring some freshness 
to your daily routine.&lt;/p&gt;

&lt;p&gt;So here are some tips that I have picked up along the way to try and help ease the transition onto an existing project.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;lower-your-expectations-and-go-exploring-&quot;&gt;Lower your expectations and go exploring 🔎&lt;/h3&gt;

&lt;p&gt;This might sound counterintuitive but coming into a project at 100mph with expectations to have an immediate impact are probably not realistic 
and will likely lead to you feeling frustrated.&lt;/p&gt;

&lt;p&gt;I understand the desire to do this and it comes from a good place of caring about what you do and wanting to help.&lt;/p&gt;

&lt;p&gt;You may also feel like “I am being paid to be here so I need to be doing things”.&lt;/p&gt;

&lt;p&gt;However, these expectations and pressures are often self-imposed.
Ask yourself, where are these expectations and pressures coming from?&lt;/p&gt;

&lt;p&gt;Often the answer is from your own desire to get things done or have an impact.&lt;/p&gt;

&lt;p&gt;Instead, give yourself a buffer when joining a new project.
You could call it the exploration phase, the discovery phase or the onboarding phase.&lt;/p&gt;

&lt;p&gt;It doesn’t matter what you call it, what matters is that mentally you give yourself time to get up to speed
without pressures or expectations to deliver.&lt;/p&gt;

&lt;p&gt;Depending on the size and complexity of the project this could be weeks or even a couple months or even longer.&lt;/p&gt;

&lt;p&gt;⭐ Pro Tip: communicate this with the rest of the team, let them know you will be in an exploratory phase where you 
get up to speed with all the things there are to learn about the new project.&lt;/p&gt;

&lt;p&gt;Remember everyone who joins the project will have to do this anyway, it just helps to set some healthier expectations for
yourself and the team around you.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;be-sensitive-&quot;&gt;Be sensitive 💙&lt;/h3&gt;

&lt;p&gt;When you join a new project it can be fairly common to immediately see something that the new team has done or are doing that you feel doesn’t seem right
or could benefit from some significant improvement.&lt;/p&gt;

&lt;p&gt;The likelihood is that you are correct. Your observations with a new perspective may have spotted something which the rest of the team have been doing
habitually without thinking about it and you can see a clear and obvious approach to improve this for everyone.&lt;/p&gt;

&lt;p&gt;But before you jump in and start suggesting changes, just take a moment to be sensitive.&lt;/p&gt;

&lt;p&gt;Every project and process has its idiosyncrasies and some have a context
behind them that explains how they ended up this way.&lt;/p&gt;

&lt;p&gt;Moreover, some people may have spent a lot of time honing these processes or code structures, so be sensitive
to the possibility that critiquing &lt;em&gt;something&lt;/em&gt; might also be viewed as critiquing &lt;em&gt;someone&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;⭐ Pro Tip: Consider holding off suggestions until the discovery phase has passed. This
gives you the time to gain some more context on how certain things developed but it also means that when you come to make a suggestion you will be respected 
by the rest of the team for having taken the time to understand things first.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;onboarding-checklist-&quot;&gt;Onboarding Checklist ✅&lt;/h3&gt;

&lt;p&gt;This is it! Your first day on the project and you arrive at the daily sync (on time, because it is your first day).&lt;/p&gt;

&lt;p&gt;There is tendency to feel a bit out
of things when everyone is going through their cards or tasks for the day and everyone seems to have a clear idea of what they are doing.&lt;/p&gt;

&lt;p&gt;You also want to feel part of it and want to have something concrete to say in the sync.&lt;/p&gt;

&lt;p&gt;A quick way to be able to do this is to create a task for onboarding and add an onboarding checklist to it. The team you are joining may already have
an onboarding checklist for onboarding new people anyway, but why not create a card for it and add some of your own things that you like to do for onboarding
as well (dare I say, you may even add some things from this list 😉).&lt;/p&gt;

&lt;p&gt;⭐ Pro Tip: Having an onboarding checklist that is visible will give you something to communicate about in sync but also give good visibility to the rest
of the team about what you are doing.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;business-overview-&quot;&gt;Business Overview 💰&lt;/h3&gt;

&lt;p&gt;Sometimes we forget that behind the codebase there is often a business.&lt;/p&gt;

&lt;p&gt;In fact sometimes the hardest thing about joining a new project is getting up to speed with all the domain
knowledge.&lt;/p&gt;

&lt;p&gt;Consider asking someone from the business side of things (preferably not another developer) if you can schedule a call just to have a chat about how the business works.&lt;/p&gt;

&lt;p&gt;This will not only give you invaluable information about what you are working with but you will also discover what are the best channels for communication to
get hold of stakeholders.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;technical-architecture-overview-&quot;&gt;Technical Architecture Overview 🎛&lt;/h3&gt;

&lt;p&gt;So far we still have not looked at anything technological, but let’s do that, without heading into the codebase just yet.&lt;/p&gt;

&lt;p&gt;Ask one of the developers or someone from the DevOps team (if there is one) for a chat to go through the technical architecture.&lt;/p&gt;

&lt;p&gt;Often you will find that understanding the technical architecture can help to answer a lot of questions that you would encounter in the codebase anyway.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How many databases are there?&lt;/li&gt;
  &lt;li&gt;What type of database are we using?&lt;/li&gt;
  &lt;li&gt;How many front-end clients interact with our server?&lt;/li&gt;
  &lt;li&gt;Is this a monolith or micro-services?&lt;/li&gt;
  &lt;li&gt;Is there an API?&lt;/li&gt;
  &lt;li&gt;Do we integrate with 3rd party API’s?&lt;/li&gt;
  &lt;li&gt;What technologies are we using?&lt;/li&gt;
  &lt;li&gt;How many environments are there besides production?&lt;/li&gt;
  &lt;li&gt;Which branch deploys to which environment?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will be surprised how many things you will discover about a project by gaining an understanding of the overall architecture and at some point
you will likely run into issues with deployments or certain bugs that require knowledge of this anyway.&lt;/p&gt;

&lt;p&gt;⭐ Pro Tip: Create your own diagram of the architecture. It will come in handy later when you forget things. You could also add it to the documentation to
help future developers onboard.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ui-walkthrough-&quot;&gt;UI Walkthrough 🖥&lt;/h3&gt;

&lt;p&gt;This may seem more obvious, but why not book in a chat with someone from QA or a developer to walk through the UI.&lt;/p&gt;

&lt;p&gt;Often it will be too vast to walkthrough all of it, so I find it helpful to ask to walkthrough the part of the UI that you will likely interact with most 
in your work. Go through some happy paths just to get a brief overview and you will pick the rest up as and when you encounter those areas.&lt;/p&gt;

&lt;p&gt;⭐ Pro Tip: If the project does not have a UI, ask for a walkthrough of the API docs or even better a walkthrough on &lt;a href=&quot;https://www.postman.com/&quot;&gt;Postman&lt;/a&gt; where you can see those API requests in action.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;codebase-walkthrough-&quot;&gt;Codebase Walkthrough 👨‍💻&lt;/h3&gt;

&lt;p&gt;I have actually rarely seen this done, but a senior developer on a project I joined recently did this with me and I found it really helpful.&lt;/p&gt;

&lt;p&gt;The idea is not to go into detail and look at individual lines of code or do any deep dives, you can do that when you get a task in that specific area. The
main purpose is to get a high level overview of where certain parts of the code live. Focus more on folders and files rather than what is in those files.&lt;/p&gt;

&lt;p&gt;It can be as simple as where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets&lt;/code&gt; are stored or where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JS&lt;/code&gt; files are kept. But often it will actually expose certain design patterns that are used in the
codebase and this is a good springboard for asking questions about certain styles within the code.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;pull-down-the-repo-and-get-it-running-locally-&quot;&gt;Pull down the repo and get it running locally 💻&lt;/h3&gt;

&lt;p&gt;Finally!&lt;/p&gt;

&lt;p&gt;Something I never do, but I should, is actually read the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadMe&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;So often I just jump into trying to get the project set up that I overlook something as simple as reading the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadMe&lt;/code&gt;. I then 
ask questions only to be sheepishly redirected back to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadMe&lt;/code&gt;. Hopefully it is up to date and will help you get the project set up locally.&lt;/p&gt;

&lt;p&gt;But if there is something not up to date, make a note of it, even something as simple as typeo, remember that because we will use that to our advantage later.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;generate-an-erd-diagram-&quot;&gt;Generate an ERD diagram 📈&lt;/h3&gt;

&lt;p&gt;If like me, you are a visual learner, I find this to be a neat trick to help you to get up to speed with the database quickly, without having to trawl through the 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;schema&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are different tools out there that can do this for you, but if you are using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rails&lt;/code&gt; there is a &lt;a href=&quot;https://github.com/voormedia/rails-erd&quot;&gt;great gem&lt;/a&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rails-erd&lt;/code&gt; that
will do this for you.&lt;/p&gt;

&lt;p&gt;This can help you to also understand the size of the system you are working with, how many data points there are, and if there is a &lt;a href=&quot;https://wiki.c2.com/?GodTable&quot;&gt;big table&lt;/a&gt; you need to watch out for.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;lets-ship-a-thing-&quot;&gt;Lets ship a thing 🚢&lt;/h3&gt;

&lt;p&gt;Remember that typeo we spoke about earlier, let’s use that to our advantage.&lt;/p&gt;

&lt;p&gt;You might not be ready to commit any working code to the project yet but you might be able to improve some documentation somewhere that lives inside the 
repo after your own onboarding experience.&lt;/p&gt;

&lt;p&gt;Create a card for this change like you would for any coding task. Treat it exactly the same as you would any coding task even if it is only a minor correction.&lt;/p&gt;

&lt;p&gt;You might feel like this is overkill, but this is a really good way to learn the workflow of making a change on a feature branch and deploying that change
through the different environments all the way to production with minimal risk. You will also see how you move the card along on whichever task planner tool
you use.&lt;/p&gt;

&lt;p&gt;You will get to learn and ask questions about the end-to-end process from development all the way to production in a relatively safe environment. This will
lessen the information load when you come to work on your first code-based task and allow you to focus on the code itself without having to also learn the
process at the same time.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ask-for-easy-taskscards-&quot;&gt;Ask for easy tasks/cards 😃&lt;/h3&gt;

&lt;p&gt;Yep that’s right, explicitly ask for easy tasks!&lt;/p&gt;

&lt;p&gt;We already set expectations when we spoke to the client about the discovery phase, so lets use that time to do some discovering.&lt;/p&gt;

&lt;p&gt;The purpose of asking for easy tasks is not to give you an easy time (even though by now you deserve one!). The purpose is also not to be able to ship 
things quickly. Everyone knows you could change the wording of a button quickly.&lt;/p&gt;

&lt;p&gt;The purpose of an easy task is to give you time to look at that area of the
codebase and learn some things about it. Removing complexity from the task itself allows you to focus and work through the complexity of the codebase whilst 
feeling slightly more comfortable about being able to make a rather trivial change.&lt;/p&gt;

&lt;p&gt;You will likely encounter some design patterns and get a feel for some of the 
automated tests that might be used, as well as linting, and hopefully it will be a springboard for pairing with other developers as well.&lt;/p&gt;

&lt;p&gt;⭐ Pro Tip: Ask for 3 or 4 simple tasks that all focus on the same area of the code. Focusing on one area to begin with can help to reduce cognitive overload
and you can dive into other areas of the code at a later stage. Start small and simple.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ask-any-question-&quot;&gt;Ask any question ❓&lt;/h3&gt;

&lt;p&gt;Lastly, ask, ask and ask some more.&lt;/p&gt;

&lt;p&gt;It can feel embarrassing sometimes to feel like you are asking so many questions and even vulnerable to be showing others that you know very little.&lt;/p&gt;

&lt;p&gt;But at some point on this project everyone knew nothing. Everyone asked the most simple questions because no one was born with the divine knowledge of how these things worked or came to be.&lt;/p&gt;

&lt;p&gt;So allow yourself to be human and ask away.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I hope you find some of these tips useful.&lt;/p&gt;

&lt;p&gt;It goes without saying that everyone onboards in different ways and ultimately everyone should onboard
in the way that feels most comfortable and natural to them. 
There is no one size that fits all.&lt;/p&gt;

&lt;p&gt;But maybe you can add one of these tips to your 
onboarding arsenal for the next time you join an existing project.&lt;/p&gt;

&lt;p&gt;Thanks for reading! ✌️&lt;/p&gt;
</description>
        <pubDate>Fri, 15 Jul 2022 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Rebase with fixup 🔧</title>
        <link>http://samibirnbaum.com/2022/06/29/rebase-fixup.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2022/06/29/rebase-fixup.html</guid>
        <description>&lt;p&gt;Say goodbye to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;squash&lt;/code&gt; and &lt;em&gt;Hell Ye!&lt;/em&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup&lt;/code&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Lets imagine you are rebasing a branch called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-new-feature&lt;/code&gt; onto &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;.
In order to do this you are doing an interactive rebase using the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase -i main&lt;/code&gt; whilst you have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-new-feature&lt;/code&gt; branch checked out.&lt;/p&gt;

&lt;p&gt;(If you are using a GUI for git like the OP is using Git Extensions, if they are up to date they should also contain these new options)&lt;/p&gt;

&lt;p&gt;Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase -i main&lt;/code&gt; opens the following in your editor:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;pick 996b0 work &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;progress
pick 59f3a feature finished

&lt;span class=&quot;c&quot;&gt;# Rebase b6914..59f3a onto b6914 (2 commands)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Commands:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# p, pick &amp;lt;commit&amp;gt; = use commit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# e, edit &amp;lt;commit&amp;gt; = use commit, but stop for amending&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# s, squash &amp;lt;commit&amp;gt; = use commit, but meld into previous commit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# f, fixup [-C | -c] &amp;lt;commit&amp;gt; = like &quot;squash&quot; but keep only the previous&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#                    commit&apos;s log message, unless -C is used, in which case&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#                    keep only this commit&apos;s message; -c is same as -C but&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#                    opens the editor&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# x, exec &amp;lt;command&amp;gt; = run command (the rest of the line) using shell&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# b, break = stop here (continue rebase later with &apos;git rebase --continue&apos;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# d, drop &amp;lt;commit&amp;gt; = remove commit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# l, label &amp;lt;label&amp;gt; = label current HEAD with a name&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# t, reset &amp;lt;label&amp;gt; = reset HEAD to a label&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# m, merge [-C &amp;lt;commit&amp;gt; | -c &amp;lt;commit&amp;gt;] &amp;lt;label&amp;gt; [# &amp;lt;oneline&amp;gt;]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# .       create a merge commit using the original merge commit&apos;s&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# .       message (or the oneline, if no original merge commit was&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# .       specified); use -c &amp;lt;commit&amp;gt; to reword the commit message&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-C | -c&lt;/code&gt; flag.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;s, squash &lt;commit&gt; = use commit, but meld into previous commit&lt;/commit&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;f, fixup [-C | -c] &lt;commit&gt; = like &quot;squash&quot; but keep only the previous
                    commit&apos;s log message, unless -C is used, in which case
                    keep only this commit&apos;s message; -c is same as -C but
                    opens the editor 
---&lt;/commit&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking at our 2 commits:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  
pick 996b0 work &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;progress
pick 59f3a feature finished
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s imagine you want to meld them together (something which can be done with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;squash&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup&lt;/code&gt;) but you want to only keep the helpful commit message of the second commit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feature finished&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup&lt;/code&gt; as we have in the past like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  
pick 996b0 work &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;progress
f 59f3a feature finished
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;will not do what we want. It will meld the commits together but it will leave us with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;work in progress&lt;/code&gt; commit message, which is not very helpful.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;We could use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;squash&lt;/code&gt; like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  
pick 996b0 work &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;progress
s 59f3a feature finished
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;this will open a new editor which will allow you comment out the first commit message manually and persist the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feature finished&lt;/code&gt; commit message. This does work but it forces you to have an extra manual step; &lt;em&gt;aint nobody got time for dat&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;This is where the new option we can pass to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup&lt;/code&gt; is super handy.&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  
pick 996b0 work &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;progress
f &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; 59f3a feature finished
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This will meld the commits together but discard the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;work in progress&lt;/code&gt; commit message and only keep the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feature finished&lt;/code&gt; commit message.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;These new options make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup&lt;/code&gt; even more powerful and allows you to rely even less on using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;squash&lt;/code&gt; when you don’t need to.&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Jun 2022 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Ruby Splat Operator 🌟</title>
        <link>http://samibirnbaum.com/2021/12/22/splat-operator.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2021/12/22/splat-operator.html</guid>
        <description>&lt;p&gt;The splat operator is confusing and here is why…&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;It does 2 things that are the exact opposite of each other.&lt;/p&gt;

&lt;p&gt;Let me explain…&lt;/p&gt;

&lt;p&gt;It destructures an array, which looks something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 1&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 2&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;But it can also be used to construct an array:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [123]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you think about this, it is doing two very different things.&lt;/p&gt;

&lt;p&gt;One takes an array and &lt;strong&gt;removes&lt;/strong&gt; the surrounding [].&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[123]&lt;/code&gt; becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;123&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The other takes a value and &lt;strong&gt;adds&lt;/strong&gt; the surrounding [].&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*123&lt;/code&gt; becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[123]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only question we need to answer then is when does it destruct and when does it construct? 🤔&lt;/p&gt;

&lt;p&gt;If you use it when &lt;strong&gt;defining a method&lt;/strong&gt; it will take any argument you give it and &lt;strong&gt;construct&lt;/strong&gt; it into an array.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_a_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;do_a_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 3&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Array&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you use it when &lt;strong&gt;passing arguments as an array to a method&lt;/strong&gt; it will &lt;strong&gt;deconstruct&lt;/strong&gt; the array into arguments.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_a_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;do_a_thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Integer&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Hopefully now we can understand code that looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thing&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;perform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# this splat operator will construct any arguments into an array&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# this splat operator will deconstruct that array into arguments &lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;perform&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@x&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;perform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# =&amp;gt; 1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;As an aside, the reason for the above class method of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perform&lt;/code&gt;, is so you can easily call
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Thing.perform()&lt;/code&gt;, without having to first instantiate the object.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*args&lt;/code&gt; means that if our expected parameters in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initialize&lt;/code&gt; method were to change
we would never have to change them in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perform&lt;/code&gt; class method.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Credit to &lt;a href=&quot;https://www.honeybadger.io/blog/ruby-splat-array-manipulation-destructuring/&quot;&gt;this article&lt;/a&gt; which helped to shape my understanding.&lt;/p&gt;
</description>
        <pubDate>Wed, 22 Dec 2021 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Dependeny Injection 💉 ⚽</title>
        <link>http://samibirnbaum.com/2021/12/17/dependency_injection.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2021/12/17/dependency_injection.html</guid>
        <description>&lt;p&gt;Fact: Objects will very often depend on other objects.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Dependency is not something we can avoid.&lt;/p&gt;

&lt;p&gt;However, we can try to make that dependency as loose as possible utilising a pattern called Dependency Injection.&lt;/p&gt;

&lt;p&gt;Lets have a look at an example which does not use dependency injection first.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TottenhamHostspurFootballClub&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;play_a_match&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;striker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HarryKane&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;striker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HarryKane&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;score&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Looking at the code above we can see that in order for TottenhamHostpur(Spurs) to play a match they &lt;strong&gt;need&lt;/strong&gt; Harry Kane.
This is a really restrictive tightly coupled dependency.
This means that without a striker called Harry Kane, Spurs would not be able to play a match.&lt;/p&gt;

&lt;p&gt;Imagine Harry Kane was injured, or worse, sold to a bigger club with more potential for trophies 😢.&lt;/p&gt;

&lt;p&gt;When Spurs would try to play a match they would not be able to do so.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;  &lt;span class=&quot;no&quot;&gt;TottenhamHotspurFootballClub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;play_a_match&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# HarryKaneGoneError&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TottenhamHotspurFootballClub&lt;/code&gt; class is pretty inflexible and relies heavily on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HarryKane&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So how could Dependency Injection allow Spurs to survive and keep playing even if Harry Kane was unavailable.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TottenhamHostspurFootballClub&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;striker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@striker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;striker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HarryKane&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;play_a_match&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;striker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@striker&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;striker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HarryKane&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;score&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ok so now things look a little more flexible.&lt;/p&gt;

&lt;p&gt;Of course Spurs are still dependent on a striker, we can’t avoid that.&lt;/p&gt;

&lt;p&gt;But they are no longer tightly coupled to Harry Kane as being the only striker.&lt;/p&gt;

&lt;p&gt;So we could do something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;  &lt;span class=&quot;n&quot;&gt;spurs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TottenhamHotspurFootballClub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LucasMoura&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;spurs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;play_a_match&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;One of the key things here is that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TottenhamHotspurFootballClub&lt;/code&gt; class doesn’t really need to care much about who or what the striker is, it can get on
with doing its own thing, only being concerned that it has received a striker.&lt;/p&gt;

&lt;p&gt;Bonus: This would also help us test the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TottenhamHotspurFootballClub&lt;/code&gt; class in isolation 👊.&lt;/p&gt;

</description>
        <pubDate>Fri, 17 Dec 2021 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>When Memoization met DRY 💕</title>
        <link>http://samibirnbaum.com/2021/12/15/memoization.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2021/12/15/memoization.html</guid>
        <description>&lt;p&gt;Let’s go on a journey into the world of memoization through the medium of &lt;del&gt;dance&lt;/del&gt; Rails…&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Once upon a time there was a controller with 3 typical methods:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserController&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clan_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# a user belongs to a clan and a clan has many users&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;locals: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;users: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;clan: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clan_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;locals: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;clan: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clan_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;user_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:power&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And all was well and good until ‘DRY’ came along and said “No, not by the hairs on my chinny chin chin…”&lt;/p&gt;

&lt;p&gt;In all 3 methods we have the exact same line of code &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clan = Clan.find(params[:clan_id])&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Fear not, we can clean this up by using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before_action&lt;/code&gt; to do the exact same thing:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserController&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before_action&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:set_clan&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;users&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;locals: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;users: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;clan: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;locals: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;clan: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;user_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:power&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;set_clan&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clan_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;“DRY” was happy with this and managed to calm down, until “Memoization” came along and said what if I can get rid of your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before_action&lt;/code&gt; altogether 🤯&lt;/p&gt;

&lt;p&gt;Check this out =&amp;gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserController&lt;/span&gt;  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;users&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;locals: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;users: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;clan: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;locals: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;user: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;clan: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:new&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;user_params&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:power&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;clan&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clan_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Notice what we did?&lt;/p&gt;

&lt;p&gt;We removed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before_action&lt;/code&gt; and changed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_clan&lt;/code&gt; method to be called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clan&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means that anytime the code calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clan&lt;/code&gt; it will not be calling a variable but rather the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clan&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;But hold on a second, I spot a performance issue….&lt;/p&gt;

&lt;p&gt;Take a look at the index method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;users&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;locals: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;users: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;clan: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clan&lt;/code&gt; 2 times which means we will be hitting our database twice in order to retrieve the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Clan&lt;/code&gt; record from the database.&lt;/p&gt;

&lt;p&gt;Enter “Memoization”…&lt;/p&gt;

&lt;p&gt;This’ll fix it 🪛&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;clan&lt;/span&gt;
   &lt;span class=&quot;vi&quot;&gt;@clan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clan_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Great! But this is not easy to read, so what is this wizadry? 🧙‍♂️&lt;/p&gt;

&lt;p&gt;Lets write the same method without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||=&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt; 
 &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;clan&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;present?&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@clan&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@clan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Clan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:clan_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@clan&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now this is more readable.&lt;/p&gt;

&lt;p&gt;Essentially when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clan&lt;/code&gt; method gets called for the first time here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users = clan.users&lt;/code&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@clan&lt;/code&gt; varaible will be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means it will move to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt; block and assign the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@clan&lt;/code&gt; instance variable to the database record.&lt;/p&gt;

&lt;p&gt;When it gets called a second time at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;render locals: {users: users, clan: clan}&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@clan&lt;/code&gt; will be present so it will just return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@clan&lt;/code&gt; and not hit the database again.&lt;/p&gt;

&lt;p&gt;Not only is this DRY, but it also means we don’t have to use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before_action&lt;/code&gt; and we learnt a cool way to utilise Memoization.&lt;/p&gt;

&lt;p&gt;And they all lived happily ever after. The End. 👊&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Co-authored with &lt;a href=&quot;https://dcyoung.dev/&quot;&gt;David Young&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Dec 2021 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Rails &quot;Joins Tables&quot; are alphabetical</title>
        <link>http://samibirnbaum.com/2021/12/02/alphabetical-joins-table.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2021/12/02/alphabetical-joins-table.html</guid>
        <description>&lt;p&gt;Imagine we have 2 models&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Area&lt;/li&gt;
  &lt;li&gt;Lane&lt;/li&gt;
&lt;/ul&gt;

&lt;!--more--&gt;

&lt;p&gt;and you want to create a standard Joins Table with just an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;area_id&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lane_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you create the table via a migration Rails will automatically create the joins table with the folloing naming convention &lt;strong&gt;in alphabetical order&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;areas_lanes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you then decided to change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Area&lt;/code&gt; table to be called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Screen&lt;/code&gt;, one of the things you will likely do is write a migration to change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;areas_lanes&lt;/code&gt; table to be called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screens_lanes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You may think Rails will therefore look for a joins table called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screens_lanes&lt;/code&gt; after all we have simply switched the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Area&lt;/code&gt; table for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Screen&lt;/code&gt; one.&lt;/p&gt;

&lt;p&gt;Unfortunately not, Rails will look for a table called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lanes_screens&lt;/code&gt; becuase it will keep to its &lt;strong&gt;alphabetical order naming convention&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So you will need something like this:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;has_and_belongs_to_many :screens, join_table: &quot;screens_lanes&quot;&lt;/code&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 02 Dec 2021 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Rails! API!! Devise!!! JWT&apos;s!!!!</title>
        <link>http://samibirnbaum.com/2018/05/30/rails-api-with-devise-and-jwt.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2018/05/30/rails-api-with-devise-and-jwt.html</guid>
        <description>&lt;p&gt;&lt;strong&gt;I had dreamed this day would finally come…&lt;/strong&gt; Ok that’s a bit melodramatic, but to say I hadn’t lay awake thinking about this concept would be wholly untrue…&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;My journey into web-development started with all the good stuff on the frontend, as it does for most people. I even went the whole hog and threw in a framework (AngularJS) just for good measure. But now I was in Star Wars territory, this was the life of a server-side developer, time to separate the men from the boys (at least in my child-like mind).&lt;/p&gt;

&lt;p&gt;Welcome Ruby on Rails. This was great, I could build a whole application back-to-front using this single framework Ruby on Rails. But hold on one second… If I could build everything with Rails, then what was the point of all the really cool frontend frameworks that everyone was raving about (currently React).&lt;/p&gt;

&lt;p&gt;Well unfortunately it turns out that if you wanted to build an application using Ruby on Rails, you would miss out on all the cool functionality of the frontend frameworks like single page applications and 2-way data binding.&lt;/p&gt;

&lt;p&gt;This left me in quite a predicament. I could have a really bespoke backend with Ruby on Rails but sub-standard frontend views. Or I could have a really bespoke frontend with Angular but a sub-standard database-as-a-service backend.&lt;/p&gt;

&lt;p&gt;Well I wanted both (I screamed, lying down kicking my legs against the floor).&lt;/p&gt;

&lt;p&gt;I wanted to have my cake &lt;em&gt;and&lt;/em&gt; eat it!&lt;/p&gt;

&lt;p&gt;Why couldn’t I have a bespoke backend using Rails and a bespoke frontend using whichever framework I so desired?&lt;/p&gt;

&lt;p&gt;This pursuit led me to the crazy world of &lt;strong&gt;Rails! API!! Devise!!! JWT’s!!!!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I would build my backend using Rails new API mode. This would allow my backend to be completely agnostic and interact with whichever frontend I wanted. I needed to set up a good authentication system, especially as I was using an API, but I was able to do this using Devise and JWT’s.&lt;/p&gt;

&lt;p&gt;Once I had the backend working as its own unit, as an API, I would be free to connect to that backend using HTTP requests from whichever frontend I desired, Angular, React, or even Android and IOS Applications.&lt;/p&gt;

&lt;p&gt;Admittedly, this would be far more work but think of the benefits in the long-run. I would have one backend for all different forms of my application. I could have a native mobile application and a website all running off one single backend. Moreover, as the pace of change on the frontend gets ever more Usain-Bolt-like I would be able to adapt my frontend to the latest designs without being concerning about the star wars server side stuff.&lt;/p&gt;

&lt;p&gt;Time to sit back, have my cake &lt;strong&gt;and&lt;/strong&gt; eat it!&lt;/p&gt;

&lt;p&gt;In my personal opinion, this division of labour between the backend and the frontend is how applications (especially sizeable ones) should be built. But hey! What do I know?! I’m just a developer with a child-like mind.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://samibirnbaum.com/portfolio/memorial-notifier-api.html&quot; target=&quot;_blank&quot;&gt;A project I built using this methodology&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Wed, 30 May 2018 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>How I Ended Up Here.</title>
        <link>http://samibirnbaum.com/2017/09/25/how-i-ended-up-here.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2017/09/25/how-i-ended-up-here.html</guid>
        <description>&lt;p&gt;&lt;strong&gt;How do any of us end up anywhere?&lt;/strong&gt;       Well.. we dip our little toe in the water, and then we wait.. we wait for that freezing cold sensation which we expect to rush through our system and when it doesn’t come we breathe a deep sigh of relief and sink into that nice warm bath.
&lt;!--more--&gt;
And since dipping my toe into the ocean that be called ‘programming’ I am yet to retract from the ice cold water (mind you though, it can get pretty cold at times).&lt;/p&gt;

&lt;p&gt;The straight and narrow path:&lt;br /&gt;
I went to school like most people (in London where i was born and raised) and following school I undertook my undergraduate degree BSc from &lt;a href=&quot;../../../img/posts/lse-certificate.png&quot; target=&quot;_blank&quot;&gt;The London School of Economics&lt;/a&gt;, one of the top universities in the country. However, although providing me with riguoruos academic analysis of the social political landscape and criminological theses. I didn’t leave LSE with a defined skill, more an amulgamation of academic disciplines (not to say that this hasn’t been handy).&lt;/p&gt;

&lt;p&gt;The &lt;del&gt;interesting&lt;/del&gt; different path:&lt;br id=&quot;ancient&quot; /&gt;
Following university, I became rather interested in languages. No, not the computer sort. But.. the ancient sort. I spent time on a course learning the skills to translate Biblical Hebrew and, wait for it.. Aramaic. This study of ancient texts, propelled me into a world of new languages, and Talmudic study, requiring thorough rigurous analysis, organisation, sturcture and clarity. I loved it and I now teach a course in Biblical Hebrew and still continue to pursuit this source of study in my spare time.&lt;/p&gt;

&lt;p&gt;From this stand-point the progression into programming was almost logical (more of a dipping toe in the water experience if i’m honest). I can now utiliste these core principles and disciplines of learning ancient languages to learn some of the most modern languages that exist today. And continuously engage in learning, thorough rigurous analysis, organisation, sturcture and clarity.&lt;/p&gt;

&lt;p&gt;And here I am.&lt;/p&gt;

&lt;p&gt;Please feel free to ask any questions, and if i can help with any advice from my own mistakes and successes along the way I would be happy to help!&lt;/p&gt;
</description>
        <pubDate>Mon, 25 Sep 2017 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>What I Find Challenging</title>
        <link>http://samibirnbaum.com/2017/09/24/what-have-i-found-most-challenging.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2017/09/24/what-have-i-found-most-challenging.html</guid>
        <description>&lt;p&gt;&lt;strong&gt;In life we all find different things challenging&lt;/strong&gt;, what may be second nature to one person can be just as easily foreign to another and vice versa. The same rings true in various different industries. Lets examine Dentists. To one dentist performing a &lt;abbr title=&quot;root canal therapy involving complete removal of dental pulp from a tooth&quot;&gt;pulpectomy&lt;/abbr&gt; is (nearly) as simple as a walk in the park, to another dentist its the equivalent of walking up mount vesuvius in flip-flops.&lt;br /&gt; 
&lt;!--more--&gt;
Note: neither Dentist is subordinate to the other, it is just the nature of all of us in all settings to find different aspects more challenging than others.&lt;/p&gt;

&lt;p&gt;So, where am I going with this?.. It is true this would be a good introduction to actually begin to relate a number of things I may find challenging in life as a whole. But lets quickly limit the question to the sphere of programming. Phew!&lt;/p&gt;

&lt;p&gt;What have I, or do I, find most challenging about programming? For me personally it’s that first point where you grapple with or are introduced to a brand new concept for the first time. That moment, where you have to come to terms with something completley new and often without a previous frame of reference.&lt;/p&gt;

&lt;p&gt;For example, learning JavaScript as an object orientated programming language for the first time was very challenging. Its a brand new concept and it’s complex at times. Moreover, when you try and find definitions for certain aspects, the definition can often include references to other concepts which hitherto are unknown. Thus, it can feel very overwhelming at first and take time to break down a new concept/language and gain a good understanding in order to venture forward.&lt;/p&gt;

&lt;p&gt;However, the greater the challenge the greater the reward. Although overwhelming at first I actually enjoy taking something new and complex, investigating it, breaking it down, simplifying it and acquiring a good understanding of it.&lt;/p&gt;

&lt;p&gt;Perhaps its reliving the lego building process of yesteryear where you destroy an entire space station to find out whats really happening underneath, get chased by your older brother, and then rebuild it with a far greater understanding and fear of your older brother than you ever had to begin with.&lt;/p&gt;

&lt;p&gt;And with this, is a small insight into what I find most challenging about programming (at least at the moment). It may be worlds apart from what you find challenging or this may resonate with you entirley.&lt;/p&gt;

&lt;p&gt;Always feel free to get in touch, if my own challenges can be of any assistance to you I would be happy to help!&lt;/p&gt;

</description>
        <pubDate>Sun, 24 Sep 2017 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>My Motivation As A Developer</title>
        <link>http://samibirnbaum.com/2017/09/23/my-motivation-as-a-developer.html</link>
        <guid isPermaLink="true">http://samibirnbaum.com/2017/09/23/my-motivation-as-a-developer.html</guid>
        <description>&lt;p&gt;&lt;strong&gt;The title of this post is deceptive&lt;/strong&gt;. Let me explain. There is an underlying assumption in the title that motivation can be isolated and confined to the work place. This may be true in some cases. But you didnt come all this way to read about &lt;em&gt;some cases&lt;/em&gt; you came here (for some unearthly reason) to read about me.
&lt;!--more--&gt;
Call me one-dimensional if you wish, but for me personally it is worth extrapalating this title to incorporate my motivation as a &lt;strong&gt;human-being&lt;/strong&gt;. Ergo, I have always found that the motivations I possess in life as a whole, must also exist and blossom in my place of work.&lt;/p&gt;

&lt;p&gt;In essence therefore, what motivates me as a developer is exactly what motivates me in my day to day existence.&lt;/p&gt;

&lt;p&gt;So that being the case, what simply does it for me (apart from &lt;a href=&quot;https://samibirnbaum.com/2017/09/25/how-i-ended-up-here.html#ancient&quot; target=&quot;_blank&quot;&gt;ancient texts&lt;/a&gt;)?&lt;/p&gt;

&lt;p&gt;Well, for some reason, I really do have a genuine drive to help others, not a programming motivation I here you say. Well yes on the surface you are right. But look deeper and its a multi-dimensional motivation which envokes an honest, genuine desire to help you.&lt;/p&gt;

&lt;p&gt;Overwhelemed by the tech world and enormity of the web, not to mention complex jargon? I genuinely want to try and help you. Need a certain feature or functionality? If I can I really would like to help.&lt;/p&gt;

&lt;p&gt;This motivation really helps me to push through tricky programming challenges because I simply want to help you where I can.&lt;/p&gt;

&lt;p&gt;I want to know about other things that motivate you I hear you cry! Well if you insist.&lt;br /&gt;
I enjoy breaking things down, getting to understand what’s really going on. Simplifying the complex. Creating order. Structure. Clarity.&lt;/p&gt;

&lt;p&gt;Now these motivations may not be your cup of tea by any means, in fact I am completley the type of guy you dont want to play lego with! But these motivations derive from my enjoyment of achieving sense within the seemingly senseless and they have facilitated my motivation in programming and enjoyment of it too.&lt;/p&gt;

&lt;p&gt;Whats that?!! You do want to play lego, sure! Get in touch..&lt;/p&gt;
</description>
        <pubDate>Sat, 23 Sep 2017 00:00:00 +0000</pubDate>
      </item>
    
  </channel>
</rss>
