<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://blog.harrisferguson.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.harrisferguson.dev/" rel="alternate" type="text/html" /><updated>2026-07-27T03:22:48+00:00</updated><id>https://blog.harrisferguson.dev/feed.xml</id><title type="html">duckypotato</title><subtitle></subtitle><entry><title type="html">Why don’t good developers like LLMs?</title><link href="https://blog.harrisferguson.dev/ai/tech/development/software/2026/07/26/ai.html" rel="alternate" type="text/html" title="Why don’t good developers like LLMs?" /><published>2026-07-26T15:00:00+00:00</published><updated>2026-07-26T15:00:00+00:00</updated><id>https://blog.harrisferguson.dev/ai/tech/development/software/2026/07/26/ai</id><content type="html" xml:base="https://blog.harrisferguson.dev/ai/tech/development/software/2026/07/26/ai.html"><![CDATA[<p>Since trying to adopt LLM workflows since around 2023, LLM generated code has generally left me with a
feeling of mild satisfaction at best. Sitting now in 2026, models have improved by leaps and bounds but 
LLM code still leaves me with that feeling. That’s not to say that LLMs haven’t encroached into more and
more of my workflow over time, however the actual code output they generate has not left me more impressed
over time. Some of the developers that I trust the most, those cracked staff devs who seem to know everything inside an out, seem to hold this opinion as well. It’s typically the junior and mid level devs that I’ve noticed lean on LLM tools the most. For a business trying to optimize for labour cost, the “mid” quality of AI code is fine enough, 
however the cult of AI driven agentic workflow development has started to turns it’s nose up when a developer
does something “manually”.</p>

<blockquote>
  <p>“Agents are so good now! I’m sure if you asked <i>model of the week</i> to do that for you it would crush it!”
– <cite>Everyone I talk to AI about</cite></p>
</blockquote>

<p>With how good models are now I have to agree, but it’s beyond a question of fidelity. I would believe that whatever
new ultra coding model given the right context, tools, skill files, hooks, etc would 100% be able to execute on the tasks.
The question for me becomes: if I already know what I want to do, what’s the tradeoff between just doing it and trying
to explain to an agent how to do it?</p>

<h2 id="where-i-use-llms">Where I use LLMs</h2>
<p>LLMs have found their ecological niche in my development environment as an effective “research assistant” that I can delegate factual research tasks to. With some of the available MCP connectors in most agent harnesses, it’s so easy to
ensure that an agent has access to tools it needs to see monitoring data, database DDL, database data, code patterns, and even institutional knowledge. Those natural questions that come up when planning a feature such as “How much extra write traffic to this table will I introduce with this change” or “How many times does this job I’m adding a new query to run in a day” can be delegated to an agent on the spot leaving me to return to whatever train of thought I was already in.</p>

<p>As much as I really want to say that all LLM generated code is garbage slop code not worth any real developers time, that’s not an intellectually honest opinion either. The reality is LLMs and agent harnesses like Claude Code are now write decent code for the most part. Agents can still struggle to write concise code that’s informed by knowledge of a given business task, and the code LLMs generate does tend towards the over-engineered at times, but for most businesses that’s probably a fine tradeoff. Agents are especially effective with changes where the work of discussing what change needs to be made is more work than the change itself: copy changes, repeatable changes to several files, etc. If we are heading towards a world where those sorts of tasks can be executed by an agent being driven by a non developer, and reviewed by
developer teams, that seems overall like a win to me.</p>

<p>The key factor that makes these tasks worth an agent doing for me is they, typically speaking, don’t take context on the codebase and the business away from me as a developer. Adding meta tags to a bunch of buttons, asking claude to rewrite an array map using a functional interface, or reviewing an AI written PR that adds a small conditional fixing some Sentry error that’s been kicking around aren’t going to reduce my ability to understand the system that a codebase is representing and the business need that it’s trying to solve.</p>

<h2 id="where-llms-fall-flat-for-me">Where LLMs fall flat for me</h2>
<p>It’s only a given then that where I don’t like LLM and agent driven work is tasks that do require my own expertise of the codebase, software development practices, or my experience. Claude Code could, with some non zero amount of quality, create for me a large sized epic that adds functionality to the app. It then could, in theory, automatically execute on those pieces of work autonomously and in parallel. I could orchestrate 15 agents all working together, giving each other code reviews, with a designer agent and a supervising agent, to get the work done. I do 100% believe agents could do this and produce a <em>reasonable</em> product. In fact, I’ve contracted my services out on the side and basically done just that, and the product worked well enough to make the client happy.</p>

<p>Where LLMs fall flat for me is not fidelity. The tradeoff between developer context and LLM speedup just isn’t worth it, and that’s being generous and assuming that agentic workflows like what I describe above do actually speed up work (With the data that I have seen I’m not convinced the speed up is real but I would believe it can given the right org).</p>

<h2 id="good-developers-thrive-on-what-llms-take-away">Good developers thrive on what LLMs take away</h2>
<p>The best developers thrive on institutional knowledge. They know their code is legacy the moment it’s shipped to production. They know that the needs of the business are going to change in a few months. They’re ready for half of their project to get de-prioritized for a company wide priority project. They know how much over or under engineering they need to do for a project by reading the context of that project against the business. LLMs are just kind of bad at that stuff. LLMs don’t know that your PM has a tendancy to under-estimate the effort of projects, or that at a company all hands if you read between the lines you know that your team is going to have to do support work for another team for a quarter. Company and office politics, org structure, and the ego of people leading projects are important inputs that can have a real effect on the code you write. And the verbose and winding nature of LLM code doesn’t lend itself well to the fuzzy nature of how work really gets done in an software shop.</p>

<h2 id="claude-code-ers-arent-bad-devs">Claude Code-ers aren’t bad devs</h2>
<p>All that being said, I don’t believe in the type of “developer powerscaling” that tends to happen in conversations like this. The Primeagean Pirate Software Yandere Dev Linus Torvalds Jonathan Blow epic pwn your code sucks cause you write javascript is a toxic part of the wider culture of software that I hope dies and never comes back. This is work for most people at the end of the day, and if the way you choose to get work done (or need to get work done if you work at a company like that) is to spin up 5 claude code agents and prompt…you gotta do what you gotta do. A non zero amount of my token usage at work is simply so that I can say I tried to do something with AI. I will say that I think going forward what’s going to separate mid level from senior developer is a desire to struggle through problems yourself and seek that deeper meaning, even if only to be able to better control agents that go off the rails.</p>]]></content><author><name></name></author><category term="ai" /><category term="tech" /><category term="development" /><category term="software" /><summary type="html"><![CDATA[Since trying to adopt LLM workflows since around 2023, LLM generated code has generally left me with a feeling of mild satisfaction at best. Sitting now in 2026, models have improved by leaps and bounds but LLM code still leaves me with that feeling. That’s not to say that LLMs haven’t encroached into more and more of my workflow over time, however the actual code output they generate has not left me more impressed over time. Some of the developers that I trust the most, those cracked staff devs who seem to know everything inside an out, seem to hold this opinion as well. It’s typically the junior and mid level devs that I’ve noticed lean on LLM tools the most. For a business trying to optimize for labour cost, the “mid” quality of AI code is fine enough, however the cult of AI driven agentic workflow development has started to turns it’s nose up when a developer does something “manually”.]]></summary></entry><entry><title type="html">Where React Doesn’t Scale</title><link href="https://blog.harrisferguson.dev/react/hooks/frontend/architecture/2024/06/17/dont-need-react.html" rel="alternate" type="text/html" title="Where React Doesn’t Scale" /><published>2024-06-17T15:30:00+00:00</published><updated>2024-06-17T15:30:00+00:00</updated><id>https://blog.harrisferguson.dev/react/hooks/frontend/architecture/2024/06/17/dont-need-react</id><content type="html" xml:base="https://blog.harrisferguson.dev/react/hooks/frontend/architecture/2024/06/17/dont-need-react.html"><![CDATA[<p>After around 2 years of professional experience with React, I’ve reached a conclusion that React alone doesn’t scale. Before you come at me with pitchforks, I don’t mean in the technical sense! React comes packaged with some challenges that can be a hinderance to the Front End of medium to large size orgs. This isn’t to say I don’t like react or its ecosystem and that we shouldn’t be using it, but realizing React’s limitations only serves to make us all stronger React developers.</p>

