<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Justin Fuller</title>
    <description>The latest articles on DEV Community by Justin Fuller (@justindfuller).</description>
    <link>https://dev.to/justindfuller</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F156913%2F49fea402-4488-462c-bbf5-7fa610282cd8.jpeg</url>
      <title>DEV Community: Justin Fuller</title>
      <link>https://dev.to/justindfuller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/justindfuller"/>
    <language>en</language>
    <item>
      <title>Twilight of the Software Engineering Team</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Mon, 05 Jan 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/justindfuller/twilight-of-the-software-engineering-team-2ef2</link>
      <guid>https://dev.to/justindfuller/twilight-of-the-software-engineering-team-2ef2</guid>
      <description>&lt;p&gt;Does the advancement of AI-driven development call for a new type of team?&lt;/p&gt;

&lt;p&gt;So far in my career, each of my teams has been staffed with some combination of: product manager, engineering manager, designer, data analyst, QA tester, and software engineer. Usually, a lot of software engineers.&lt;/p&gt;

&lt;p&gt;Every one of those teams had two broad principles: first, move fast; second, make few mistakes.&lt;/p&gt;

&lt;p&gt;Each team enacted these principles differently. For example, at a startup, we pursued speed with long hours and manual testing. At the banks, we stuck to tried-and-true tech stacks and rigorous testing protocols. Now, at The Times, my teams attempt to balance speed and correctness with developer tooling, such as robust CI pipelines.&lt;/p&gt;

&lt;p&gt;Yet, regardless of each team's appetite for mistakes, they had one thing in common: the desire to move &lt;em&gt;faster&lt;/em&gt;. There was always an ever-growing backlog of JIRA tickets. Those JIRA backlogs always grew faster than tickets closed. Ideas have always been cheaper to articulate than to implement. At least, until recently. Now, articulation and implementation are converging.&lt;/p&gt;

&lt;p&gt;Even though the bottleneck was different for each team, it basically came down to one thing: engineering time. Occasionally, engineers would be stuck waiting on a product spec or a visual design, but that was rare. Even when this happened, the engineers typically had enough business context and design savvy to create a working MVP while waiting on the real specs and designs. In my career, I've only seen an engineer waiting around with nothing to do a few times. When all else fails, there's always some tech debt to clean up.&lt;/p&gt;

&lt;p&gt;So, in my experience, the bottleneck has always been engineering. This is not an insult to any engineer's ability. These were teams of knowledgeable, efficient, highly capable engineers. Yet, we were always the bottleneck. This is because the process of engineering non-trivial software has historically taken a long time. Time spent hands-to-keyboard comprised only a small fraction of that time.&lt;/p&gt;

&lt;p&gt;On any given project, engineers need to: understand the change, understand relevant parts of the code, determine how to implement the change, write the code, debug the code, test the code, optimize the code, deploy, and monitor. Code review and meetings occasionally (or often) disrupt these tasks.&lt;/p&gt;

&lt;p&gt;Of course, some engineers and teams have fewer steps than these. Some have even more. But, in general, the shape of a project is roughly like that. It takes a lot of time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg04o27mswpopdddfcbra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg04o27mswpopdddfcbra.png" alt="A rough sketch of typical Software Engineering teams." width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or, at least, it &lt;em&gt;took&lt;/em&gt; a lot of time. Recently, our industry created (and parts of it have embraced) what can only be called dynamite for the old way of operating. This new technology can automate, to varying extents (based on both who you ask and where and how you use it), nearly all of the above tasks. And it's only getting better. New releases go out each month proclaiming that they are achieving even better results. More services are integrating with agentic coding assistants. The effectiveness and reach of the dynamite's blast only grows.&lt;/p&gt;

&lt;p&gt;In my experience, these claims are valid. &lt;a href="https://www.justindfuller.com/programming/my-claude-code-setup" rel="noopener noreferrer"&gt;I have written&lt;/a&gt; about how I am producing all of my production, user-facing, business-critical software with agentic coding assistant tools like Claude Code. I am able to generate far, far more code than I could before. I now have a new problem: I can generate more code than either myself or my team can handle. It's now the humans who are slowing down the agents.&lt;/p&gt;

&lt;p&gt;Software engineers producing code is no longer the bottleneck.&lt;/p&gt;

&lt;p&gt;The very structure of our teams needs to change to accommodate this new world.&lt;/p&gt;

&lt;p&gt;I believe this is the twilight of the software engineering team.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dawn of the Agentic Team
&lt;/h2&gt;

&lt;p&gt;Now that we can produce 10x and potentially even 100x more code than we could before, we have a new problem. How can we manage such gargantuan quantities of code while maintaining quality? Every time I log in to LinkedIn, I see warnings about the perils of low-quality AI-generated code, "slop." It is clear many are running into the same problem.&lt;/p&gt;

&lt;p&gt;One option is to arbitrarily slow down the teams to the pace they are currently capable of. This may be due to individuals rejecting the technological advancement, fear, or moral concerns. These fears and concerns are valid. They should be talked about and treated seriously. The moral concerns should be addressed, primarily politically but also by consumers voting with their wallets.&lt;/p&gt;

&lt;p&gt;Right now, both politically and economically, the broad consensus appears to be that AI is the future (despite predictions of an imminent bubble pop). This applies to professional and personal settings. Claude Code is on my work computer, generating code with the blessing and funding of my employer. ChatGPT is on my phone, answering questions in my personal life. To be clear, this is not to say we should stop pursuing solutions to copyright, economic, and environmental issues. However, it does suggest those solutions will need to happen within the context of an AI-centered world. Abandonment seems to be a non-starter.&lt;/p&gt;

&lt;p&gt;If ignoring AI won't work, the other option is to adapt. We must enable our teams to effectively manage increased output. Both options intend to maintain the level of quality. Only one attempts to maintain quality while increasing output.&lt;/p&gt;

&lt;p&gt;What would this new team look like? For starters, it would need fewer people producing code. With Claude Code or similar tools, a single engineer can work on multiple projects at once. Personally, I've been able to effectively manage up to six simultaneous projects with agentic coding assistants. Beyond six, it can be quite difficult to manage. I believe with improved models and better tooling, our coding agents will require less babysitting. The number of concurrent projects per engineer will only increase.&lt;/p&gt;

&lt;p&gt;So, we’ll need fewer Software Engineers focused on code output. That neither means we need fewer Software Engineers nor smaller teams. To the contrary, our ability to generate more code suggests we could use more people. We will produce more software than ever before. However, those same people will carry out vastly different tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xqbus8w87yse6vp1n07.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xqbus8w87yse6vp1n07.png" alt="One idea for a new agent-centric Software team." width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before, the primary bottleneck was generating correct code. The new bottlenecks will be: identifying work, designing changes, creating technical specs, reviewing the sheer quantity of code produced, and managing the agent's supporting tools. These problems still require deep technical expertise — applied to different areas.&lt;/p&gt;

&lt;p&gt;An experienced engineer on the team may now need to focus more on providing high-quality technical specs. These may take the form of JIRA tickets or similar. Those specs will be an important part of the agent’s prompt.&lt;/p&gt;

&lt;p&gt;Another engineer (or multiple) may need to focus on reviewing the enormous volume of code. Agents could use their feedback to iterate on a PR. These engineers would not generate code but spend the bulk of their time reading, validating, and articulating feedback for the agents to act on.&lt;/p&gt;

&lt;p&gt;Other engineers may need to focus on building tools for agents, much like some engineers today may focus on building pipelines and developer tooling. These engineers may connect the agent to other tools like JIRA, GitHub, Slack, PagerDuty, Google Docs/Sheets, and Datadog. The possibilities are endless. The goal of this engineer would be to continually streamline the use of agentic coding assistants.&lt;/p&gt;

&lt;p&gt;This is still a highly skilled, technical team. However, the shift in focus would reflect moving bottlenecks caused by evolving technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;In reality, AI may produce teams that are very different from what I’ve described above. I do not feel confident about any particular team shape. Instead, I feel confident about two things.&lt;/p&gt;

&lt;p&gt;First, I believe teams that do not adjust to this new world will continually feel frustrated. They will experience the volume of output created by agentic tools as a detriment, and rightfully so. The current shape of Software Engineering teams is &lt;em&gt;not&lt;/em&gt; equipped to handle this volume. Imagine a hose designed to output 20 liters of water per minute. You’re going to have a bad time if you suddenly try to 10x that volume.&lt;/p&gt;

&lt;p&gt;I am not saying those teams will not succeed. Just like there are successful teams still working with waterfall instead of agile, there will still be successful Software Engineering teams in the AI era. I am specifically warning against the mixing of high-output agentic coding assistants with a human-coder-centered team structure.&lt;/p&gt;

&lt;p&gt;Second, I believe the evolution will be messy. This is a rapidly evolving technology. Teams should continually experiment with new structures. Some will fail. Some will work for a time, then stop working when the technology advances further. I believe this will be an uncomfortable but healthy part of the industry’s evolution. Engineering leaders should embrace this discomfort and adopt an experimentation mindset with their teams. They should try five different structures in five different teams, then adopt whatever works best, wherever it works best.&lt;/p&gt;

&lt;p&gt;Some teams may need to stack heavily on code review. Others may need to focus on automation. Still others, testing. The bottleneck has shifted, but we do not yet understand how to best adapt to it. My intention with the description above is to articulate just one possibility and to encourage the industry to imagine what teams could be like in this new world.&lt;/p&gt;




&lt;p&gt;This post originally appeared on &lt;a href="https://www.justindfuller.com/programming/twilight-of-the-software-engineering-team" rel="noopener noreferrer"&gt;justindfuller.com&lt;/a&gt;. You can follow me on &lt;a href="https://www.linkedin.com/in/justin-fuller-8726b2b1" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://github.com/JustinDFuller" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>agentic</category>
    </item>
    <item>
      <title>Keeping One Tab Open</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Sun, 18 Dec 2022 01:14:00 +0000</pubDate>
      <link>https://dev.to/justindfuller/keeping-one-tab-open-3k23</link>
      <guid>https://dev.to/justindfuller/keeping-one-tab-open-3k23</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appear at &lt;a href="https://www.justindfuller.com/2022/12/keeping-one-tab-open/" rel="noopener noreferrer"&gt;justindfuller.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Recently, someone found the maximum number of tabs that Microsoft Edge can handle.
The number is &lt;a href="https://www.reddit.com/r/MicrosoftEdge/comments/zgwt1f/edge_crashed_with_1600_open_tabs_clicked_inbuilt/" rel="noopener noreferrer"&gt;sixteen hundred&lt;/a&gt;.
One tab over this and it crashes.&lt;/p&gt;