<p>In my first ever web course in university, my TA in the very first lab told us something that is really core to what I mean here:</p>

<p><em>React is not a framework, its a UI library.</em></p>

<p>For a long time I relegated this fact to something I could say at dev trivia games or over lunch with co-workers, but this idea is really deep. React isn’t an opinionated way to build a front end. React isn’t a way to manage how data flows through an application. React isn’t a tool to build entire applications. What React <em>is</em> is a library to manage the lifecycle of UI. All the fancy hooks and contexts are just there to help you manage how your UI changes over time in a (mostly) declarative way.</p>

<p>Since React itself doesn’t have any opinions about what you do outside of how it expects you to manage this visual lifecycle, in larger orgs what tends to happen is that the Front End codebase gets more and more chaotic. I won’t go as far to say it gets messy or unclean, as long as an org has good coding standards the code itself can make sense be quite clean. What I mean is that over time there isn’t a unified way to do the things a large application needs to do, particularly at the boundary between front end and back end. React doesn’t have an opinion about how you fetch data from the backend, so what will happen is some teams fetch their data using custom hooks, and others write large <code class="language-plaintext highlighter-rouge">useEffect</code>s that fetch data, and others leverage tools like Redux to manage their data. When Contexts were introduced teams started to favour that instead of Redux as a way to manage their data, and again React really has no care in the world about how you pass data down to its components.</p>

<p>What’s even stickier is that because React doesn’t care how you do all this, it’s hard to fix. The best you can do is release an org wide guideline on when to reach for what tools, but theres nothing in React itself that can enforce any of these patterns unless you build it yourself (for example using a pattern like Flow, but if you’re doing that you might as well just use Redux). I also have found that despite how powerful frameworks like Next.js are, they still don’t really solve this problem since the front end of a Next app is essentially still just React. Next solves for the problem of how routing and pages should work on your frontend, and it does provide a pretty thin API layer, but it doesn’t give you an opinionated way to organize how data flows through the application.</p>

<p>Strong React developers usually have a great sense of what makes a component “Reactive”, this idea of writing a declarative pure function that perfectly describes how a visual element should look and how it should change over time. That “Reactive” paradigm just doesn’t extend to the larger concerns of a front-end. React gives you nice ways to tell a component to look like its loading something while data isn’t available, through <code class="language-plaintext highlighter-rouge">useEffect</code>s to fetch the data and <code class="language-plaintext highlighter-rouge">&lt;Suspense&gt;</code> to manage what a loading state looks like. That’s its strength and why its so popular. The reality is, you can also use React to manage other parts of your application, and it does that job just fine. Not great, but fine. Custom hooks that call out to databases, backends, and services are a great abstraction for a lot of cases, but its not something react FORCES you do use.</p>

<p>That’s not a problem at all, but knowing that React doesn’t force your hand is key here. Once we are outside of the component, we are just in JavaScript land. Once we acknowledge that landscape, we can survey it with clear eyes and pick a better tool as our needs fit.</p>]]></content><author><name></name></author><category term="React" /><category term="Hooks" /><category term="Frontend" /><category term="Architecture" /><summary type="html"><![CDATA[After around 2 years of professional experience with React, I’ve reached a conclusion that React alone doesn’t scale. Before you come at me with pitchforks, I don’t mean in the technical sense! React comes packaged with some challenges that can be a hinderance to the Front End of medium to large size orgs. This isn’t to say I don’t like react or its ecosystem and that we shouldn’t be using it, but realizing React’s limitations only serves to make us all stronger React developers.]]></summary></entry><entry><title type="html">A loose collection of lessons from an internship</title><link href="https://blog.harrisferguson.dev/work/internship/software/development/tech/2023/08/13/internship-reflection.html" rel="alternate" type="text/html" title="A loose collection of lessons from an internship" /><published>2023-08-13T15:30:00+00:00</published><updated>2023-08-13T15:30:00+00:00</updated><id>https://blog.harrisferguson.dev/work/internship/software/development/tech/2023/08/13/internship-reflection</id><content type="html" xml:base="https://blog.harrisferguson.dev/work/internship/software/development/tech/2023/08/13/internship-reflection.html"><![CDATA[<p>I just finished a 16 month internship placement. My opinions on software in general underwent constant metamorphosis during the past year and a half, but a constant thread running through my experience is a conflict between two personal truths:</p>

<ol>
  <li>I loved what I did on a micro scale</li>
  <li>What I did on a macro scale was often upsetting to me</li>
</ol>

<p>The following lessons, mantras, koans, hot tips, and nuggets of advice are the result of what has been an eternal dialogue with myself. Take these not as hard truths, but as directions or interpretations of an attempt to resolve the dissonance in myself.</p>

<p><em>Note: After writing this I noticed a shocking resemblance to some of the advice in</em> The Pragmatic Programmer <em>so go check that out if you like the vibe here</em></p>

<h3 id="clean-code-is-a-useful-framework">Clean Code is a useful framework</h3>
<p>You should strive to write clean code. The act of coming up with good function, class, and variable names makes you think about your code more and then makes you write better code which makes you think about your code more and your names more and it’s all a lovely run on sentence of a loop that keeps improving and improving itself. Worship at the altar of clean code. Strive for perfection.</p>

<h3 id="clean-code-is-a-crutch">Clean Code is a crutch</h3>
<p>Learn every prayer, every verse, and every single interpretation and sect in the Theology of Clean Code. Once you do, become an godless anarchist. There are no rules or laws. The doctrine of Clean Code is a flawed one, and the only way forward is to form a voluntary association of code. Clean Code is merely a social construct. Clean Code is whatever makes sense for the code you are writing. Throw away the oppressive and frankly outdated word of Uncle Bob and embrace the chaotic and beautiful world of unclean code.</p>

<p>You won’t have time to make it perfect, so make it good enough. It’s always going to be bad, and even if code is self documenting and all that good stuff, code always changes and good function names change. All it takes is one new line of code to completely change the meaning behind a function name. So, learn to live with bad code.</p>

<h3 id="your-employer-hopefully-wants-you-to-learn-and-grow">Your employer (hopefully) wants you to learn and grow</h3>
<p>I’m a bit spoiled in the sense that the first workplace of mine in the industry was a very healthy one. We were encouraged to learn and grow as developers, and there were a plethora of company wide initiatives such as Dev Talks, Hackathons, and Study groups to foster that. However what I did learn from the silver spooned experience is that you should want to work at an organization where this is the case. Working in software is about constantly staying up to date with modern tech, and you should be always learning. There is no perfect piece of software, and the process of making software is one of perpetual skill building. Every project and feature carries some lesson with it, and if your workplace is helping you learn those lessons you should try and stick around.</p>

<h3 id="code-is-expensive">Code is expensive</h3>
<p>Software developers, at least at the time I’m writing this, are paid pretty well. Senior Developers in Canada make significantly more in salary than 99% of the labour force. In terms of just raw time and salary, code is expensive. It takes a team of 5 developers 2 weeks (the average sprint length) to build what product teams would consider a feature, and that’s being <em>very</em> generous in terms of scoping. Larger pieces of functionality can take upwards of 6 months, at which point the organization has probably spent $500,000 on just salary.</p>

<p>There’s also costs to actually letting people use that code. CPU time costs money! We need that CPU time to run tests, run CI/CD, make builds, run a staging server, run a production server, and possibly other environments such as sandboxes. It’s all expensive! This is why real pressures to build products people want to pay for and to build things quickly and descope aggressively always end up arising in these projects.</p>

<h3 id="tech-companies-want-to-make-money-duh">Tech companies want to make money, duh</h3>
<p>What you started working on was probably a cool tool that made peoples lives easier. Something that eased a pain in the real world, and as a software developer you should ideally love the challenge and reward that comes with expressing that real world pain into the logical domain of a programming language. In the software world, you can control the laws of the universe and solve that problem with absolute certainty. Time passes, the product gets sold, and eventually economics plays into how the product and organization operate. Turns out, you need to make money to pay for all that <a href="#code-is-expensive">expensive code</a>. Features get paywalled, pricing schemes are changed and introduces, and at least in my experience it starts to feel like the think that makes the app useful is now gated behind enterprise / mid market size corporate customers, and the average user who found the tool awesome in the first place is left in the dust. This really sucks as the engineer, since I would hope you derive some value from making something people actually like rather than some list of required features to make some important deal work out.</p>

<h3 id="coding-is-fun">Coding is fun</h3>
<p>I really like writing code. I really like trying to figure out how to make something work, from the smaller things like trying to implement a function to larger scale system design. The name of the beast is managing complexity and the only thing you can do to slay it is have an undying craving for simplicity. It doesn’t really matter what you actually work on:</p>
<blockquote>
  <p>If you have the right attitude, interesting problems will find you. <a href="http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s02.html"><em>source</em></a></p>
</blockquote>

<p>Some of my peers will often tell me they wouldn’t work in X field or don’t want to work in Y language. The thing is the core problem in development never changes, it’s always about managing complexity. Every language, environment, tool, and stack is just trying to do that in a different way for a different use case. So, embrace the fun in all problems.</p>

<h3 id="writing-code-for-a-living-makes-it-not-fun">Writing code for a living makes it not fun</h3>

<p>The day to day, or even week to week, of coding is really fun. Technical problems appeal to people who like to find interesting problems, and its a joy to solve them. What puts a dark stain on my heart is when I step back from the work and look at a wider scale of what I’ve worked on and see it amounts to something I don’t like. In my case I spent weeks working on really interesting problems in Typescript/React only to realize what I built was a mechanism by which we can make the app frustrating to use for our “small fish” customers. I want to be clear here, I worked on a team that specifically dealt with Billing and Growth, so my perspective is very skewed. By all customer accounts our product was still great, but still! I don’t enjoy writing paywalls just as much as I don’t enjoy writing data tracking software or software that generates ad content. The comparison has been beaten beyond death but working as a developer can feel like living in a Quarter over Quarter loop of Frankenstein.</p>

<h3 id="you-know-something-that-other-people-dont">You know something that other people don’t</h3>

<p>Your job as a developer is to communicate the technical perspective of any problem. You know something others don’t, and its your job to explain that to them. This is really hard, and a lot of people stop at the first step. The first step is really easy. Most people know something that other people don’t. Get to the second step and get good at explaining it to others! The people around you will have varying levels of ability to understand technical content, and it takes a lot of work to cater your explications to that understanding. But if you can’t make everyone involved with a project understand the technical stuff, even at a high level, you aren’t doing your job.</p>

<h3 id="be-resourceful">Be Resourceful</h3>

<p>Learn how your environment works. Learn keyboard shortcuts. Learn how to use your computer effectively. Learn how to edit text effectively and quickly. Learn tools to ease your work. If you have a frustration, find or make a tool that solves your pain point. If you don’t have time to make a tool, complain to your co workers about it, someone else might have the time (or you might be lucky enough to have a Developer Experience team who’s job it is to fix your problems).</p>

<p>Learn how to find documentation. Learn to read documentation. Learn to write good documentation. Find help at the right times. If you come to someone else with a problem, at least try to have solved it yourself first. Someone else probably had your problem, go find the solution out there.</p>

<p>Don’t spend more than around an hour stuck on a problem. Don’t spend any less than around an hour stuck on something. Allow yourself to be frustrated with problems, them let them sit and come back to them. Don’t try to fix that one last thing at 4:45, chances are you will fix it in 5 minutes the next morning.</p>]]></content><author><name></name></author><category term="work" /><category term="internship" /><category term="software" /><category term="development" /><category term="tech" /><summary type="html"><![CDATA[I just finished a 16 month internship placement. My opinions on software in general underwent constant metamorphosis during the past year and a half, but a constant thread running through my experience is a conflict between two personal truths:]]></summary></entry><entry><title type="html">The end of my challenge</title><link href="https://blog.harrisferguson.dev/aug-19/data-serialization" rel="alternate" type="text/html" title="The end of my challenge" /><published>2022-08-19T15:00:00+00:00</published><updated>2022-08-19T15:00:00+00:00</updated><id>https://blog.harrisferguson.dev/aug-19/the-challenge</id><content type="html" xml:base="https://blog.harrisferguson.dev/aug-19/data-serialization"><![CDATA[<p>The previous 4 blog posts were part of a challenge I set for myself: Write one blog post a day for an entire work week. In coinciding with some things I’m participating in professionally, I wanted to practice writing on technical topics aimed at a reader
a baseline knowledge who may not have dived into the details of specific topics yet. Put another way, I wanted to write the posts I wish I had found when I was learning about these 
topics myself.</p>

<p>One of the more challenging parts of actually working as a developer is the need to
understand the technologies you are using and creating on a very deep level in order to be 
able to developer new software, answer questions and communicate capabilities to other people. Instead of writing the minimal level of software needed to get a rubric mark for 
a piece of logic or code, thousands of real people are engaging with your application and
it needs to be robust, extendable, and cleanly written enough that you can effectively maintain it. I like the way that Steve McConnell puts it in <em>Code Complete</em>:</p>