&lt;p&gt;Not too long ago, I felt like my brain had sixteen hundred tabs open at all times.
Even while I focused on one task, I would keep several tabs open in the background,
mostly to remember to do things after the current task.&lt;/p&gt;
&lt;p&gt;I’d try to remember:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What I planned to do next&lt;/li&gt;
&lt;li&gt;The email or slack message I need to follow up on&lt;/li&gt;
&lt;li&gt;Questions I need to ask my team&lt;/li&gt;
&lt;li&gt;Issues I need to address&lt;/li&gt;
&lt;li&gt;And so much more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even when I focused deeply on a task, I still had to dedicate a large portion of my processing
power to all these other “open tabs” that I needed to hold on to.&lt;/p&gt;
&lt;p&gt;It’s not just a metaphor, though. This was reflected in the literal open browser tabs on my computer.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Ftabs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Ftabs.png" alt="Tabs" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At any given time, I would have open:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The current page I’m working on, perhaps adjusting a component or adding a feature&lt;/li&gt;
&lt;li&gt;MDN or StackOverflow to answer some question I have, related to the current task&lt;/li&gt;
&lt;li&gt;Maybe a few more MDN and StackOverflow tabs that &lt;em&gt;might&lt;/em&gt; be useful&lt;/li&gt;
&lt;li&gt;Gmail, google calendar, jira, trello&lt;/li&gt;
&lt;li&gt;Some blog posts I want to read later&lt;/li&gt;
&lt;li&gt;Random tabs I opened and forgot about but I’m not sure I’m ready to close them yet&lt;/li&gt;
&lt;li&gt;And probably a lot more too&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This trend of open tabs and “open tabs” continued until I discovered the book, &lt;a href="https://amzn.to/3PwjIBV" rel="noopener noreferrer"&gt;Getting Things Done: The Art of Stress-Free Productivity&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="write-it-down"&gt;Write It Down&lt;/h2&gt;
&lt;p&gt;Most people laugh or don’t believe me when I try to explain how helpful this method is, because it sounds too simple.&lt;/p&gt;
&lt;p&gt;If you have something you need to remember: &lt;strong&gt;write it down&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Once you write it down in a place that you can easily come back to later, you can finally close that open tab.
Once you write down everything that you need to remember, you can close &lt;em&gt;all&lt;/em&gt; of your open tabs and start to truly focus on one thing at a time.&lt;/p&gt;
&lt;p&gt;For this to work, you need to write it down in a place that…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is consistent across all the things you think about&lt;/li&gt;
&lt;li&gt;You can trust to remind you&lt;/li&gt;
&lt;li&gt;Allows you to prioritize and reprioritize tasks&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="trello"&gt;Trello&lt;/h2&gt;
&lt;p&gt;For the rest of this post, I will show you how I use &lt;a href="https://www.trello.com" rel="noopener noreferrer"&gt;Trello&lt;/a&gt; to keep one tab open.
However, Trello is just one of many tools that you can use. It probably will not be right for everyone.
I hope what you’ll see is the strategy I use, rather than the specific tool I use to accomplish it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Fliving_on_24_hours_a_day_trello.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Fliving_on_24_hours_a_day_trello.png" alt="Trello" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="step-1-record-all-inputs"&gt;Step 1: Record All Inputs&lt;/h2&gt;
&lt;p&gt;Throughout your day you’ll receive countless inputs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Emails&lt;/li&gt;
&lt;li&gt;Old-school snail-mail&lt;/li&gt;
&lt;li&gt;Slack messages&lt;/li&gt;
&lt;li&gt;Texts&lt;/li&gt;
&lt;li&gt;Calendar Invites&lt;/li&gt;
&lt;li&gt;Your spouse asking you to do something&lt;/li&gt;
&lt;li&gt;You’ll notice an issue with your house or work&lt;/li&gt;
&lt;li&gt;You’ll remember something you forgot to take care of&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typically, you have a few options to handle these inputs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Completely ignore it&lt;/li&gt;
&lt;li&gt;Try to remember it for later&lt;/li&gt;
&lt;li&gt;Drop what you’re doing to handle it immediately&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But there is another way: record the input, along with any relevant information such as dates or links, so that you can come back to it later.&lt;/p&gt;
&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Ftodo_column.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Ftodo_column.png" alt="TODO Column" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;For me, this looks like dropping a new card in my TODO column in Trello.
When I notice a slack message or email that requires follow-up, I drop a card in the column.&lt;/p&gt;
&lt;h2 id="step-2-add-detail"&gt;Step 2: Add Detail&lt;/h2&gt;
&lt;p&gt;The cards alone are useful as a prioritization and reminder tool.
However, the real benefit materializes only when you are able to decrease your mental load and “close some tabs”.&lt;/p&gt;
&lt;p&gt;That’s where adding detail comes in.&lt;/p&gt;
&lt;p&gt;When I create a card, I add:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Any relevant links to get me back to the slack message, email, or related information&lt;/li&gt;
&lt;li&gt;A brief description containing whatever thoughts I have on the task.
&lt;ul&gt;
&lt;li&gt;“Make sure to talk to XYZ person about this before responding”&lt;/li&gt;
&lt;li&gt;“See if this has already been implemented in another system”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A due date if there’s a deadline or even ideal time to have this task complete&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Fdetails.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Fdetails.png" alt="Card Details" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Details are crucial to staying focused.
With only the card you have a reminder of what you need to do, but not how to do it.
So you may find that the task itself is off your mind, but you’re still attempting to hold on to all the extra things required to complete the task.&lt;/p&gt;
&lt;h2 id="step-3-focus"&gt;Step 3: Focus&lt;/h2&gt;
&lt;p&gt;This is the hardest part. You now have the tools to focus on one task at a time.
But it still takes conscious effort to do so.&lt;/p&gt;
&lt;p&gt;In Trello, this looks like literally one card in the “Doing” tab at all times.
There should always be a card in that tab unless you are actively choosing to be “off” or “wasting time” (which is a totally valid and normal thing to do, by the way, life isn’t only about productivity).&lt;/p&gt;
&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Fdoing_tab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.justindfuller.com%2Fdoing_tab.png" alt="One Open Task" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2 id="switching-tasks"&gt;Switching Tasks&lt;/h2&gt;

&lt;p&gt;It’s pretty common to start a task, only to be interrupted and forced to switch to another task.
This is notoriously difficult for “knowledge workers” like Software Engineers.
However, your cards can help you context switch easily.&lt;/p&gt;

&lt;p&gt;When switching tasks, you need to be able to completely turn off the current task and focus on the new one.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write down any new details you’ll need to remember when coming back.&lt;/li&gt;
&lt;li&gt;Add relevant links, such as the path to the file you were working in or the StackOverflow answer you were reading.&lt;/li&gt;
&lt;li&gt;Move the task back to “TODO”&lt;/li&gt;
&lt;li&gt;If the new task will take more than 5 minutes: Create a card for it and move it to “Doing”.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="finishing-tasks"&gt;Finishing Tasks&lt;/h2&gt;

&lt;p&gt;Whenever you finish a task, move it to the “Done” column.&lt;/p&gt;

&lt;p&gt;At the end of each week, I review the completed tasks to see if I’m satisfied with my work.&lt;/p&gt;

&lt;p&gt;I like to ask myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did I spend my time wisely this week?&lt;/li&gt;
&lt;li&gt;Did I get stuck on a certain task for too long?&lt;/li&gt;
&lt;li&gt;What were the affects or results of the tasks I completed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I’m not satisfied, I try to understand why, and prepare to spend my time differently in the next week.&lt;/p&gt;

&lt;h2 id="cleaning-up"&gt;Cleaning Up&lt;/h2&gt;

&lt;p&gt;The more you do this, the more you will accumulate cards.
At the end of each week, I move my “Done” column to a different board.
I don’t delete the cards, because I occasionally like to browse back through them to do a longer
retro on my work.&lt;/p&gt;

&lt;p&gt;I also set up an automation to remove cards that are older than thirty days.
Again, it does not delete the cards, it moves them to an “Archive” board.
I do this because I have a lot of ideas, but often find that they are unimportant to me a month later.
I think it’s healthy to let go of ideas once I no longer feel they are relevant.
I don’t need to power through unimportant tasks, just because I incorrectly thought they were important in the past.&lt;/p&gt;





&lt;h2 id="putting-it-all-together"&gt;Putting it All Together&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Write down every input&lt;/li&gt;
&lt;li&gt;Record enough details that you can truly get it off your mind&lt;/li&gt;
&lt;li&gt;Focus on one task at a time&lt;/li&gt;
&lt;li&gt;Do a weekly retro on your completed tasks&lt;/li&gt;
&lt;li&gt;Regularly prune your tasks to focus on only what is currently relevant&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>technology</category>
      <category>productivity</category>
      <category>focus</category>
    </item>
    <item>
      <title>Why do we fall into the rewrite trap?</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Tue, 21 Jan 2020 12:20:25 +0000</pubDate>
      <link>https://dev.to/justindfuller/why-do-we-fall-into-the-rewrite-trap-211e</link>
      <guid>https://dev.to/justindfuller/why-do-we-fall-into-the-rewrite-trap-211e</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://justindfuller.com/2020/01/why-do-we-fall-into-the-rewrite-trap?utm_source=Dev.To&amp;amp;utm_medium=referral&amp;amp;utm_campaign=learning_javascript" rel="noopener noreferrer"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of my favorite reads is Joel Spolsky's &lt;a href="https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/" rel="noopener noreferrer"&gt;Things You Should Never Do&lt;/a&gt;. He wrote this post almost twenty years ago, outlining the downfall of Netscape and others because they spent years rewriting working code. His solution is, unsurprisingly, to refactor. About a year before Joel wrote &lt;em&gt;Things You Should Never Do&lt;/em&gt;, Martin Fowler published his popular book, &lt;a href="https://amzn.to/2R6rFkP" rel="noopener noreferrer"&gt;Refactoring: Improving the Design of Existing Code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, my question is, if we as a community figured out — twenty years ago — that we should stop rewriting programs, why is it still commonly done today?&lt;/p&gt;

&lt;h2&gt;
  
  
  My History
&lt;/h2&gt;

&lt;p&gt;To figure out why we keep falling into the rewrite trap, I want to first step back through a few points in my history. &lt;/p&gt;

&lt;h3&gt;
  
  
  Cold–what?
&lt;/h3&gt;

&lt;p&gt;My first job was with a fun, scrappy startup called &lt;a href="//www.signupgenius.com"&gt;SignUpGenius&lt;/a&gt;. Most of SignUpGenius's code had been written before I was even thinking of becoming a web developer, on a platform called Coldfusion (you've probably never heard of it), with a sprinkling of Angular.js. We had no microservices, no Node.js, no React, Go, Docker, or Kubernetes. Our production deployment consisted of arriving early in the morning to manually copy over files and debug issues (I told you we were scrappy).&lt;/p&gt;

&lt;p&gt;Yes, this situation is not ideal and, no, I am not advocating for anyone to manually FTP files for their production deploys. However, one thing that cannot be denied is that we were very productive. Granted, the Coldfusion code was old, but we were constantly improving it. There was never talk of a rewrite; instead, the code was improved, little by little, each time we worked on adding a feature or fixing a bug.&lt;/p&gt;

&lt;p&gt;The results were clear: in my time at SignUpGenius I was able to see the company gain market share; with increased traffic, revenue, and even a buyout of a competitor. &lt;/p&gt;

&lt;p&gt;The code wasn't perfect — far from it, as any codebase would be after ten years — but if we had stopped to rewrite the whole thing we would have been dead in the water and the company would have suffered. Just like in Joel's post, where Netscape took years to rewrite its already working code, rewriting code because Coldfusion was "dead" or "inferior" would have served little business purpose. &lt;/p&gt;

&lt;p&gt;I understand there are plenty of counter-arguments to be made here. First and foremost, it gets harder every day to find a Coldfusion developer. Those who know the platform are most likely looking to give a facelift to their skillset, rather than prolonging the inevitable drying-up of the proverbial job pool. More, it may be harder to implement functionality in Coldfusion, particularly the kind we were dealing with, than, say, in .Net, Ruby on Rails, or even Go.&lt;/p&gt;

&lt;p&gt;Even so, there are other, better ways to move toward new technology without rewriting an entire codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Taking advantage of new technologies
&lt;/h3&gt;

&lt;p&gt;If I think SignUpGenius was doing the right thing by not rewriting, how, then, how does one take advantage of new technologies? &lt;/p&gt;