<blockquote>
  <p>Software’s Primary Technical Imperative is managing complexity.</p>
</blockquote>

<p>Software is so complex that no one person can even really understand it. The only way we can
even begin to get a foothold is to divide that complexity into simple and understandable parts, and organize those simple parts into a system.</p>

<p>A great source of examples for how this is even accomplished is found by actually diving in to
the weeds of how a particular problem works. Some problems are so difficult that nobody has 
really solved it, and looking at the various approaches can tell you the different ways 
people have attempted to solve those problems. I wanted to learn some of these general techniques by looking into the functions, classes, libraries, and technologies I use everyday and take for granted. I’ve found that by asking questions like “How does <code class="language-plaintext highlighter-rouge">useState</code> work and what problem was it created to solve” I can get a foothold into how I’m even supposed to something in the first place.</p>

<p>The process of looking deeper can also lead to connections with new techniques or technologies in of itself. I barely remembered binary arithmetic from my 2nd year Computer 
Science courses, but I had a reason to learn about it when writing my <a href="/aug-18/data-serialization">post</a> on data serialization. Diving into when something is useful by seeing it actually used is so much more motivational for learning.</p>

<p>Going forward I think I’ll do something closer to a post a week. I may do a challenge like this in the future if I find I’m slacking or have a bunch of topics I wanna write about. I wanna do longer style posts I construct over a few days so I can go into more detail about some of the thing I look into. I found myself writing long paragraphs only to delete them because I felt it was a rabbit hole that didn’t need to be gone down 
to get a point across. Hopefully you found those posts informative!</p>]]></content><author><name></name></author><category term="Misc" /><category term="Meta" /><summary type="html"><![CDATA[The previous 4 blog posts were part of a challenge I set for myself: Write one blog post a day for an entire work week. In coinciding with some things I’m participating in professionally, I wanted to practice writing on technical topics aimed at a reader a baseline knowledge who may not have dived into the details of specific topics yet. Put another way, I wanted to write the posts I wish I had found when I was learning about these topics myself.]]></summary></entry><entry><title type="html">How many bytes can you fit an object into?</title><link href="https://blog.harrisferguson.dev/aug-18/data-serialization" rel="alternate" type="text/html" title="How many bytes can you fit an object into?" /><published>2022-08-18T15:00:00+00:00</published><updated>2022-08-18T15:00:00+00:00</updated><id>https://blog.harrisferguson.dev/aug-18/data-message</id><content type="html" xml:base="https://blog.harrisferguson.dev/aug-18/data-serialization"><![CDATA[<p>A running program handles data by keeping it in memory. Some languages may abstract this away from you, but at some point down the stack your program is
manipulating data stored in locations in memory. Sometimes, you might want to send this data to another function so it can perform some operation on it. Functions do this by taking the data <a href="https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference">by reference</a>. That is, they accept as an argument a memory location, and make its operations by <em>referencing</em> that memory location.</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span> 
    <span class="kt">int</span> <span class="n">y</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">movePoint</span><span class="p">(</span><span class="n">Point</span><span class="o">*</span> <span class="n">point</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// operates on a specific point by going to its location in memory</span>
    <span class="n">point</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">+=</span> <span class="n">x</span><span class="p">;</span>
    <span class="n">point</span><span class="o">-&gt;</span><span class="n">y</span> <span class="o">+=</span> <span class="n">y</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>However, program memory is specific to the machine (and process!) the program is running on. Suppose that <code class="language-plaintext highlighter-rouge">movePoint()</code> was actually a function running on a different 
machine that we could call. I could pass in a memory location to a <code class="language-plaintext highlighter-rouge">Point</code> at some location like <code class="language-plaintext highlighter-rouge">0x1FFFFF21</code>, but on that other machine where <code class="language-plaintext highlighter-rouge">movePoint()</code> 
lives <code class="language-plaintext highlighter-rouge">0x1FFFFF21</code> could be the location of some completely different data. So, how can I represent the data running in memory on my computer so that other
machines (maybe over the network) could understand it?</p>

<p>As a sidenote, we might still run into this problem with only one machine. If I were to write the memory location <code class="language-plaintext highlighter-rouge">0x1FFFFF21</code> to a file, and have my <code class="language-plaintext highlighter-rouge">movePoint()</code> function read from that file to get that memory location, that memory location might not make sense by the time <code class="language-plaintext highlighter-rouge">movePoint()</code> gets to it. This is especially the case if <code class="language-plaintext highlighter-rouge">movePoint()</code> is invoked by a different process than the one that wrote the memory location to disc. Memory is really only relevant to the exact same process you are running in, and persisting a memory location probably isn’t a good strategy.</p>

<h1 id="serialization">Serialization</h1>

<p>One thing we could do is take our data, like our <code class="language-plaintext highlighter-rouge">Point</code> struct, and write out its data in a binary format. We could pass <code class="language-plaintext highlighter-rouge">movePoint()</code> a long sequence of bits 
and as long as <code class="language-plaintext highlighter-rouge">movePoint()</code> knows how to decode that data it could do calculations with it.</p>

<p>We could accomlish this with JSON. We take our data, and represent it using <strong>J</strong>ava<strong>S</strong>cript(‘s) <strong>O</strong>bject <strong>N</strong>otation, then just encode that representation
as a bunch of bytes. For example, a <code class="language-plaintext highlighter-rouge">Point</code> object could look like:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
    </span><span class="nl">"x"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> 
    </span><span class="nl">"y"</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p>For the sake of demonstration, lets use a more complicated example. We could take a PHP class:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="kd">class</span> <span class="nc">User</span> <span class="p">{</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="nv">$name</span><span class="p">;</span> 
    <span class="k">public</span> <span class="kt">int</span> <span class="nv">$totalVictoryRoyales</span><span class="p">;</span> 
    <span class="k">public</span> <span class="kt">array</span> <span class="nv">$nicknames</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>and encode it in JSON as:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Harris"</span><span class="p">,</span><span class="w"> 
    </span><span class="nl">"totalVictoryRoyales"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">  
    </span><span class="nl">"nicknames"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"duckypotato"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ducky"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p>Now that I have some JSON text that represents my data, however in text form we still need to turn it into binary so that languages other than Javascript 
can make heads or tails of it. We could just encode each of those ASCII bytes and send a big long message, but we can do slightly better. One algorithm that takes some JSON and gives us a binary encoding is <a href="https://msgpack.org/index.html"><code class="language-plaintext highlighter-rouge">MessagePack</code> </a>. What we do in MessagePack is use byte control codes to tell the 
receiver of the message what kind of data will follow and how much of it there is. If we did this in spoken language, it would be like we said: “I’m about to tell you 5 words”, then we said “Hello My Name Is Harris”.</p>

<p>Our original 
message above occupies 77 bytes with whitespace removed. Let’s walk through <code class="language-plaintext highlighter-rouge">MessagePack</code> and see how many bytes we can shed! Running our message through 
<code class="language-plaintext highlighter-rouge">MessagePack</code> gives us a 63 byte message:</p>

<figure class="highlight"><pre><code class="language-hex" data-lang="hex">83 a4 6e 61 6d 65 a6 48 61 72 72 69 
73 b3 74 6f 74 61 6c 56 69 63 74 6f 
72 79 52 6f 79 61 6c 65 73 00 a9 6e 
69 63 6b 6e 61 6d 65 73 92 ab 64 75 
63 6b 79 70 6f 74 61 74 6f a5 64 75 
63 6b 79</code></pre></figure>

<p>The first byte <code class="language-plaintext highlighter-rouge">83</code> is a code that indicates that the following message is an Object with 3 fields, the first 4 bits give us <code class="language-plaintext highlighter-rouge">8</code> for object and the last 4 bits tell us the number of fields.</p>

<p>Next, we have <code class="language-plaintext highlighter-rouge">a4</code>. The first four bits <code class="language-plaintext highlighter-rouge">a0</code> tell us that we have a string that is <code class="language-plaintext highlighter-rouge">4</code> bytes long (see the pattern yet?). This means the bytes <code class="language-plaintext highlighter-rouge">6e 61 6d 65</code>
represent <code class="language-plaintext highlighter-rouge">name</code> in ASCII, the name of our field! In the following byte we see <code class="language-plaintext highlighter-rouge">a6</code>, which is a 6 byte string, so <code class="language-plaintext highlighter-rouge">48 61 72 72 69 73</code> must stand for my name (Harris).</p>

<p>Now, the next byte is <code class="language-plaintext highlighter-rouge">b3</code>. The first 4 bytes of this number is still <code class="language-plaintext highlighter-rouge">a0</code>, which means we are still looking at a string, and that string is <code class="language-plaintext highlighter-rouge">b3 - a0 = 13</code> bytes 
long (thats 19 in decimal). This is the bytes <code class="language-plaintext highlighter-rouge">74 6f 74 61 6c 56 69 63 74 6f 72 79 52 6f 79 61 6c 65 73</code> which is our field name <code class="language-plaintext highlighter-rouge">totalVictoryRoyals</code>. Next we have
<code class="language-plaintext highlighter-rouge">00</code>, <code class="language-plaintext highlighter-rouge">0</code> being a code for positive fixed integer and our value being <code class="language-plaintext highlighter-rouge">0</code>. Just like before, <code class="language-plaintext highlighter-rouge">a9</code> is telling us we have a 9 character string which is the 
name of our array, <code class="language-plaintext highlighter-rouge">nicknames</code>.</p>

<p>The next byte is <code class="language-plaintext highlighter-rouge">92</code>. <code class="language-plaintext highlighter-rouge">90</code> tells us we have an array, and <code class="language-plaintext highlighter-rouge">02</code> tells us that array has two elements. Those two elements are encoded just like before, we have
two strings.</p>

<p>That’s a lot to follow, so lets break it down like this:</p>

<table>
  <thead>
    <tr>
      <th>Code</th>
      <th>Meaning</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>83</td>
      <td>Object w/ 3 fields</td>
      <td> </td>
    </tr>
    <tr>
      <td>a4</td>
      <td>4 character string</td>
      <td><code class="language-plaintext highlighter-rouge">6e 61 6d 65</code></td>
    </tr>
    <tr>
      <td>a6</td>
      <td>6 character string</td>
      <td><code class="language-plaintext highlighter-rouge">48 61 72 72 69 73</code></td>
    </tr>
    <tr>
      <td>b3</td>
      <td>19 character string</td>
      <td><code class="language-plaintext highlighter-rouge">74 6f 74 61 6c 56 69 63 74 6f 72 79 52 6f 79 61 6c 65 73</code></td>
    </tr>
    <tr>
      <td>00</td>
      <td>integer whos value are all the lower order bytes</td>
      <td>0</td>
    </tr>
    <tr>
      <td>a9</td>
      <td>9 character string</td>
      <td><code class="language-plaintext highlighter-rouge">6e 69 63 6b 6e 61 6d 65 73</code></td>
    </tr>
    <tr>
      <td>92</td>
      <td>2 element array</td>
      <td><code class="language-plaintext highlighter-rouge">ab</code> 11 Char String, <code class="language-plaintext highlighter-rouge">a5</code> 5 Char String</td>
    </tr>
  </tbody>
</table>

<p>Not bad! We can shed a LOT more bytes with things like <a href="https://en.wikipedia.org/wiki/Protocol_Buffers">ProtocolBuffer</a> which can pack our same
message into a lot fewer bytes. These protocols do this by not encoding the names of our fields. Instead, we specify ahead of time using a schema
definition what our objects are going to look like. For example,</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="n">message</span> <span class="nc">User</span> <span class="p">{</span>
    <span class="n">required</span> <span class="n">string</span> <span class="n">name</span> <span class="o">=</span> <span class="mi">1</span> 
    <span class="n">required</span> <span class="n">int64</span> <span class="n">totalVictoryRoyales</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
    <span class="n">repeated</span> <span class="n">string</span> <span class="n">nicknames</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Now, when we go to encode <code class="language-plaintext highlighter-rouge">totalVictoryRoyals</code>, instead of having to encode all whopping 19 bytes of that field, we simply encode the <code class="language-plaintext highlighter-rouge">2</code> from our
schema. This is called a Field Tag. Then, the ProtocolBuffer library can look up what that 2 means, and decode the bytes properly. By avoiding the <code class="language-plaintext highlighter-rouge">32</code> bytes we needed JUST to encode field names, we can pack our message into a lot less bytes. We can also save our byte to indicate that we have encoded an object
because the ProtocolBuffer schema is already encoding that.</p>

<p>It might look something like this</p>

<figure class="highlight"><pre><code class="language-hex" data-lang="hex">0a 06 48 61 72 72 69 73 10 00 1a B0 
64 75 63 6B 79 70 6F 74 61 74 6F 0A 
1a 05 64 75 63 6B 79 0A</code></pre></figure>

<p>which breaks down as</p>

<table>
  <thead>
    <tr>
      <th>Code</th>
      <th>Meaning</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0a</code></td>
      <td>Field Tag 1, Type String</td>
      <td>length: <code class="language-plaintext highlighter-rouge">06</code>: <code class="language-plaintext highlighter-rouge">48 61 72 72 69 73</code> (Harris)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">10</code></td>
      <td>Field Tag 2, Type Int</td>
      <td><code class="language-plaintext highlighter-rouge">00</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">1a</code></td>
      <td>Field Tag 3</td>
      <td>length: <code class="language-plaintext highlighter-rouge">B0</code>: <code class="language-plaintext highlighter-rouge">64 75 63 6B 79 70 6F 74 61 74 6F 0A</code> (duckypotato)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">1a</code></td>
      <td>Field Tag 3</td>
      <td>length: <code class="language-plaintext highlighter-rouge">05</code>: <code class="language-plaintext highlighter-rouge">64 75 63 6B 79 0A</code> (ducky)</td>
    </tr>
  </tbody>
</table>

<p>Note that we also don’t need to encode any information about our last 2 fields being part of an array. Since we tagged them as being in field tag 3, 
ProtocolBuffer can figure out it needs to place them inside an array. So, our byte count is down to <code class="language-plaintext highlighter-rouge">32</code>. Not so bad.</p>

<h1 id="why-this-is-important">Why this is important</h1>
<p>Okay, we just spent a LOT of time in the weeds of how we can encode information in binary. I’m a little worn out from writing that, and you’re probably
a little confused. Let’s take a massive step back and get some context for why we care.</p>

<p>We want to be able to encode data in such a way that it can still be relevant to something that is not the same OS level process that created that data. 
This situation can come up as:</p>
<ul>
  <li>Sending or requesting data from RESTful API’s</li>
  <li>Sending a message to a message broker such as <a href="https://www.rabbitmq.com/">RabbitMQ</a> or <a href="https://kafka.apache.org/">Kafka</a></li>
  <li>Using <a href="https://en.wikipedia.org/wiki/Remote_procedure_call">Remote Procedure Calls</a> such as <a href="https://grpc.io/">gRPC</a></li>
  <li>Passing messages between concurrent processes as actors in a actor system such as <a href="https://akka.io/">Akka</a></li>
</ul>

<p>We could do this decently enough with the built in serialization that some languages come with, such as Java’s <a href="https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html">built in serialize </a> that Akka uses. WE can use JSON encodings like MessagePack to compatability with most web services. We can also use ProtocolBuffer to drastically reduce the 
amount of space messages take up, at the cost of the up front setup needed to write custom schemas and run a compiler to turn those schemas into language
specific decoders.</p>

<h1 id="references">References</h1>

<p>I made heavy use of the examples that Martin Kleppmann uses in Chapter 4 of <a href="https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/"><em>Designing Data Intensive Applications</em></a>, with some small modifications made so I had to work through the bytes myself. You should definitely 
read this book!</p>]]></content><author><name></name></author><category term="Backend" /><category term="Messages" /><category term="Marshalling" /><category term="Data" /><category term="MessagePack" /><summary type="html"><![CDATA[A running program handles data by keeping it in memory. Some languages may abstract this away from you, but at some point down the stack your program is manipulating data stored in locations in memory. Sometimes, you might want to send this data to another function so it can perform some operation on it. Functions do this by taking the data by reference. That is, they accept as an argument a memory location, and make its operations by referencing that memory location.]]></summary></entry><entry><title type="html">My Promises Crash Course</title><link href="https://blog.harrisferguson.dev/typescript/promises/frontend/2022/08/17/promises.html" rel="alternate" type="text/html" title="My Promises Crash Course" /><published>2022-08-17T15:00:00+00:00</published><updated>2022-08-17T15:00:00+00:00</updated><id>https://blog.harrisferguson.dev/typescript/promises/frontend/2022/08/17/promises</id><content type="html" xml:base="https://blog.harrisferguson.dev/typescript/promises/frontend/2022/08/17/promises.html"><![CDATA[<p>I’ve been doing a lot of front end work lately! It’s been a fun experience, especially since the typical front end technologies aren’t something I was exposed 
to in a major way during school. Today I needed to write a function that required me to actually learn how Javascript Promises work, as well as how to 
aggregate Promises into a single Promise. So, heres a summary of the crash course I had to take.</p>