&lt;p&gt;This brings me to the next chapter of my professional career, when I found myself at &lt;a href="https://www.fisglobal.com/" rel="noopener noreferrer"&gt;FIS Global&lt;/a&gt; (the biggest company you've never heard of), working on user experiences with the wealth and retirement division.&lt;/p&gt;

&lt;p&gt;Our team found a very specific problem: the websites for 401k plan participants and sponsors were horrendous. Not just in how they looked (but they did look pretty terrible) but also in how participants could interact with them.&lt;/p&gt;

&lt;p&gt;The company had built heavily around .NET, which, while it has its merits, did not provide the type of experience that was best for this environment.&lt;/p&gt;

&lt;p&gt;To understand why, you must first understand that interactions with your 401k plan are not like your interactions with, say, Amazon. On Amazon, you are probably going to a specific shopping page that you want to load very quickly. You're also probably not very likely to use more than a couple of pages of the website (possibly a search page, a few products, and the checkout). The pages are not necessarily related to each other. There's no reason to load them all up at once, in fact, there's plenty of reasons not to.&lt;/p&gt;

&lt;p&gt;However, your retirement website is very different. When you go to it you are not trying to load it as quickly as possible to make an impulsive purchase of some ETFs — you're probably doing your yearly check-in or enrolling for the first time. You'll probably check your balance, your contributions, the performance of your holdings, and maybe even download a few tax documents.&lt;/p&gt;

&lt;p&gt;We found that users were coming less often, while spending far more time on the website, using many parts of it — the perfect use-case for a single-page web application. The initial load time was a low priority while seamless transitions between pages were of great value.&lt;/p&gt;

&lt;p&gt;So, what did we do? Did we rewrite the whole application? No.&lt;/p&gt;

&lt;p&gt;Existing applications' UI code was refactored, reorganized, and maybe even rewrapped with a framework like Angular. New applications were kept separate and had new code written with the new paradigm. &lt;/p&gt;

&lt;p&gt;This allowed for a quick, gradual, and seamless transition from old technology to new, with very little loss of all those years worth of things like tests and bug fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contempt Culture
&lt;/h2&gt;

&lt;p&gt;Unfortunately, some developers and institutions bank hard on convincing others that a rewrite is the best use of their money. To do this they rely on convincing others of the inferiority of older, battle-tested languages like Java and PHP to newly popular technologies like Node.js or Go. &lt;/p&gt;

&lt;p&gt;They don't just stop at "Go is better than Java for this problem" — no, they say Java is always bad, always the wrong choice, and our existing Java projects are terrible messes that need to be rewritten. Maybe, even, the experienced Java developers that we have aren't as good as we once thought.&lt;/p&gt;

&lt;p&gt;This is &lt;a href="https://blog.aurynn.com/2015/12/16-contempt-culture" rel="noopener noreferrer"&gt;contempt culture&lt;/a&gt; and it's prevalent in some software development communities. I know this because I was one of the developers who called old languages terrible, clunky, slow while claiming the superiority of my language of choice.&lt;/p&gt;

&lt;p&gt;That is until I started learning about and using some of those older languages.&lt;/p&gt;

&lt;p&gt;When I read through &lt;a href="https://amzn.to/3amlznX" rel="noopener noreferrer"&gt;Robert Martin's Clean Code Series&lt;/a&gt; I was struck by how easy it was to understand the Java and &lt;a href="https://amzn.to/2TFnMF5" rel="noopener noreferrer"&gt;C++&lt;/a&gt; code that he wrote. I realized that the Java and C++ he was writing was far easier to understand than the JavaScript and Go that I had been writing for a few years. The same thing happened when I read through &lt;a href="https://amzn.to/2R6rFkP" rel="noopener noreferrer"&gt;Martin Fowler's Refactoring&lt;/a&gt; — he transformed hard to understand, hard to change Java into code that is clear and easy to change to meet new requirements.&lt;/p&gt;

&lt;p&gt;After starting a new job at &lt;a href="https://open.nytimes.com" rel="noopener noreferrer"&gt;The New York Times&lt;/a&gt; — which has amazing code quality, and not just for an organization that is over 150 years old — I found that the company still has some legacy Java and PHP services. I was scared when I heard that I needed to research how to interact with these APIs — until I saw the code. It turns out that these services are so well-factored, with such well-established patterns, that they were incredibly easy to understand. Less than two months into the job and I was able to traverse several of these codebases to find exactly what I needed.&lt;/p&gt;

&lt;p&gt;So much for contempt culture, these older languages can be great.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rewrite
&lt;/h2&gt;

&lt;p&gt;Back to rewrites. I mentioned earlier that some developers rely on convincing their managers that a rewrite is necessary; in some cases, even multiple-year, large team efforts to completely rewrite existing codebases. I've even seen a case where there were multiple rewrites in a row. Did no one stop to think, "if I didn't get it right the first few times, why would I get it right this time?"&lt;/p&gt;

&lt;p&gt;No, I don't &lt;em&gt;finally&lt;/em&gt; have the right programming language. Maybe I finally have the right team, but probably not.&lt;/p&gt;

&lt;p&gt;I think Joel is exactly right with his fundamental, cardinal rule of programming:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's harder to read code than to write it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I recently experienced this first-hand. In the codebase I'm currently working with, I encountered an error handling pattern that I didn't like; it seemed cumbersome and convoluted. &lt;/p&gt;

&lt;p&gt;My initial thought was to ignore this pattern, rewrite it, maybe even replace it with a better solution. That was until I found that the original author put together an entire talk about this error handling pattern. It turns out that, while it may be a little confusing, it gives incredible transparency when you need to debug with application logs.&lt;/p&gt;

&lt;p&gt;The real problem is that I hadn't taken the time to understand how the error pattern worked. I was confused, which led me to dismiss it, rather than to improve it.&lt;/p&gt;




&lt;p&gt;👋 Want to learn more about programming? &lt;a href="https://justindfuller.us4.list-manage.com/subscribe?u=d48d0debd8d0bce3b77572097&amp;amp;id=0c1e610cac" rel="noopener noreferrer"&gt;Subscribe to my newsletter&lt;/a&gt; to get an update, once-per-month, about what I'm writing about.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Refactor
&lt;/h2&gt;

&lt;p&gt;So, if rewrites are so bad, how can you avoid them?&lt;/p&gt;

&lt;p&gt;Here's a rule of thumb: If your reason for rewriting the code is that you don't understand it, you should not rewrite it. Instead, you should spend the time trying to understand the code. Once you understand it, refactor the code to make it easier for the next person to understand.&lt;/p&gt;

&lt;p&gt;Instead of rewriting the error handling pattern I will probably try to improve a few method names. This brings me back to Martin Fowler's &lt;a href="https://amzn.to/2R6rFkP" rel="noopener noreferrer"&gt;Refactoring&lt;/a&gt;. Most of the time, if you feel that a rewrite is needed, you can probably just refactor a few pieces of the program and you'll be in great shape. &lt;/p&gt;




&lt;blockquote&gt;
&lt;h2&gt;
  
  
  If your reason for rewriting the code is that you don't understand it, you should not rewrite it.
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sure, refactoring may have more pieces now than it did when he wrote it — moving an endpoint to another service may be a modern extension to moving a method to another class — but the base concepts are still the same.&lt;/p&gt;

&lt;p&gt;More importantly, the benefits are still the same. You will retain all the bug fixes, handled edge-cases, and sparsely-documented features that you don't even know about. They'll still be there when you're done refactoring.&lt;/p&gt;

&lt;p&gt;If you rewrite, you'll likely lose much of that. It's an idealistic view of ourselves to think that we understand any large codebase, probably rewritten by several or dozens of developers over months or years, well enough to cover all of these cases in a rewrite. Much of it will be lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hurdles to Refactoring
&lt;/h2&gt;

&lt;p&gt;I used to have a very abstract understanding of refactoring. My manager would ask if I was done with my current task and I would say, yes, but I need to refactor it before it's ready.&lt;/p&gt;

&lt;p&gt;What did I mean by that? In the beginning, I had some vague notion of making the code "prettier" or "easier to understand". They're not bad reasons; if I just wrote code that I can't understand now, I certainly won't be able to when I come back a few months later.&lt;/p&gt;

&lt;p&gt;The problem with this approach is that a vague understanding of refactoring comes with a vague understanding of the costs and benefits. Will the next developer agree that the code is easier to understand? &lt;/p&gt;

&lt;p&gt;Imagine that you were asked to clean up after a party. If you have never cleaned up before or if it was a big party, it could seem like a daunting task. How do you clean up? Should you remodel the bathroom or should you throw away all the cups and plates? Should you mow the yard, or make the living room usable again by putting all the chairs back at the table?&lt;/p&gt;

&lt;p&gt;Books like &lt;em&gt;Refactoring&lt;/em&gt; help by giving a clear picture of when and how to refactor. This greatly reduces the cost of refactoring because the possibilities are no longer limitless.&lt;/p&gt;

&lt;p&gt;For example, here are a few concrete refactoring reasons and solutions:&lt;/p&gt;

&lt;p&gt;Reason 1: The code is hard to understand. I don't know where to make my change.&lt;/p&gt;

&lt;p&gt;Solution 1: Read through the code; add tests where there are none; then, once you understand their true purpose and have added tests, improve variable or function names.&lt;/p&gt;

&lt;p&gt;Reason 2: Making this change will touch many parts of the codebase, otherwise known as &lt;a href="https://refactoring.guru/smells/shotgun-surgery" rel="noopener noreferrer"&gt;shotgun surgery&lt;/a&gt;, I'm worried something will break.&lt;/p&gt;

&lt;p&gt;Solution 2: Rearrange the codebase so that your change will only have to modify one or a few pieces of the code.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href="https://refactoring.guru/refactoring/smells" rel="noopener noreferrer"&gt;code smells&lt;/a&gt; and their specific solutions to greatly reduce the abstract-ness of refactoring. Refactoring can become a quick, concrete tool that you use to accomplish specific purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backward Refactoring
&lt;/h3&gt;

&lt;p&gt;I used to think refactoring was done after I finished coding. I finished my work, I made some concessions in the name of "&lt;a href="https://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast" rel="noopener noreferrer"&gt;Make it work, make it right, make it fast&lt;/a&gt;", now I need to clean up.&lt;/p&gt;

&lt;p&gt;However, refactoring can be a better tool &lt;a href="https://martinfowler.com/articles/preparatory-refactoring-example.html" rel="noopener noreferrer"&gt;before you begin making any changes&lt;/a&gt; as a way to make your change easier. As &lt;a href="https://twitter.com/kentbeck/status/250733358307500032?lang=en" rel="noopener noreferrer"&gt;Kent Beck said&lt;/a&gt; "Make the change easy (warning: this may be hard), then make the easy change."&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-250733358307500032-216" src="https://platform.twitter.com/embed/Tweet.html?id=250733358307500032"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-250733358307500032-216');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=250733358307500032&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Think about when you refactor after making your changes. What are you doing? You're &lt;em&gt;guessing&lt;/em&gt; what will be needed by the next person or the next change to the code. You're &lt;em&gt;guessing&lt;/em&gt; what will be misunderstood or unclear to the next developer. You might be right, but you also might be wasting everyone's time.&lt;/p&gt;

&lt;p&gt;When you refactor before making a change you have a clearer picture of what is misunderstood, what change needs to be done, and why it's difficult to accomplish.&lt;/p&gt;

&lt;p&gt;For this reason, I suggest another rule of thumb: Prefer refactoring &lt;em&gt;before&lt;/em&gt; you make a change, rather than after.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to rewrite
&lt;/h2&gt;

&lt;p&gt;As always, things aren't perfectly black-and-white. There are a few times when a rewrite might be necessary.&lt;/p&gt;

&lt;p&gt;The golden opportunity to rewrite less-than-stellar code is when the business wants to re-think how the product works. If the business is unhappy with the product and the developers are unhappy with the code, this may be the perfect opportunity to rewrite. Rewrite for better functionality, rather than better code. However, unless you're in a fast-moving startup, this opportunity may not come very often as most companies that I've worked with prefer incremental change.&lt;/p&gt;

&lt;p&gt;This is one reason that, as &lt;a href="https://amzn.to/36g7PaN" rel="noopener noreferrer"&gt;Sam Newnan writes in &lt;em&gt;Building Microservices&lt;/em&gt;&lt;/a&gt;, some people suggest to keep microservices small enough to rewrite in 2 weeks or less. There's no huge loss if a total overhaul is needed. You could rewrite it during a slow season.&lt;/p&gt;

&lt;p&gt;There's another opportunity, which (I hope) is even rarer than the last case. Sometimes a development team has written code that is so bad, so convoluted, that even they can't understand it enough to make a single change without creating a slew of bugs. If this is the case, a rewrite may be unavoidable.&lt;/p&gt;




&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Rewrite for better functionality, rather than better code.
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, let me caution you even in this case. If the composition of the team has not drastically changed; if there is not a clear definition of the cause and solution to the last iteration's problems; or there is not new leadership that provides clearer vision, principles, and guidance — you will likely repeat the same mistakes all over again. If the people haven't changed, the circumstances haven't changed, and the practices haven't changed, what will be different this time?&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Yes, all of this was just to say that you should prefer refactoring over rewriting. If you couldn't tell by all the times I linked to it, I highly recommend &lt;a href="https://amzn.to/2R6rFkP" rel="noopener noreferrer"&gt;Martin Fowler's Refactoring&lt;/a&gt; to learn more about the subject.&lt;/p&gt;

&lt;p&gt;Here are the key takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prefer refactoring over rewriting.&lt;/li&gt;
&lt;li&gt;If your reason for rewriting the code is that you don't understand it, you should not rewrite it.&lt;/li&gt;
&lt;li&gt;Prefer refactoring &lt;em&gt;before&lt;/em&gt; you make a change, rather than after.&lt;/li&gt;
&lt;li&gt;Rewrite for better functionality, rather than better code.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Hi, I’m Justin Fuller. I’m so glad you read my post! I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer. All code samples are my own.&lt;/p&gt;

&lt;p&gt;I’d also love to hear from you, please feel free to follow me on &lt;a href="https://github.com/justindfuller" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/justin_d_fuller" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://justindfuller.us4.list-manage.com/subscribe?u=d48d0debd8d0bce3b77572097&amp;amp;id=0c1e610cac" rel="noopener noreferrer"&gt;subscribe to my newsletter&lt;/a&gt; to get an update, once-per-month, about what I'm writing about. Thanks again for reading!&lt;/p&gt;




</description>
      <category>learning</category>
      <category>refactoring</category>
      <category>rewriting</category>
      <category>projects</category>
    </item>
    <item>
      <title>Go Things I Love: Channels and Goroutines</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Mon, 06 Jan 2020 13:19:00 +0000</pubDate>
      <link>https://dev.to/justindfuller/go-things-i-love-channels-and-goroutines-22c7</link>
      <guid>https://dev.to/justindfuller/go-things-i-love-channels-and-goroutines-22c7</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared at &lt;a href="https://www.justindfuller.com/2020/01/go-things-i-love-channels-and-goroutines?utm_source=Dev_to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=go_things_i_love"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This series, &lt;em&gt;Go Things I Love&lt;/em&gt;, is my attempt to show the parts of Go that I like the best, as well as why I love working with it at &lt;a href="https://open.nytimes.com"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In my last post &lt;a href="https://www.justindfuller.com/2019/12/go-things-i-love-methods-on-any-type/"&gt;Go Things I Love: Methods On Any Type&lt;/a&gt;, I demonstrated a feature of Go that makes it easy to build Object-Oriented software.&lt;/p&gt;

&lt;p&gt;This post, &lt;em&gt;Channels and Goroutines&lt;/em&gt;, will demonstrate a few neat concurrency patterns in Go.&lt;/p&gt;

&lt;p&gt;First: to get the most out of this post you should familiarize yourself with the fundamentals of Go concurrency. A great place to do that is &lt;a href="https://tour.golang.org/concurrency/1"&gt;in the Go tour&lt;/a&gt;. These patterns rely on goroutines and channels to accomplish their elegance.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Class
&lt;/h2&gt;

&lt;p&gt;Concurrency, in some form, is one of the most important building blocks of performant software. That's why it's important to pick a programming language with first-class concurrency support. Because Go, in my estimation, provides one of the most delightful ways to achieve concurrency, I believe it is a solid choice for any project that involves concurrency.&lt;/p&gt;

&lt;p&gt;To be first-class is to have full support and consideration in all things. That means, to be first-class, concurrency must be a part of the Go language itself. It cannot be a library bolted on the side.&lt;/p&gt;

&lt;p&gt;A few type declarations will begin to show how concurrency is built into the language.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;WriteOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ReadOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ReadAndWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;chan&lt;/code&gt; keyword in the function argument definitions. A &lt;code&gt;chan&lt;/code&gt; is a channel. &lt;/p&gt;

&lt;p&gt;Next comes the arrow &lt;code&gt;&amp;lt;-&lt;/code&gt; that shows which way the data flow to or from the channel. The &lt;code&gt;WriteOnly&lt;/code&gt; function receives a channel that can only be written to. The &lt;code&gt;ReadOnly&lt;/code&gt; function receives a channel that can only be read from. &lt;/p&gt;

&lt;p&gt;Being able to declare the flow of the data to a channel is an important way in which channels are first-class members of the Go programming language. Channel flow is important because it's how goroutines communicate. &lt;/p&gt;

&lt;p&gt;It's directly related to this phrase you might have seen before:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not communicate by sharing memory; instead, share memory by communicating.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The phrase, "share memory by communicating", means goroutines should communicate changes through channels; they provide a safer, idiomatic way to share memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communicating by sharing memory (👎)
&lt;/h2&gt;

&lt;p&gt;Here's an example of Go code that communicates by sharing memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;IntAppender&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ints&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;ints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;IntAppender&lt;/code&gt; creates a goroutine for each integer that is appended to the array. Even though it's a little too trivial to be realistic, it still serves an important demonstrative purpose. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;IntAppender&lt;/code&gt; each goroutine shares the same memory—the &lt;code&gt;ints&lt;/code&gt; array—which it appends integers to.&lt;/p&gt;

&lt;p&gt;This code communicates by sharing memory. Yes, it works—but it's not idiomatic Go. More importantly, it's not the safest way to write this program. &lt;/p&gt;

&lt;p&gt;It's not very safe because there are 11 goroutines (one running the main function and ten more spawned by the loop) with access to the &lt;code&gt;ints&lt;/code&gt; slice. What happens when the codebase grows? &lt;/p&gt;

&lt;p&gt;This pattern provides no guarantee that the program will behave as expected; anything can happen when memory is shared broadly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Share memory by communicating (👍)
&lt;/h2&gt;

&lt;p&gt;The first sign that this example is not following "share memory by communicating" is the use of &lt;code&gt;sync.WaitGroup&lt;/code&gt;. Even though I consider WaitGroups to be a code smell, I'm not ready to claim they are always bad. Either way, code is usually safer with a channel.&lt;/p&gt;

&lt;p&gt;Let's convert the bad example to idiomatic Go by replacing the &lt;code&gt;WaitGroup&lt;/code&gt; with a channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// WriteOnly serves the purpose of demonstrating&lt;/span&gt;
&lt;span class="c"&gt;// a method that writes to a write-only channel.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;WriteOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ints&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;WriteOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ints %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.golang.org/p/gi8zyZH7KMd"&gt;See this example in the Go playground.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, only one goroutine can modify the &lt;code&gt;ints&lt;/code&gt; slice while the rest communicate through a channel. They're sharing memory by communicating through a channel instead of modifying shared memory.&lt;/p&gt;

&lt;p&gt;The example here shows two important ways that concurrency (goroutines and channels) are first-class citizens of the Go programming language. First, we used a write-only channel argument. This guaranteed that the method won't accidentally read from the channel, unexpectedly altering the functionality. Second, we see that the &lt;code&gt;for range&lt;/code&gt; loop works on channels.&lt;/p&gt;

&lt;p&gt;These are just a few ways that Go makes concurrency a first-class citizen. Next, let's see what we can accomplish with goroutines and channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeout
&lt;/h2&gt;

&lt;p&gt;To demonstrate a timeout, we will construct a simple news UI backend that fetches results from three &lt;a href="https://developer.nytimes.com/"&gt;New York Times endpoints&lt;/a&gt;. Even though the NYT endpoints respond very quickly, this won't quite meet our standards. Our program must always respond within 80 milliseconds. Because of this restriction, we're only going to use NYT endpoint responses that come fast enough.&lt;/p&gt;

&lt;p&gt;Here are the URLs that the program will fetch from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"https://api.nytimes.com/svc/topstories/v2/home.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"https://api.nytimes.com/svc/mostpopular/v2/viewed/1.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"https://api.nytimes.com/svc/books/v3/lists/current/hardcover-fiction.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The URLs have been declared as an array of strings, which will allow them to be iterated. &lt;/p&gt;

&lt;p&gt;Another neat feature of Go is how you can declare &lt;code&gt;const&lt;/code&gt; blocks. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;urlTopStories&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://api.nytimes.com/svc/topstories/v2/home.json"&lt;/span&gt;
    &lt;span class="n"&gt;urlMostPopular&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://api.nytimes.com/svc/mostpopular/v2/viewed/1.json"&lt;/span&gt;
    &lt;span class="n"&gt;urlHardcoverFictionReviews&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://api.nytimes.com/svc/books/v3/lists/current/hardcover-fiction.json"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, the &lt;code&gt;urls&lt;/code&gt; array can be more expressive by using the const declarations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;urlTopStories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;urlMostPopular&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;urlHardcoverFictionReviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The URLs are for top stories, most popular stories, and the current hardcover fiction reviews. &lt;/p&gt;

&lt;p&gt;Instead of a real &lt;code&gt;http.Get&lt;/code&gt; I will substitute a fake &lt;code&gt;fetch&lt;/code&gt; function. This will provide a clearer demonstration of the timeout.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnixNano&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;150&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is a common pattern in Go demonstration code—generate a random number, sleep the goroutine for the randomly generated duration, then do some work. To fully understand why this code is being used to demonstrate a fake &lt;code&gt;http.Get&lt;/code&gt;, the next sections will step through each line, explaining what it does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deterministic Randomness (See: oxymorons)
&lt;/h3&gt;

&lt;p&gt;In Go, the random number generator is, by default, deterministic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In mathematics, computer science and physics, a deterministic system is a system in which no randomness is involved in the development of future states of the system. - &lt;a href="https://www.daviddarling.info/encyclopedia/D/deterministic_system.html"&gt;The Encyclopedia of Science&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that we have to seed the randomizer with something that changes; if not, the randomizer will always produce the same value. So we create a source, typically based on the current time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnixNano&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After the source is created, it can be used to create a random number generator. We must create the source and random generator each time. Otherwise, it will continue to return the same number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once the generator is created, it can be used to create a random number between 0 and 150. That random number is converted to a &lt;code&gt;time.Duration&lt;/code&gt; type, then multiplied to become milliseconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;150&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;One further note about the randomness is needed. It will always return the same value in the go playground because the go playground always starts running with the same timestamp. So, if you plug this into the playground, you'll always receive the same result. If you want to see the timeout in action, just replace 150 with some number below 80.&lt;/p&gt;

&lt;h3&gt;
  
  
  Another send-only channel
&lt;/h3&gt;

&lt;p&gt;At the very bottom of &lt;code&gt;fetch&lt;/code&gt; are the two lines that we care about.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first line tells the goroutine to sleep for the specified duration. This will make some responses take too long for the given URL, later causing the API to respond without the results of that URL.&lt;/p&gt;

&lt;p&gt;Finally, the URL is sent to the channel. In a real &lt;code&gt;fetch&lt;/code&gt; it would be expected that the actual response is sent to the channel. For our purposes, it's just the URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  A read-only channel
&lt;/h3&gt;

&lt;p&gt;Since the &lt;code&gt;fetch&lt;/code&gt; function funnels results in the channel, it makes sense to have a corresponding function funnel results from the channel into a slice of strings.&lt;/p&gt;

&lt;p&gt;Take a look at the function. Next, we'll break it down line-by-line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;stringSliceFromChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxLength&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;maxLength&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got all results"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Timeout!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First, look at the function argument declaration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;stringSliceFromChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxLength&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;stringSliceFromChannel&lt;/code&gt; function declares that it will accept a read-only channel, &lt;code&gt;channel &amp;lt;-chan string&lt;/code&gt;. This indicates that the function will convert the channel's inputs into a different type of output—a slice of strings, or &lt;code&gt;[]string&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Even though it's valid to declare a function argument with, &lt;code&gt;channel chan string&lt;/code&gt;, opting for the arrow &lt;code&gt;&amp;lt;-&lt;/code&gt; operator makes the function's intent clearer. This can be particularly helpful in a long function.&lt;/p&gt;

&lt;p&gt;Next, the timeout is created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function &lt;code&gt;time.After&lt;/code&gt; returns a channel. After the given &lt;code&gt;time.Duration&lt;/code&gt; it will write to the channel (&lt;em&gt;what&lt;/em&gt; it writes doesn't matter).&lt;/p&gt;

&lt;p&gt;Moving on, the &lt;code&gt;timeout&lt;/code&gt; and &lt;code&gt;input&lt;/code&gt; channels are used together in a &lt;code&gt;for select&lt;/code&gt; loop. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;for&lt;/code&gt; loop with no other arguments will loop forever until stopped by a &lt;code&gt;break&lt;/code&gt; or &lt;code&gt;return&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;select&lt;/code&gt; acts as a &lt;code&gt;switch&lt;/code&gt; statement for channels. The first &lt;code&gt;case&lt;/code&gt; block to have a channel ready will execute. &lt;/p&gt;

&lt;p&gt;By combining the &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;select&lt;/code&gt;, this block of code will run until the desired number of results is retrieved or until the timeout happens.&lt;/p&gt;

&lt;p&gt;Take a look at the case block for the &lt;code&gt;input&lt;/code&gt; channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;maxLength&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got all results"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The output of the channel is assigned to a variable, &lt;code&gt;str&lt;/code&gt;. Next, &lt;code&gt;str&lt;/code&gt; is appended to the results array. The results array is returned if it is the desired length.&lt;/p&gt;

&lt;p&gt;Now, look at the case block for the &lt;code&gt;timeout&lt;/code&gt; channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Timeout!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Whatever results are available, even if there are none, will be returned when the timeout happens.&lt;/p&gt;




&lt;p&gt;👋 Want to learn more about Go? &lt;a href="https://justindfuller.us4.list-manage.com/subscribe?u=d48d0debd8d0bce3b77572097&amp;amp;id=0c1e610cac"&gt;Subscribe to my newsletter&lt;/a&gt; to get an update, once-per-month, about what I'm writing about.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Main Function
&lt;/h2&gt;

&lt;p&gt;Now there is both a channel writer and a channel reader. Let's see how to put it all together in the &lt;code&gt;main&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;stringSliceFromChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Results: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First, a channel is created to collect the fetch results, &lt;code&gt;channel := make(chan string)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, the &lt;code&gt;urls&lt;/code&gt; are looped over, creating a goroutine to fetch each url.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This allows the fetching to happen concurrently.&lt;/p&gt;

&lt;p&gt;After the fetches have been kicked off, &lt;code&gt;stringSliceFromChannel&lt;/code&gt; will block until either the results are in or the timeout occurs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;stringSliceFromChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we can print the results to see which URLs are returned. If you run this code in the &lt;a href="https://play.golang.org/p/g3RnP9A26v5"&gt;Go Playground&lt;/a&gt;, remember to change the timeout number since the random number generator will always return the same results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Here's the cool thing. We started out talking about how Go has first-class concurrency support with goroutines and channels. Then we saw how easy it is to implement a complex concurrent pattern, a timeout, with a single channel and a few goroutines. Over my next few posts, I hope to show that this was only scratching the surface of what one can do with concurrency in Go. I hope you'll check back in. (Better yet, &lt;a href="https://justindfuller.us4.list-manage.com/subscribe?u=d48d0debd8d0bce3b77572097&amp;amp;id=0c1e610cac"&gt;subscribe to my newsletter&lt;/a&gt; to be updated each month about my new posts)&lt;/p&gt;

&lt;p&gt;Finally, even though this is a neat concurrency pattern, it's unrealistic. As an exercise you could open the &lt;a href="https://play.golang.org/p/g3RnP9A26v5"&gt;Go Playground&lt;/a&gt; to see if you can implement these scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The results should be returned as a JSON object. Maybe we could use a struct instead of an array of URLs?&lt;/li&gt;
&lt;li&gt;A blank page is useless, the code should at least wait until there is one result to display.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://golang.org/pkg/context/"&gt;context&lt;/a&gt; type is often used with http handlers. Can you replace the &lt;code&gt;time.After&lt;/code&gt; with an expiring context?&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Hi, I’m Justin Fuller. Thanks for reading my post. Before you go, I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer. All code samples are my own.&lt;/p&gt;

&lt;p&gt;I’d also love to hear from you, please feel free to follow me on &lt;a href="https://github.com/justindfuller"&gt;Github&lt;/a&gt; &lt;br&gt;
or &lt;a href="https://twitter.com/justin_d_fuller"&gt;Twitter&lt;/a&gt;. Thanks again for reading!&lt;/p&gt;

</description>
      <category>go</category>
      <category>oop</category>
      <category>objectorientedprogramming</category>
      <category>development</category>
    </item>
    <item>
      <title>Go Things I Love: Methods On Any Type</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Sat, 14 Dec 2019 20:41:59 +0000</pubDate>
      <link>https://dev.to/justindfuller/go-things-i-love-methods-on-any-type-2md2</link>
      <guid>https://dev.to/justindfuller/go-things-i-love-methods-on-any-type-2md2</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://justindfuller.com/posts/2019-12-14_Go-Things-I-Love-Methods-On-Any-Type?utm_source=Dev.To&amp;amp;utm_medium=referral&amp;amp;utm_campaign=go_things_i_love"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that I am working with &lt;a href="https://golang.org/"&gt;Go&lt;/a&gt; as my primary language at &lt;a href="https://open.nytimes.com/"&gt;The New York Times&lt;/a&gt;, I want to explore some of my favorite features of the language. I don't intend this to reveal previously unknown features or best practices; I just want to share some of the reasons that I enjoy working with the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods
&lt;/h2&gt;

&lt;p&gt;Typically a method is defined as a function that belongs to an object or class. This means you wouldn't necessarily add a method to a string, boolean, or number.&lt;/p&gt;

&lt;p&gt;This limitation might lead a developer to produce code that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;LastOldSchoolID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;23959&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;LastOldSchoolID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// allow access to the old school version of the game&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// and elsewhere&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;LastOldSchoolID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// allow access to the old school version of the forum&lt;/span&gt;
  &lt;span class="c"&gt;// or some other custom logic for old school players&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this silly example, there is a game that recently released a new version. Players who made an account before the release are still allowed to play the old game and use the old forum. To do this, the developers went around the codebase and added a check: Is the user's ID lower than the last old school player's ID? If so, they can access the old game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encapsulation
&lt;/h2&gt;

&lt;p&gt;Unfortunately, and right away, the community notices a bug. Specifically, a single user notices this bug. The last old school player is locked out of the game! The developers used the check &lt;code&gt;id &amp;lt; LastOldSchoolID&lt;/code&gt; everywhere. So it works for all but the very last player.&lt;/p&gt;

&lt;p&gt;At this point, the developers are forced to search for every instance of this check (fortunately there aren't that many, only a dozen or so) and they replace the logic with &lt;code&gt;id &amp;lt;= LastOldSchoolID&lt;/code&gt;. Everything is working perfectly again.&lt;/p&gt;

&lt;p&gt;Except it's not. The developer who coded logic for the old school login page included this snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;LastOldSchoolId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;httperrors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"We're sorry but you don't have access to the old school game."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So, unfortunately, the bug still exists.&lt;/p&gt;

&lt;p&gt;This could have all been prevented by a little encapsulation. The developers shouldn't have repeated the logic—all over the codebase—to determine if an ID is valid for old school. The logic should live in only one place. &lt;/p&gt;

&lt;p&gt;Thankfully, Go provides exactly what is needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a custom type
&lt;/h2&gt;

&lt;p&gt;The User's ID will be implemented as a custom type. The type can be used independently or as part of a user struct. Most importantly, it can have custom methods.&lt;/p&gt;

&lt;p&gt;Here's how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;LastOldSchoolID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;23959&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;UserID&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;UserID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;IsOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;LastOldSchoolID&lt;/span&gt; &lt;span class="c"&gt;// The last oldschool player&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;UserID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;IsNotOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice the custom methods added directly to the &lt;code&gt;UserID&lt;/code&gt; type, which is an &lt;code&gt;int&lt;/code&gt;. The code around the app can now be rewritten.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// allow access to the old school version of the game&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// elsewhere&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNotOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;httperrors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Please join us playing the new version at game.com/v2."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If only this had been done in the first place, a lot of pain and suffering would have been saved for that poor user who wasn't able to access the game for a few days. The developers could have made the fix at a single location in the code and the fix would have been applied everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  More encapsulation, delegation.
&lt;/h2&gt;

&lt;p&gt;Some might point out that the code is still revealing too many details about the user and the old school logic. &lt;/p&gt;

&lt;p&gt;Why should the rest of the code need to know that old school access is determined by the ID? What if the business decides to change the rules to instead use the creation date? What if the developers decide to make an &lt;code&gt;IsOldSchool&lt;/code&gt; property on the user? &lt;/p&gt;

&lt;p&gt;These are all valid points. First, I ask you to remember that this is simply an example to show a great feature within &lt;code&gt;Go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, I'd like to point out two things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding methods to a non-struct type (like an int or string) &lt;em&gt;might&lt;/em&gt; be a code smell that you are unnecessarily leaking implementation details or other logic that should be private.&lt;/li&gt;
&lt;li&gt;If the details need to be hidden, methods can still be added to the custom type, while at the same time hiding where that logic comes from.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Allow me to demonstrate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;UserID&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;IsOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;IsNotOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNotOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Delegation is used inside the &lt;code&gt;User&lt;/code&gt; struct. The details of how the ID calculates old school is even hidden to &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now the implementation details (that old school access is based on the ID) can be hidden from the rest of the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// allow access to the old school version of the game&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// elsewhere&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNotOldSchool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;httperrors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Please join us playing the new version at game.com/v2."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Again, internally, the User struct will take advantage of the methods on the ID, further encapsulating the logic.&lt;/p&gt;

&lt;p&gt;You can play around with these examples on the &lt;a href="https://play.golang.org/p/2WlOg1byot1"&gt;Go Playground&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Hi, I’m Justin Fuller. I’m so glad you read my post! I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer. All code samples are my own.&lt;/p&gt;

&lt;p&gt;I’d also love to hear from you, please feel free to follow me on &lt;a href="https://github.com/justindfuller"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/justin_d_fuller"&gt;Twitter&lt;/a&gt;. Thanks again for reading!&lt;/p&gt;

</description>
      <category>go</category>
      <category>oop</category>
      <category>objectorientedprogramming</category>
      <category>development</category>
    </item>
    <item>
      <title>Keep a git repository of all your practice code</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Sun, 13 Oct 2019 18:59:22 +0000</pubDate>
      <link>https://dev.to/justindfuller/keep-a-git-repository-of-all-your-practice-code-2gi1</link>
      <guid>https://dev.to/justindfuller/keep-a-git-repository-of-all-your-practice-code-2gi1</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://justindfuller.com/posts/2019-10-13_Person-Knowledge-Repo?utm_source=Dev.To&amp;amp;utm_medium=referral&amp;amp;utm_campaign=learning_javascript" rel="noopener noreferrer"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Are you struggling to find projects to showcase to potential employers? Have you been practicing &lt;a href="https://leetcode.com/" rel="noopener noreferrer"&gt;LeetCode&lt;/a&gt; as you prepare to interview for a Software Development job? Do you occasionally practice a Kata on &lt;a href="//www.codewars.com"&gt;Codewars&lt;/a&gt; to keep your skills from getting rusty?&lt;/p&gt;

&lt;p&gt;If you answered yes to any of these questions, you should consider saving every practice problem you do in a public git repo, like &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I try to keep up with programming trends, and one question that I see come up a lot, &lt;a href="https://www.reddit.com/r/learnprogramming/" rel="noopener noreferrer"&gt;particularly&lt;/a&gt; on &lt;a href="https://www.reddit.com/r/cscareerquestions/" rel="noopener noreferrer"&gt;reddit&lt;/a&gt;, is "What project should I do?"&lt;/p&gt;

&lt;p&gt;Projects are a great way to learn, but most people don't have time to work on big projects in their free time. Another option is to work on algorithmic problems. You've got an almost 100% chance of running into at least one algorithm question if you are interviewing, plus they are a good way to learn a new programming language.&lt;/p&gt;

&lt;p&gt;If you have been a developer for years, practicing algorithm problems is a great way to keep your skills sharp—particularly on a groggy Monday morning when you are having trouble getting started, or on a Friday afternoon when you are feeling unmotivated. A quick practice problem can get your brain moving.&lt;/p&gt;

&lt;h2&gt;
  
  
  My knowledge repo
&lt;/h2&gt;

&lt;p&gt;I recently started learning C++. To keep track of what I am learning I created a &lt;a href="https://github.com/JustinDFuller/problems" rel="noopener noreferrer"&gt;practice problem repo of my own&lt;/a&gt; that I hope to see grow over time.&lt;/p&gt;

&lt;p&gt;What do I plan to do with it?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Code review myself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From time to time I will come back to the code and review it. I'll ask myself, "based on what I have learned, is this still the best way to implement this?" If the answer is no, I will create a new one and document what I misunderstood when I originally wrote the code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use it as a knowledge repository.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I may have a similar problem pop up in a real application in the future. Now I have a knowledge repo that demonstrates how I solved it the first time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Your knowledge repo
&lt;/h2&gt;

&lt;p&gt;What can you use it for?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learning a new programming language.

&lt;ul&gt;
&lt;li&gt;Practice each new concept you learn and save it for review later; make sure you don't just copy and paste examples, though!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Tracking your improvement over time.

&lt;ul&gt;
&lt;li&gt;Occasionally review your old code. What have you learned since you wrote it?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A personal knowledge repository.

&lt;ul&gt;
&lt;li&gt;When you get a tough problem at work, maybe you've done something similar before—now you have a way to remember.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A showcase for potential employers.

&lt;ul&gt;
&lt;li&gt;New college graduate or long-time developer, there's no better way to show your skill than to have a potential employer see your code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Hi, I’m Justin Fuller. I’m so glad you read my post! I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer. All code samples are my own.&lt;/p&gt;

&lt;p&gt;I’d also love to hear from you, please feel free to follow me on &lt;a href="https://github.com/justindfuller" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/justin_d_fuller" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;. Thanks again for reading!&lt;/p&gt;

</description>
      <category>learning</category>
      <category>projects</category>
      <category>showcase</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Simply JavaScript: a straightforward intro to Mocking, Stubbing, and Interfaces</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Wed, 04 Sep 2019 01:13:29 +0000</pubDate>
      <link>https://dev.to/justindfuller/simply-javascript-a-straightforward-intro-to-mocking-stubbing-and-interfaces-12bg</link>
      <guid>https://dev.to/justindfuller/simply-javascript-a-straightforward-intro-to-mocking-stubbing-and-interfaces-12bg</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://justindfuller.com/posts/2018-10-17_simply-javascript-a-straightforward-intro-to-mocking-stubbing-and-interfaces?utm_source=Dev.To&amp;amp;utm_medium=referral&amp;amp;utm_campaign=learning_javascript" rel="noopener noreferrer"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I like to think that I’m a simple guy, I like simple things. So whenever I sense complexity, my first reaction is to wonder if I can make things easier.&lt;/p&gt;

&lt;p&gt;Before I transitioned to software development, I spent time as a sound engineer. I was recording bands and mixing live shows. I was even recording and mixing live shows for broadcast. During that time I talked with too many people who would always attempt to solve problems by purchasing some expensive, more complex equipment. Sadly the return on investment never seemed to be all it promised.&lt;/p&gt;

&lt;p&gt;Instead of buying into the “more expensive, more complex is better” philosophy, I spent every evening learning the basics. I focused on fundamental skills. I learned how to use an equalizer to make a voice sound natural. I learned how to use a compressor to soften quick and loud sounds or to beef up thin sounds. It turned out that the return on investment for those hours was more than I ever hoped for!&lt;/p&gt;

&lt;p&gt;I ended up favoring the simplest tools and I was very happy with the work I produced.&lt;/p&gt;

&lt;p&gt;I believe the same principle can be applied to almost every aspect of life—finances, parenting, even software engineering.&lt;/p&gt;

&lt;p&gt;As people, we naturally tend to look for flashy, popular solutions that promise to solve all of our problems (or at least to perfectly solve a single problem). We are misguided about these complex solutions. We’ve created complicated problems by not properly understanding the fundamentals of whatever we’re struggling with.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Basics
&lt;/h2&gt;

&lt;p&gt;We’ll be looking at basic programming concepts and how they can be applied to JavaScript. The goal here is to have code that is simpler, more flexible, easier to understand, and easier to test.&lt;/p&gt;

&lt;p&gt;First, before introducing interfaces, I’d like to talk about a problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mocking, stubbing, and mutating
&lt;/h3&gt;

&lt;p&gt;Recently I was writing code that read files from the file system. The code worked great. To test it, I had to use a library that would stop my code from reading from the file system. My tests would have been too slow if I had let it do that. Plus I needed to simulate scenarios that would have been complicated to implement with the actual file system.&lt;/p&gt;

&lt;p&gt;Historically I would have used a library like &lt;a href="https://www.npmjs.com/package/proxyquire" rel="noopener noreferrer"&gt;Proxyquire&lt;/a&gt; or &lt;a href="https://www.npmjs.com/package/sinon" rel="noopener noreferrer"&gt;Sinon&lt;/a&gt;. Proxyquire allows you to override the imports of a file. Sinon allows you to mutate methods on an object. You can use either or both of these to make your code easier to test. Although it would be better to use just one.&lt;/p&gt;

&lt;p&gt;As an example, let’s pretend you have a module called “a”. Let’s also say that module “a” imports module “b”. Proxyquire works by importing module “a” and overwriting the exports of module “b”. It won’t affect other imports of module “b” elsewhere. Sinon works by mutating the exports of module “b”. It will affect every place that imports module “b”, so you must remember to restore it when you are done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* This is my file I'll be testing foo.js */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;readFileAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readJsonFile&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;readFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* This is my test file foo.test.js */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ava&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stub&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sinon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;proxyquire&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;proxyquire&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readJsonFile with proxyquire&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="cm"&gt;/* fs.readFile is overwritten for this import of foo.js */&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readJsonFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;proxyquire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./foo.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myTestFile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{ success: true }&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;readJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myTestFile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readJsonFile with sinon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="cm"&gt;/* fs.readFile is overwritten everywhere */&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fsStub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readFile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myTestFile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callsArg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{ success: true }&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;readJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myTestFile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="c1"&gt;// Won't happen if test fails :(&lt;/span&gt;
  &lt;span class="nx"&gt;fsStub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;restore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why are stubs bad?
&lt;/h3&gt;

&lt;p&gt;Neither of these options is great because they involve mutation. In software development, we want to avoid mutation when possible. because mutation leads to a decrease in predictability across an application.&lt;/p&gt;

&lt;p&gt;One small mutation never seems like a big deal. But when there are many small mutations it becomes difficult to track which function is changing what value and when each mutation is being done.&lt;/p&gt;

&lt;p&gt;There’s also the nuisance of lock-in. Both sinon and proxyquire will require you to update your tests if you change your file system library from fs to fs-extra-promise. In both cases, you’ll still be using the function readFileAsync. However, sinon and proxyquire will keep on trying to override fs.readFile.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the alternatives?
&lt;/h2&gt;

&lt;p&gt;To solve this problem I followed a principle called &lt;a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle" rel="noopener noreferrer"&gt;Dependency Inversion&lt;/a&gt;. Instead of my module creating its dependencies, it will expect to be given its dependencies. This produces modules that are both easier to test and more flexible. They can also be made to work with many implementations of the same dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* This is my file I'll be testing foo.js */&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;readFileAsync&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;readJsonFile &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;readFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* This is my test file foo.test.js */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ava&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo with dependency inversion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;readFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{ success: true &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;readJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only have precious lines been saved in our code, but there is also no more worrisome mutation happening! The module will now accept readFileAsync rather than creating that function itself. The module is better because it’s more focused and has fewer responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where does the dependency go?
&lt;/h3&gt;

&lt;p&gt;The dependencies have to be imported somewhere. In an application that follows dependency inversion, you should move the dependencies as far “out” as you can. Preferably you’d import them one time at the entry point of the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* json.js */&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;readFileAsync&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;writeFileAsync&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;readJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;readFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nf"&gt;writeJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;writeFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* content.js */&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;readJsonFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;writeJsonFile&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// business logic goes here.&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;readJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="nf"&gt;writeContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// business logic goes here&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;writeJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
     &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* index.js where the app starts */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs-extra-promise&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;jsonInterface&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;contentInterface&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;jsonInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;contentInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// content can be used by an http server&lt;/span&gt;
&lt;span class="c1"&gt;// or just exported if this is a library&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example, you saw that the dependencies were moved to the entry point of the application. Everything except index.js accepted an interface. This causes the application to be flexible, easy to change, and easy to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  What else can Dependency Inversion do?
&lt;/h2&gt;

&lt;p&gt;Now that you’ve fallen in love with dependency inversion I’d like to introduce you to some more of its power.&lt;/p&gt;

&lt;p&gt;When your module accepts an interface, you can use that module with multiple implementations of that interface. This is a scenario where the libraries &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; and &lt;a href="https://flow.org/" rel="noopener noreferrer"&gt;Flow&lt;/a&gt; can be useful. They’ll check that you’ve provided the correct interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An interface is simply a collection of methods and properties&lt;/strong&gt;. So by saying that a module accepts an interface, I am saying that a module accepts an object that implements a set of methods and properties. The expectation is that the interfaces similarly implement different functionality.&lt;/p&gt;

&lt;p&gt;A common interface you might know is the React component interface. In TypeScript it might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComponentLifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;?():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;shouldComponentUpdate&lt;/span&gt;&lt;span class="p"&gt;?(&lt;/span&gt;&lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;componentWillUnmount&lt;/span&gt;&lt;span class="p"&gt;?():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;componentDidCatch&lt;/span&gt;&lt;span class="p"&gt;?(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ErrorInfo&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
      &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please don’t despair if you didn’t understand everything in that interface. The point is that a React Component has a predictable set of methods and properties that can be used to make many different components.&lt;/p&gt;

&lt;p&gt;We are now beginning to venture into the territory of the &lt;a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle" rel="noopener noreferrer"&gt;Open-Closed Principle&lt;/a&gt;. It states that our software should be open for extension but closed for modification. This may sound very familiar to you if you’ve been building software with frameworks like &lt;a href="https://angularjs.org/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;, or &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;. They provide a common interface that you extend to build your software.&lt;/p&gt;

&lt;p&gt;Now, instead of relying on third-party interfaces for everything, you can begin to rely on your internal interfaces to create your software.&lt;/p&gt;

&lt;p&gt;If you are writing a CRUD (create, read, update, delete) application, you can create an interface that provides the building blocks for your actions. Your modules can extend that interface to implement the business logic and use-cases.&lt;/p&gt;

&lt;p&gt;If you are writing an application that performs tasks, you can build a task interface that provides the building blocks for different tasks. Each task can accept that task interface and extend it.&lt;/p&gt;

&lt;p&gt;Dependency inversion and the Open-Closed principle allow you to write more reusable, testable, and predictable software. You’ll no longer have a jumbled mess of spaghetti code. Instead, you’ll have a uniform group of modules that follow the same pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Many Implementations
&lt;/h3&gt;

&lt;p&gt;There’s one more benefit to accepting an interface. You can implement that interface in many different ways.&lt;/p&gt;

&lt;p&gt;Here’s my favorite example of this. Imagine that you have an interface for a CRUD application. You could have one interface that implements the database storage. This is great, but what if the database reads or writes become slow? You could also write a faster implementation that uses &lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt; or &lt;a href="https://www.memcached.org/" rel="noopener noreferrer"&gt;Memcached&lt;/a&gt; to speed up the response times. The only change you’ll have to make is writing a new interface. There will be no need to update business logic or anything else.&lt;/p&gt;

&lt;p&gt;You could consider React and &lt;a href="https://facebook.github.io/react-native/" rel="noopener noreferrer"&gt;React-Native&lt;/a&gt; to be popular examples of this. They both use the same React component and React DOM interfaces, but they implement them differently. Even inside React Native, there is an implementation for both IOS and Android. Multiple implementations allow you to write your logic once and execute it in multiple ways.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now what?
&lt;/h2&gt;

&lt;p&gt;Now that you’ve learned about dependency inversion and the open-closed principle, it’s time for you to go and apply it in your code. Don’t write any imports in the next module you write. Instead, allow it to accept an interface. In your tests, you’ll be able to avoid third-party libraries that mutate your dependencies! Then try to start identifying where common interfaces can be used. You’ll slowly but surely create a better application!&lt;/p&gt;




&lt;p&gt;This is a repost, the post originally appeared on &lt;a href="https://justindfuller.com/posts/2018-10-17_simply-javascript-a-straightforward-intro-to-mocking-stubbing-and-interfaces" rel="noopener noreferrer"&gt;www.justindfuller.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Hi, I’m Justin Fuller. I’m so glad you read my post! I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer in &lt;em&gt;any&lt;/em&gt; way. All code samples are my own and are completely unrelated to my employer's code.&lt;/p&gt;

&lt;p&gt;I’d also love to hear from you, please feel free to connect with me on &lt;a href="https://github.com/justindfuller" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/justin_d_fuller" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;. Thanks again for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>oop</category>
      <category>errors</category>
    </item>
    <item>
      <title>How To Write Error Messages That Don’t Suck</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Mon, 02 Sep 2019 01:11:01 +0000</pubDate>
      <link>https://dev.to/justindfuller/how-to-write-error-messages-that-don-t-suck-544f</link>
      <guid>https://dev.to/justindfuller/how-to-write-error-messages-that-don-t-suck-544f</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://justindfuller.com/posts/2018-11-28_how-to-write-error-messages-that-dont-suck?utm_source=Dev.To&amp;amp;utm_medium=referral&amp;amp;utm_campaign=learning_javascript" rel="noopener noreferrer"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;“A validation error occurred.” Yep. Thanks!&lt;/p&gt;

&lt;p&gt;The release is imminent; this is the last update that needs to be verified, and I get an error message that’s as useful as the close button on an elevator.&lt;/p&gt;

&lt;p&gt;It turns out that it &lt;em&gt;is&lt;/em&gt; a validation error, kind of. The input I am giving is a duplicate. It’s valid, it just already exists!&lt;/p&gt;

&lt;p&gt;Wouldn’t it be so helpful to know that?&lt;/p&gt;

&lt;p&gt;It would be helpful to be informed of several things when errors happen. I don’t need to know everything. The history of programming won’t help me here. The message should give me just enough info for me to get this error fixed so that I can finish my work, go home, and play with my kids.&lt;/p&gt;

&lt;h3&gt;
  
  
  What makes an Error?
&lt;/h3&gt;

&lt;p&gt;In JavaScript, an error object always has the name, message, and stack properties. The name gives you an at-a-glance classification of the error. The stack tells you where it happened. The message? Well, according to some developers, you don’t need to worry about that! “The stack trace gives you everything you need.”&lt;/p&gt;

&lt;p&gt;Please, don’t be one of those developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful Error Messages
&lt;/h3&gt;

&lt;p&gt;Raise your right hand, place your left hand on a copy of “Clean Code” and repeat after me.&lt;/p&gt;

&lt;p&gt;“I swear to include enough detail in my error messages that future developers will easily be able to determine what went wrong and what they need to do to fix it.”&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happened
&lt;/h3&gt;

&lt;p&gt;When a police officer pulls you over to give you a ticket, does it say “Bad Driving”? No! It says you were going 65 miles per hour in a school zone, you passed a stopped bus, and your car hasn’t been inspected in four years! Sure, you’re going to jail, but at least you know &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So the error message from earlier should not be, “A validation error occurred”, but instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unable to save model "user" because the property "email" with value "JustinFuller@company.com" already exists.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of a simple error that says, “Invalid option” use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The option "update" is not valid. Valid options include "upsert", "get", and "delete".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These updated error messages attempt to help us understand the cause, giving us a start toward the solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Might Have Happened
&lt;/h3&gt;

&lt;p&gt;Now that the error is describing what exactly went wrong, it’s time to help the poor soul who stumbled into this predicament begin to climb back out. Watch carefully. When done correctly it will seem like you’re reaching forward through time by anticipating what could have led to this unfortunate turn of events. You’ll be right there with that future developer — maybe yourself — telling them that everything is fine, that you’ll get through this together.&lt;/p&gt;

&lt;p&gt;You’ll begin by explaining what happened.&lt;/p&gt;

&lt;p&gt;For anything that has a prerequisite step, such as configuration or validation, you can suggest verifying that step has been completed. Don’t worry if your error messages get long. It’s better to provide too much information than not enough.&lt;/p&gt;

&lt;p&gt;I’ll add more detail to one of the earlier examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The option “update” is not valid. Valid options include “upsert”, “get”, and “delete”. **If you expected “update” to be an option, you must first export it from the file: "./src/controllers/index.js".**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you are anticipating how this might have happened: the developer probably just forgot to export the new option. The error becomes a reminder of that step. You’ve now shown two possible causes of the error; the first is a possible typo (here are the valid options) and the second is a configuration error (here’s where it should be exported).&lt;/p&gt;

&lt;p&gt;The React library does an excellent job of anticipating how errors might have occurred. They don’t address every edge case, but they do give helpful hints for the most common errors. For example, you can’t use the function reactDom.renderToNodeString() in the browser because node streams don’t exist there. So React gives you a suggestion of how it happened and how to fix it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReactDOMServer.renderToNodeStream(): The streaming API is not available in the browser. Use ReactDOMServer.renderToString() instead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There could be other ways for that error to occur, but they guess that the most common reason is that renderToNodeStream was called in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relevant Data
&lt;/h3&gt;

&lt;p&gt;While writing error messages you must remember that applications rarely do only one thing at a time. So when errors occur it’s a challenge to find the state of the application at that time. For this reason, it’s very important to capture the relevant data and relay it back to the developer so that they can pinpoint the cause.&lt;/p&gt;

&lt;p&gt;In the first example, I included the phrase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The property “email” with value “JustinFuller@company.com” already exists.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very useful but could be impractical. It may take too much effort or time to create natural language errors for every variation of data, or in some cases, we may simply be passing on a failure outside of our control, so the only option left is to give a good description and include as much relevant data that is safe to print.&lt;/p&gt;

&lt;p&gt;The choice of what data is safe to print is tricky: if you choose exactly what properties to include then you end up modifying the list every time there is a new property, or, worse, you forget and it doesn’t show up when needed; on the other hand you can remove properties that are known to be unsafe, but here you risk adding a new property and forgetting to exclude it, causing leaked sensitive data. You have to use your judgment and consider your company rules. Does your software handle highly valuable or personal data that should not be written to a non-encrypted destination? Thoughtlessly logging out every object that causes an error is liable to get you fired from some jobs, while at others it’s the standard operating procedure. So please, use common sense and be careful!&lt;/p&gt;

&lt;h3&gt;
  
  
  Unexpected Errors
&lt;/h3&gt;

&lt;p&gt;There are two ways to include relevant data when you don’t know exactly which property or action caused the error.&lt;/p&gt;

&lt;p&gt;The first should be used when you intend for the error to be read by humans, you put the data right in the message: &lt;code&gt;An error was received: “Duplicate entry found for user.email”, while upserting user: { “email”: “justinfuller@company.com” }&lt;/code&gt;. This error style has its drawbacks, like the entire object being placed into the error message that could be sent somewhere unintended. If, however, you know it’s safe then this style has the advantage of giving complete details about the situation.&lt;/p&gt;

&lt;p&gt;In other cases, you may not want the data to leak to a log file or an API response. You can provide a reference ID, a timestamp that can be manually or automatically referenced to data later, or some other property that will allow the developer to track down the pesky data-point that caused an error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expected Errors
&lt;/h3&gt;

&lt;p&gt;I’ll be the first to admit that I’m prone to making simple mistakes. I type “upswert” instead of “upsert”; I type “npm tes” instead of “npm test”. So it’s refreshing when I get an error message saying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Received an unknown command, "npm tes". Did you mean "npm test"?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the developers prepped for this, they must have gazed into the future and saw that someone would make that typo — or maybe they just know that humans are prone to silly errors.&lt;/p&gt;

&lt;p&gt;Whenever there’s a step in a process that can go predictably wrong you have an opportunity to prepare clear guidance on what went wrong and how to fix it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps To Fix The Issue
&lt;/h3&gt;

&lt;p&gt;For some errors, it will be possible to give a solution to the error instead of just reporting that it happened. Some times it will be easy, like earlier when we showed the correct options after accidentally typing “update” instead of “upsert”. Other times you’ll need to put in more effort to give the user enough information to correct their mistake, like if you’ve detected a recursive dependency, and you need to tell them where the loop is and what they must do to remove it.&lt;/p&gt;

&lt;h3&gt;
  
  
  An error that doesn’t suck
&lt;/h3&gt;

&lt;p&gt;So, do you want to provide helpful error messages? Next time you write an error, try to include a full description of what happened, how it might have happened, any relevant data that is safe to include, and any steps that might help resolve the problem.&lt;/p&gt;




&lt;p&gt;This is a repost, the post originally appeared on &lt;a href="https://justindfuller.com/posts/2018-11-28_how-to-write-error-messages-that-dont-suck" rel="noopener noreferrer"&gt;www.justindfuller.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Hi, I’m Justin Fuller. I’m so glad you read my post! I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer in &lt;em&gt;any&lt;/em&gt; way. All code samples are my own and are completely unrelated to my employer's code.&lt;/p&gt;

&lt;p&gt;I’d also love to hear from you, please feel free to connect with me on &lt;a href="https://github.com/justindfuller" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/justin_d_fuller" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;. Thanks again for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>errors</category>
    </item>
    <item>
      <title>Refactoring — oops, I’ve been doing it wrong.</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Sun, 01 Sep 2019 19:07:54 +0000</pubDate>
      <link>https://dev.to/justindfuller/refactoring-oops-i-ve-been-doing-it-wrong-33ge</link>
      <guid>https://dev.to/justindfuller/refactoring-oops-i-ve-been-doing-it-wrong-33ge</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://justindfuller.com/posts/2019-01-24_refactoring-oops-ive-been-doing-it-backwards?utm_source=Dev.To&amp;amp;utm_medium=referral&amp;amp;utm_campaign=learning_javascript" rel="noopener noreferrer"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Welcome to my intervention. I’m a refactoring addict and I’m not afraid to admit it, but there’s only one problem: I’ve been doing it backward. You see, what I’ve been doing could be more accurately described as premature code abstraction.&lt;/p&gt;

&lt;p&gt;We all know about refactoring. If you’ve read even a single programming book, or if you spend much time reading code blogs, you’ll have heard all about it. It’s an important concept that keeps code understandable, maintainable, and extensible.&lt;/p&gt;

&lt;p&gt;At least that’s what everyone tells me.&lt;/p&gt;

&lt;p&gt;So why has refactoring not been accomplishing what I was hoping?&lt;/p&gt;

&lt;p&gt;As I wrote my most recent library, I took some time to reflect on the evolution of my code. I realized that before I had a fully working product and before I had an ideal output in my unit tests, I had refactored my code into interfaces that I wasn’t even sure I would need. I had moved code around, made it extensible, made it reusable, but why? Was that code going to give me the final output I needed? I didn’t know yet.&lt;/p&gt;

&lt;p&gt;Everything worked out in the end, but was my code more complicated than it needed to be? I believe so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principles Over Purpose
&lt;/h2&gt;

&lt;p&gt;Have you heard of &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; principles? I try to follow them closely. Every function that I write aims to have &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="noopener noreferrer"&gt;a single responsibility&lt;/a&gt;. My classes and factories aim to be &lt;a href="https://en.wikipedia.org/wiki/Open/closed_principle" rel="noopener noreferrer"&gt;open for extension while discouraging modification&lt;/a&gt;. I also try not to depend directly on too many things, so instead, &lt;a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle" rel="noopener noreferrer"&gt;I accept dependencies as arguments&lt;/a&gt; in functions and classes.&lt;/p&gt;

&lt;p&gt;Does that like a recipe for good code? I think it does. The problem occurs when my code focuses on being SOLID, or &lt;a href="https://en.wikipedia.org/wiki/Pure_function" rel="noopener noreferrer"&gt;pure&lt;/a&gt;, rather than on accomplishing what it was born to do. The problem occurs when I put principles over purpose.&lt;/p&gt;

&lt;p&gt;For example, I’ve been so focused on making sure my &lt;a href="https://medium.freecodecamp.org/how-writing-tests-can-make-you-a-faster-and-more-productive-developer-f3ad978e3872" rel="noopener noreferrer"&gt;unit tests have no expensive IO&lt;/a&gt; (input and output). I’ve occasionally had to go back and fix code that was wrong due to my incorrectly mocked dependencies.&lt;/p&gt;

&lt;p&gt;So, what’s the solution?&lt;/p&gt;

&lt;p&gt;Remember that reflection I mentioned earlier? It reminded me of the mantra, “&lt;a href="http://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast" rel="noopener noreferrer"&gt;Make it work, make it right, make it fast.&lt;/a&gt;” I’ve realized I’ve been going out of order. I’ve been making it right, making it fast, then making it work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Make It Work
&lt;/h2&gt;

&lt;p&gt;As I’ve begun to write more it has become clear that good writing doesn’t just happen. First I have to get all my thoughts down on the page. I have to see where my thoughts take me. Then I must shape them into some sort of semi-coherent and non-rambling version of what just spilled out.&lt;/p&gt;

&lt;p&gt;The same thing can happen with code.&lt;/p&gt;

&lt;p&gt;Get it all out there into that function. At first don’t worry &lt;em&gt;too&lt;/em&gt; much about naming, single responsibility, or being extensible — you’ll address that once your function is working. To be clear, you won’t be writing your whole application like this, just one small piece.&lt;/p&gt;

&lt;p&gt;Once you’ve got the output you are looking for (you’ve got unit tests to prove that the code is correct, right?) begin refactoring, but don’t go too far too fast! For now, stick with refactoring strategies that are in the category of proper naming, functions doing only one thing, and the avoidance of mutation; don’t immediately start making extensible or reusable classes and factories until you have identified a repeating pattern.&lt;/p&gt;

&lt;p&gt;At this point, it makes sense to use any refactoring that has a logical benefit. This means refactoring with the purpose of the code being understood, or the code being reliable.&lt;/p&gt;

&lt;p&gt;Consider postponing refactoring with patterns that are only useful in certain scenarios.&lt;/p&gt;

&lt;p&gt;You’ll want to save those until you have a reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  Have A Reason
&lt;/h2&gt;

&lt;p&gt;Having SOLID code is not a reason. Having functional or pure code is not a reason.&lt;/p&gt;

&lt;p&gt;Why do we make our code extensible? So that similar, but not identical, functionality can branch off of base logic.&lt;/p&gt;

&lt;p&gt;Why do we invert dependencies? So that the business logic can be used by multiple implementations.&lt;/p&gt;

&lt;p&gt;Hopefully, you see where I am going with this. Some refactoring stands on its own. For example, refactoring the name of a variable to become more accurate will always make sense. Its merit is inherent. Refactoring a function to be pure usually makes sense because side-effects can cause unforeseen issues. That's a valid reason.&lt;/p&gt;

&lt;p&gt;“It’s best practice to use dependency inversion” is not a reason. “Good code is extensible” is not a reason. What if I only have a couple of never-changing dependencies? Do I still need dependency inversion? Perhaps not yet. What if nothing needs to extend my code and I have no plans for anything to do so? Should my code increase its complexity just to check off this box? No!&lt;/p&gt;

&lt;p&gt;Take a look at the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// not extensible&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Justin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;justinfuller@email.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;entitlements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;global&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;feature_specific&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// used later&lt;/span&gt;

&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;entitlements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;feature_specific&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// Extensible&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// initialize here&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;hasEntitlement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expectedEntitlement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entitlements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expectedEntitlement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// used later&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;hasEntitlement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;feature_specific&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which do you prefer? Which do you naturally tend to write first? Of course, the User class is far more extensible because it can be overriden by another class. For example, if you had a &lt;code&gt;SuperUser&lt;/code&gt; then you could implement &lt;code&gt;hasEntitlement&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;hasEntitlement&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't let the Class throw you off. The same result can be accomplished without it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function superUser(user) {
  return {
    ...user,
    hasEntitlement() {
      return true
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Either way, this encapsulation of &lt;code&gt;hasEntitlement&lt;/code&gt; allows the User to, for different use cases, take advantage of polymorphism to extend—rather than change—the code.&lt;/p&gt;

&lt;p&gt;Still, that User class may be complete overkill, and now your code is more complicated than it will ever need to be.&lt;/p&gt;

&lt;p&gt;My advice is to stick with the simplest possible pattern until you have a reason for something more complex. In the above solution, you may choose to stick with the same simple User data object until you have multiple user types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Order Of Complexity
&lt;/h2&gt;

&lt;p&gt;And now, if you’ll allow it, I’m going to make something up! I call it the order of complexity and it helps me when I make refactoring decisions. It looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const" rel="noopener noreferrer"&gt;Constant Variable&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let" rel="noopener noreferrer"&gt;Mutable Variable&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collection (Object, Array)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Function&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Function with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" rel="noopener noreferrer"&gt;Closure&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Factory (A function that returns a collection)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Class&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whenever I decide how to organize functionality, I refer to the list. I choose the highest possible choice that will suffice for my implementation. I don’t choose again until it simply will not work. Sometimes performance will affect this choice, but not often.&lt;/p&gt;

&lt;p&gt;Usually, I find that I’ll put something in an object instead of a simpler constant variable. Or I created a factory when I only require a function.&lt;/p&gt;

&lt;p&gt;This list keeps me grounded. It prevents me from prematurely refactoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Balance
&lt;/h2&gt;

&lt;p&gt;I recently heard that if you say in a meeting, “it’s all about finding balance,” everyone will nod their head at your meaningless comment like you’ve said something profound. I’ve got to give it a try soon.&lt;/p&gt;

&lt;p&gt;Here, though, I think balance is important. As programmers, we have to balance code quality, performance, maintainability, with the good old-fashioned need to get things done.&lt;/p&gt;

&lt;p&gt;We have to be vigilant and make sure both needs stay in their correct place. Our code can’t be maintainable if it doesn’t work correctly. On the other hand, it’s hard to make bad code work correctly.&lt;/p&gt;

&lt;p&gt;Still, code may be refactored, but what if it’s been refactored past the point of what is useful? These are important questions to keep in mind.&lt;/p&gt;

&lt;p&gt;Next time you write your code, please, refactor! But also, maybe… don’t?&lt;/p&gt;




&lt;p&gt;This is a repost, the post originally appeared on &lt;a href="https://justindfuller.com/posts/2019-01-24_refactoring-oops-ive-been-doing-it-backwards" rel="noopener noreferrer"&gt;www.justindfuller.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Hi, I’m Justin Fuller. I’m so glad you read my post! I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer in &lt;em&gt;any&lt;/em&gt; way. All code samples are my own and are completely unrelated to my employer's code.&lt;/p&gt;

&lt;p&gt;I’d also love to hear from you, please feel free to connect with me on &lt;a href="https://github.com/justindfuller" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/justin_d_fuller" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;. Thanks again for reading!&lt;/p&gt;

</description>
      <category>refactoring</category>
      <category>javascript</category>
      <category>oop</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Service calls make your tests better</title>
      <dc:creator>Justin Fuller</dc:creator>
      <pubDate>Fri, 19 Jul 2019 02:13:48 +0000</pubDate>
      <link>https://dev.to/justindfuller/service-calls-make-your-tests-better-2eck</link>
      <guid>https://dev.to/justindfuller/service-calls-make-your-tests-better-2eck</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://justindfuller.com/posts/2019-07-19_service-calls-make-your-tests-better?utm_source=Dev.To&amp;amp;utm_medium=referral&amp;amp;utm_campaign=learning_javascript" rel="noopener noreferrer"&gt;JustinDFuller.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; If all tests are mocked, you don’t know if your code really works, you only know that, theoretically, it is supposed to work if the integrations adhere to the contract you expect. &lt;/p&gt;

&lt;p&gt;Mocking, stubbing, or maybe—even better—dependency inversion, they can simplify testing and make your code easier to change, but can they cause problems too? Let’s see. &lt;/p&gt;

&lt;p&gt;Take a look at this test where we are saving a file using an external file service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2Ay5AJuTRbi2HBrah3" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2Ay5AJuTRbi2HBrah3" width="700" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can you determine if this is a useful test?&lt;/p&gt;

&lt;p&gt;The answer is that it most likely isn’t going to ever catch any bugs. Let’s see if we can determine why not.&lt;/p&gt;

&lt;p&gt;The first reason is that we are using a mock implementation of the drive service. So we won’t catch any errors if someone changes the drive service without changing the file uploader. &lt;/p&gt;

&lt;p&gt;Now, what about even further down the line? What if something changes with the actual drive server that we want to integrate with? We certainly won’t catch those errors because we aren’t ever making a call to it.&lt;/p&gt;

&lt;p&gt;In the end the only thing we are truly testing is that the uploadFile method gives the file object to the driveService’s write function. We’ll catch an error if drive service uses the file object incorrectly, or if fileUploader stops giving the file directly to the drive service.&lt;/p&gt;

&lt;p&gt;Unfortunately we will also have to update this test whenever we change how fileUploader and driveService interact.&lt;/p&gt;

&lt;p&gt;So not only is the test brittle, it’s just not very useful. Further, in a typed language it would be completely useless since the compiler would catch these types of errors during compilation.&lt;/p&gt;

&lt;p&gt;So, how can we make this test better? The test can become useful if it actually makes the service call to the drive server. Not the internal drive service object, but to a real drive server. &lt;/p&gt;

&lt;p&gt;Immediately you should be objecting, “My unit tests will take forever to run and become extremely brittle if I am making real service calls!” If you said that then you are absolutely right. This test is best served as an integration test. &lt;/p&gt;

&lt;h2&gt;
  
  
  Integration Tests
&lt;/h2&gt;

&lt;p&gt;Integration tests may not be run as often as unit tests, but they should—at the very least—be run before integrating your changes into the code base. See what I did there? Integration tests run when you integrate. &lt;/p&gt;

&lt;p&gt;Still, the problem exists, how could I realistically run all the servers needed for my application to function? Starting them up can be expensive, not to mention the data stores, managing ports, authentication, and everything else that goes into creating a fully-functioning system.&lt;/p&gt;

&lt;p&gt;Take a look at this simple system diagram. It represents a very stripped-down version of the system in the example test from earlier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2AEByxzGkBFV-tC8L8" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2AEByxzGkBFV-tC8L8" width="626" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that all we’re interested in here is testing the integration of our “File Service” with the external “Drive Service” that belongs to another team. In this case we’re not trying to run a full end to end test. &lt;/p&gt;

&lt;p&gt;But what are we actually testing?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2Ac8sCS-H_FJxRSUyg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2Ac8sCS-H_FJxRSUyg" width="626" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oops! Here, as shown in green, only the file service was tested. We wanted to test if our File Service and its connection to the Drive service are actually working. So instead of writing a mocked version on our end, we will look for a way to obtain a testable version of the drive service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolated Services
&lt;/h2&gt;

&lt;p&gt;One option is to create an isolated version of the Drive Service. Ideally this will be owned by the team that created the Drive Service. In order to ensure that the fake server is trustworthy they will run the same tests against both the fake server and the real server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2AGp-SMfRFeoTXyimI" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2AGp-SMfRFeoTXyimI" width="700" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above code represents a sample isolated server implementation. You can see that it is very similar to the real server implementation, except that it uses an in-memory data store instead of a real file storage device. It even uses port 0 to ensure that an ephemeral port is used, further increasing the stability of it’s tests.&lt;/p&gt;

&lt;p&gt;Now that the Drive team is providing this isolated server, our integration tests can safely start it and use it during integration tests. Let’s rewrite that original test as an integration test and see if it becomes more useful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2A7I8V3PLQgOKOCv0w" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2A7I8V3PLQgOKOCv0w" width="700" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, is our test more useful? Since we made the call to the real Drive Server api (even though it saves to a different storage device, the API and business logic remain the same) we will know if our integration breaks. &lt;/p&gt;

&lt;p&gt;Even better, not only were we able to test what URL it returns, we were able to test if the content was saved as expected.  Our test will actually tell us if file saving works!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2AqeITxHrazRrTKg27" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2AqeITxHrazRrTKg27" width="626" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look at our system diagram again. You can see in green the services that are being tested. This time we are testing the file service, the drive service, and, most importantly, the connection between them.&lt;/p&gt;

&lt;p&gt;It isn’t realistic to expect that this set of tests will be run every time we change a line of code—that expectation is reserved for unit tests—but this test is still lightweight enough to run on each code check-in. Executing the integration test in this fashion will ensure that your main branch(es) will have not only correct business logic, but also working integrations with other services. &lt;/p&gt;

&lt;h2&gt;
  
  
  A fallback when an isolated service just isn’t possible
&lt;/h2&gt;

&lt;p&gt;Sometimes you really may have some kind of environment or build-time constraint that makes an isolated server impossible. If that’s the case then you could look to fake APIs as a fallback. &lt;/p&gt;

&lt;p&gt;Remember, we’re still talking about integrations here—code that interacts with other services. You may have noticed the code contained two Drive related entities: “DriveServer” and “DriveService”. The DriveServer was the actual service that belongs to the third party. We were using their in-memory version to test our integration with their service. The DriveService is an API that knows how to interact with a DriveServer. This API also belongs to the Drive team. &lt;/p&gt;

&lt;p&gt;Thankfully they understand that not everyone can use their isolated in-memory server, so they also created a fake version of their API. Take a look.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2AnRPxOUoRRxlyo_bD" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2AnRPxOUoRRxlyo_bD" width="700" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This FakeDriveService is an implementation that the Drive Team could provide to anyone who uses their service. They are saying “If you test with the FakeDriveService you can trust that the real DriveService will work. We run tests against both to ensure that they work the same.” &lt;/p&gt;

&lt;p&gt;This implementation is obviously even lighter than the isolated server, so what’s the drawback? Let’s refer, once again, to our system diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2A-HnhLFl8kcpFkPd9" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F626%2F0%2A-HnhLFl8kcpFkPd9" width="626" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While we are technically testing the connection mechanism we aren’t actually touching the Drive Service. Our test is built on trust, not actual verification. The trust is that the fake service really does work the same as the full service. In many scenarios this could be good enough, but if you have a production critical system you may need a better guarantee.&lt;/p&gt;

&lt;p&gt;Still, this test is better than the original mock function that we started with. That mock function was completely untrustworthy to the point that, I would argue, it actually tricked us into thinking we were safe from bugs, but in reality we had no idea. Our tests will now have to change if the Drive Service changes. In that first mock scenario we wouldn’t have had to change our tests, it would have tricked us into thinking that our code still worked, even when it was broken due to an API change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Credits
&lt;/h3&gt;

&lt;p&gt;This post was directly inspired by posts that I recently found in Google’s “Testing on the toilet” blog. I wanted to take their idea and reframe it in the lens of a JavaScript application. Please see the links below to read their original posts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exercise service call
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://testing.googleblog.com/2018/11/testing-on-toilet-exercise-service-call.html" rel="noopener noreferrer"&gt;https://testing.googleblog.com/2018/11/testing-on-toilet-exercise-service-call.html&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Fakes
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://testing.googleblog.com/2013/06/testing-on-toilet-fake-your-way-to.html" rel="noopener noreferrer"&gt;https://testing.googleblog.com/2013/06/testing-on-toilet-fake-your-way-to.html&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Hermetic Servers
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://testing.googleblog.com/2012/10/hermetic-servers.html" rel="noopener noreferrer"&gt;https://testing.googleblog.com/2012/10/hermetic-servers.html&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;The views and suggestions here are my own, not my employer’s. I in no way intend to represent them through this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get in touch
&lt;/h3&gt;

&lt;p&gt;I’d love to hear from you. Please feel free to reach out to me on &lt;a href="https://github.com/justinDFuller" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/justin_d_fuller" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;This is a repost, the post originally appeared on &lt;a href="https://justindfuller.com/posts/2019-07-19_service-calls-make-your-tests-better" rel="noopener noreferrer"&gt;www.justindfuller.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>tdd</category>
      <category>node</category>
    </item>
  </channel>
</rss>