<h1 id="whats-a-promise">Whats a promise?</h1>

<p>From the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">MDN Docs</a>:</p>

<blockquote>
  <p>The <code class="language-plaintext highlighter-rouge">Promise</code> object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.</p>
</blockquote>

<p>This comes up if you want to query an external API: retrieving data over the network is asynchronous. <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">Javascript’s Fetch API</a>
uses Promises to provide the data from requests once it becomes available. Not only that, but the <code class="language-plaintext highlighter-rouge">async/await</code> pattern that was <a href="https://tc39.es/ecma262/multipage/ecmascript-language-functions-and-classes.html#sec-async-function-definitions">introduced in ES2017</a> 
makes use of Promises under the hood. Use that syntax to avoid <a href="http://callbackhell.com/">👹callback hell👹</a>.</p>

<p>A promise is really just any object or function that implements a <code class="language-plaintext highlighter-rouge">.then()</code> method. That <code class="language-plaintext highlighter-rouge">.then()</code> method needs to accept two arguments: <code class="language-plaintext highlighter-rouge">onFulfilled</code> and <code class="language-plaintext highlighter-rouge">onRejected</code>. 
So, our mental model so far is:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">const</span> <span class="nb">Promise</span> <span class="o">=</span> <span class="p">{</span>
      <span class="na">then</span><span class="p">:</span> <span class="p">(</span><span class="nx">onFulfilled</span><span class="p">,</span> <span class="nx">onRejected</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="c1">// </span>
      <span class="p">}</span>  
<span class="p">}</span></code></pre></figure>

<p><em>If you’re unfamiliar with Javascript or this syntax,</em> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#arrow_functions_used_as_methods"><em>here is a good resource</em></a></p>

<p><code class="language-plaintext highlighter-rouge">onFulfilled</code> and <code class="language-plaintext highlighter-rouge">onRejected</code> need to behave in <a href="https://promisesaplus.com/#the-then-method">specific ways</a>. <code class="language-plaintext highlighter-rouge">onFulfilled</code> needs satisfy:</p>
<ol>
  <li>is called when the Promise is Fulfilled</li>
  <li>is called exactly once</li>
  <li>is NOT called if the Promise is not Fulfilled</li>
</ol>

<p><code class="language-plaintext highlighter-rouge">onRejected</code> is the same, except we call it when the Promise is rejected. These functions are provided by whoever is creating the promise. This means we can supply the 
success / error behavior the promise should have in the form of callbacks. <code class="language-plaintext highlighter-rouge">then()</code> has access to the current state of the promise, which means a promise has to keep some 
internal state with transitions. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#description">This diagram</a> shows what state machine
this object has to implement. So, <code class="language-plaintext highlighter-rouge">then()</code> looks something like:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">const</span> <span class="nb">Promise</span> <span class="o">=</span> <span class="p">{</span>
      <span class="na">then</span><span class="p">:</span> <span class="p">(</span><span class="nx">onFulfilled</span><span class="p">,</span> <span class="nx">onRejected</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="nb">Promise</span><span class="p">.</span><span class="nx">is_fulfilled</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">didNotCallOnFulfilled</span><span class="p">())</span> <span class="p">{</span>
            <span class="nx">onFulfilled</span><span class="p">(</span><span class="nb">Promise</span><span class="p">.</span><span class="nx">result</span><span class="p">)</span>
        <span class="p">}</span>
      <span class="p">}</span>  
<span class="p">}</span></code></pre></figure>

<p>We could go down a rabbit hole of expanding this mental model, but <a href="https://www.promisejs.org/implementing/">here’s a great article</a> walking through what a Promise implementation would look like.
We have enough now to see how we could aggregate promises.</p>

<h1 id="aggregating-promises">Aggregating promises</h1>
<p>Here’s the situation I was in. I was writing a function that was restricted to returning something with a type of <code class="language-plaintext highlighter-rouge">Promise&lt;DataType[]&gt;</code>. However, the only way I could
get access to any elements of <code class="language-plaintext highlighter-rouge">DataType</code> was a function that returned <code class="language-plaintext highlighter-rouge">Promise&lt;DataType&gt;</code>. In code:</p>

<figure class="highlight"><pre><code class="language-typescript" data-lang="typescript"><span class="k">async</span> <span class="kd">function</span> <span class="nx">getDataItem</span><span class="p">(</span><span class="nx">dataId</span><span class="p">):</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">DataType</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="c1">// A working implementation</span>
<span class="p">}</span>

<span class="k">async</span> <span class="kd">function</span> <span class="nx">getDataArray</span><span class="p">(</span><span class="nx">dataIds</span><span class="p">):</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">DataType</span><span class="p">[]</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="c1">// how do I convert return values from the above function into what I need? </span>
<span class="p">}</span></code></pre></figure>

<p>Luckily, the Promises API has a function that can perform this aggregation: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all"><code class="language-plaintext highlighter-rouge">Promise.all()</code>.</a>
Given an iterable of Promises as input, we get back a single promise that will resolve to the array of results. So, we can call our first function to get individual data items from our API,
then package all of those promises into a single promise. The great part is that performance wise this isn’t even that bad: as soon as we call our first function, thats it! It spits back a 
promise that will eventually resolve, and each of those requests aren’t blocking each other. We are doing them in parallel! That looks something like this:</p>

<figure class="highlight"><pre><code class="language-typescript" data-lang="typescript"><span class="k">async</span> <span class="kd">function</span> <span class="nx">getDataItem</span><span class="p">(</span><span class="nx">dataId</span><span class="p">):</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">DataType</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="c1">// A working implementation</span>
<span class="p">}</span>

<span class="k">async</span> <span class="kd">function</span> <span class="nx">getDataArray</span><span class="p">(</span><span class="nx">dataIds</span><span class="p">):</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">DataType</span><span class="p">[]</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="na">promises</span><span class="p">:</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">DataType</span><span class="o">&gt;</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[];</span>
    <span class="nx">dataIds</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">id</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">promises</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">getDataItem</span><span class="p">(</span><span class="nx">id</span><span class="p">));</span>
    <span class="p">});</span>
    <span class="kd">const</span> <span class="nx">aggregatePromise</span> <span class="o">=</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span><span class="nx">promises</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">aggregatePromise</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Pretty neat! The aggregate promise will reject if any of the individual requests reject, and will resolve when every one of the promises have been fulfilled. The promise API
also has some other functions such as <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any"><code class="language-plaintext highlighter-rouge">.any()</code></a> returning the first promise that resolves, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race"><code class="language-plaintext highlighter-rouge">race()</code></a> which resolves when any of the provided promises resolve, and
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled"><code class="language-plaintext highlighter-rouge">allSettled()</code></a> which returns a promise that resolves to an array containing the promises result (reject or resolve).</p>

<p>Extra fun fact, <code class="language-plaintext highlighter-rouge">Promises</code> aren’t supported on internet explorer! ☠️ RIP ☠️.</p>]]></content><author><name></name></author><category term="Typescript" /><category term="Promises" /><category term="Frontend" /><summary type="html"><![CDATA[I’ve been doing a lot of front end work lately! It’s been a fun experience, especially since the typical front end technologies aren’t something I was exposed to in a major way during school. Today I needed to write a function that required me to actually learn how Javascript Promises work, as well as how to aggregate Promises into a single Promise. So, heres a summary of the crash course I had to take.]]></summary></entry><entry><title type="html">Why do the rules of hooks even exist?</title><link href="https://blog.harrisferguson.dev/react/hooks/frontend/2022/08/16/data.html" rel="alternate" type="text/html" title="Why do the rules of hooks even exist?" /><published>2022-08-16T21:30:00+00:00</published><updated>2022-08-16T21:30:00+00:00</updated><id>https://blog.harrisferguson.dev/react/hooks/frontend/2022/08/16/data</id><content type="html" xml:base="https://blog.harrisferguson.dev/react/hooks/frontend/2022/08/16/data.html"><![CDATA[<p>I ran into a sticky hooks situation recently that I was banging my head against for a bit. I had the following situation.</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">const</span> <span class="p">{</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">loading</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useGetData</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">userId</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
<span class="kd">const</span> <span class="p">{</span> <span class="nx">relatedData</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useGetRelatedDataForUser</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span></code></pre></figure>

<p>Often it’s useful to write a custom react hook that interacts with any external data sources. However, in this particular situation I needed to use some data from one API endpoint to fetch data from a second endpoint. The problem comes with the <code class="language-plaintext highlighter-rouge">loading</code> variable that indicates if our API request is still in progress. <code class="language-plaintext highlighter-rouge">data</code> is going to be <code class="language-plaintext highlighter-rouge">undefined</code> as long as we aren’t loading, which means in order to use our second hook we need to wait. Okay, easy enough right?</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">const</span> <span class="p">{</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">loading</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useGetData</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">loading</span><span class="p">){</span>
    <span class="kd">const</span> <span class="nx">userId</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
    <span class="kd">const</span> <span class="p">{</span> <span class="nx">relatedData</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useGetRelatedDataForUser</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>Unfortunately if you try to run this, you might see something like the following in the console:</p>

<p><code class="language-plaintext highlighter-rouge">🚨🚨 THIS BREAKS THE RULES OF HOOKS 🚨🚨 READ THE RULES OF HOOKS 🚨🚨</code></p>

<p>Having seen this error and other related errors in my console before, I thought I would actually learn why the rules exist, and lucky for me our facebook overlords figured people might wonder <a href="https://reactjs.org/docs/hooks-rules.html#explanation">why the rules exist</a>. Here are <a href="https://dev.to/wuz/linked-lists-in-the-wild-react-hooks-3ep8">some</a> <a href="https://reactjs.org/docs/hooks-faq.html#how-does-react-associate-hook-calls-with-components">other</a> <a href="https://overreacted.io/how-does-setstate-know-what-to-do/">amazing</a> resources I used while figuring this out.</p>

<p>The basic problem is this: how do we distinguish calls to the same hook that are controlling a different state value? For example:</p>

<figure class="highlight"><pre><code class="language-react" data-lang="react"><span class="kd">const</span> <span class="nx">ClickCount</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="p">[</span><span class="nx">rightCount</span><span class="p">,</span> <span class="nx">setRightCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="kd">const</span> <span class="p">[</span><span class="nx">leftCount</span><span class="p">,</span> <span class="nx">setLeftCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="k">return</span> <span class="p">(</span>
        <span class="p">&lt;&gt;</span>
            <span class="p">&lt;</span><span class="nt">div</span><span class="p">&gt;</span><span class="si">{</span><span class="s2">`Right: </span><span class="p">${</span><span class="nx">rightCount</span><span class="p">}</span><span class="s2"> Left: </span><span class="p">${</span><span class="nx">leftCount</span><span class="p">}</span><span class="s2">`</span><span class="si">}</span><span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
            <span class="p">&lt;</span><span class="nc">Button</span> <span class="na">onClick</span><span class="p">=</span><span class="si">{</span><span class="p">()</span><span class="o">=&gt;</span><span class="p">{</span><span class="nx">setRightCount</span><span class="p">(</span><span class="nx">rightCount</span><span class="o">+</span><span class="mi">1</span><span class="p">)}</span><span class="si">}</span> <span class="p">/&gt;</span>
            <span class="p">&lt;</span><span class="nc">Button</span> <span class="na">onClick</span><span class="p">=</span><span class="si">{</span><span class="p">()</span><span class="o">=&gt;</span><span class="p">{</span><span class="nx">setLeftCount</span><span class="p">(</span><span class="nx">leftCount</span><span class="o">+</span><span class="mi">1</span><span class="p">)}</span><span class="si">}</span> <span class="p">/&gt;</span>
        <span class="p">&lt;/&gt;</span>
    <span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>React needs to keep track of which state values corresponds to which <code class="language-plaintext highlighter-rouge">useState</code> call. If I try to access one of <code class="language-plaintext highlighter-rouge">leftCount</code> and <code class="language-plaintext highlighter-rouge">rightCount</code>, React needs to access the correct state value.</p>

<p>React does this by keeping a <a href="https://github.com/facebook/react/blob/5f06576f51ece88d846d01abd2ddd575827c6127/packages/react-reconciler/src/ReactFiberHooks.js#L85">linked list of hooks</a>, and relying on the hooks always being called in the same order. In fact, component state itself is kept as a linked list. When hooks are called, we append a state to the linked list of hook states, and then move to the next spot in the linked list. This explains why we can’t have hooks in conditionals: if we allowed hooks in conditionals, we could be at the wrong state node for the state we are calling!</p>

<p>What about the other rule: we can’t have hooks outside react function components. Well this is easy to explain with what we know now. Hooks need to be associated with the state of some component in order to work. If we call them outside of a react component, the react engine won’t be able to make this association since it really isn’t associated with any react component.</p>

<p>Hopefully thats not too hard to follow. I know I had a tough time grappling with all the resources I used.</p>

<p>So, how did I fix my initial problem? I wish I had a nice answer, but it came down to using <code class="language-plaintext highlighter-rouge">useEffect</code> with a whole lot of null checks sadly. The solution was not nearly as interesting as my investigation into Hooks.</p>]]></content><author><name></name></author><category term="React" /><category term="Hooks" /><category term="Frontend" /><summary type="html"><![CDATA[I ran into a sticky hooks situation recently that I was banging my head against for a bit. I had the following situation.]]></summary></entry><entry><title type="html">How I didn’t write a unit test</title><link href="https://blog.harrisferguson.dev/misc/testing/deploy/failure/2022/08/16/woah.html" rel="alternate" type="text/html" title="How I didn’t write a unit test" /><published>2022-08-16T04:30:00+00:00</published><updated>2022-08-16T04:30:00+00:00</updated><id>https://blog.harrisferguson.dev/misc/testing/deploy/failure/2022/08/16/woah</id><content type="html" xml:base="https://blog.harrisferguson.dev/misc/testing/deploy/failure/2022/08/16/woah.html"><![CDATA[<p>In school, one thing I never really experienced is software failures. If there were glaring issues you didn’t catch, you got a <code class="language-plaintext highlighter-rouge">-N</code> points on your mark and you never really had to deal with the issue. However, now that I’m working I’ve had to experience the fallout of bad code. Nothing as jarring to a new developer like myself as coming in to work the next day and hearing you broke something for 30+ important customers 😓.</p>

<p>The actual issue was pretty small and simple:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">findItem</span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">id</span><span class="p">){</span>
    <span class="k">return</span> <span class="nx">array</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">item</span> <span class="o">=&gt;</span> <span class="nx">item</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">id</span><span class="p">).</span><span class="nx">name</span> <span class="o">||</span> <span class="nx">DEFAULT_ITEM</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This little snippet prevented a core page in the app from rendering. The array in question contained configuration info for a series of supported integrations, and given the account had an unsupported integration value we would default to <code class="language-plaintext highlighter-rouge">DEFAULT_ITEM</code>. The original check was:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">findItem</span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">id</span><span class="p">){</span>
    <span class="k">return</span> <span class="nx">array</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">item</span> <span class="o">=&gt;</span> <span class="nx">item</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">id</span><span class="p">)</span> <span class="o">||</span> <span class="nx">DEFAULT_ITEM</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>For those unfamiliar with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find">Javascript’s <code class="language-plaintext highlighter-rouge">Array.find()</code></a>:</p>

<blockquote>
  <p>The find() method returns the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.</p>
</blockquote>

<p>My initial thinking was: if <code class="language-plaintext highlighter-rouge">find()</code> returns undefined, it means we didn’t find something to match, we “short circuit” and evaluate the right hand side of the expression, which will return the <code class="language-plaintext highlighter-rouge">DEFAULT_ITEM</code>. However, I later realized the component which would call this function would need the <code class="language-plaintext highlighter-rouge">.name</code> value of the config object. I added that evaluation in without checking that my logic was still valid: in my head I assumed that my <code class="language-plaintext highlighter-rouge">||</code> would still catch any unsupported values. I didn’t stop to asses that my previous logic was still valid, and I didn’t write a test that enforced that logic in code. Lo and behold when <code class="language-plaintext highlighter-rouge">find()</code> doesn’t pass the predicate function and we try to access <code class="language-plaintext highlighter-rouge">undefined.name</code> the component doesn’t render 💀.</p>

<p>And, it ended up shipping.</p>

<p>Really this is a silly mistake that could have been caught by me writing that unit test, or caught in PR, or with more testing on our Sandbox. Before writing the initial function I should have written a test that might have caught this mistake, but I didn’t! To be fair, the people who reviewed this could have also noticed this, but the issue only came up with unsupported integrations and the accounts I set up for testing all used supported integrations.</p>

<p>My takeaways:</p>
<ul>
  <li>I probably should have written a unit test for this function. I neglect writing front end tests because setting up mocking in jest is really painful for React. I have to get over the hump of it being frustrating to do and either just do it or find a way to make it easier!</li>
  <li>I should bake the assumptions about my code into a unit test. That way, once situations change I have tests to rely on to check that my logic is still valid.</li>
  <li>I should have considered the case where someone doesn’t have a supported integration. More generally, I find I rush when it comes to the UAT stage. I should take the time to consider edge cases and failure points.</li>
  <li>Something I want to leverage and learn more about in general is End to End tests. While something as small as this could have been caught by unit tests or a UAT step, having a worst case fallback of a good end to end test would easy my mind. (Maybe its time I actually look into Cypress…)</li>
</ul>

<p>So, a small mistake but I finally learned something that I’ve probably read and heard hundreds of times: WRITE TESTS!</p>]]></content><author><name></name></author><category term="misc" /><category term="testing" /><category term="deploy" /><category term="failure" /><summary type="html"><![CDATA[In school, one thing I never really experienced is software failures. If there were glaring issues you didn’t catch, you got a -N points on your mark and you never really had to deal with the issue. However, now that I’m working I’ve had to experience the fallout of bad code. Nothing as jarring to a new developer like myself as coming in to work the next day and hearing you broke something for 30+ important customers 😓.]]></summary></entry></feed>