<?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: Stuart Dotson</title>
    <description>The latest articles on DEV Community by Stuart Dotson (@sdotson).</description>
    <link>https://dev.to/sdotson</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%2F341926%2Fcc3e79e3-79ed-4a3b-b5af-dc32f898af3f.jpeg</url>
      <title>DEV Community: Stuart Dotson</title>
      <link>https://dev.to/sdotson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sdotson"/>
    <language>en</language>
    <item>
      <title>How to find your forgotten software engineer tasks</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Fri, 14 Jun 2024 12:47:22 +0000</pubDate>
      <link>https://dev.to/sdotson/how-to-find-your-forgotten-software-engineer-tasks-29j3</link>
      <guid>https://dev.to/sdotson/how-to-find-your-forgotten-software-engineer-tasks-29j3</guid>
      <description>&lt;p&gt;Do you ever wonder how many software engineering tasks have fallen through the cracks? How many times you've let your coworkers down?&lt;/p&gt;

&lt;p&gt;It is extremely easy for this to happen, especially for mentions of your username scattered across various platforms like GitHub, Jira, Google Docs, Slack, and so many others. Each of these mentions represents a time when a coworker asked a question or shared a perspective squarely in your direction. If you like, or at the very least respect your coworkers, these mentions warrant some sort of response, either an emoji reaction or a comment.&lt;/p&gt;

&lt;p&gt;Some other software engineering tasks that are easy to lose sight of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jira tickets assigned, especially if they are carryovers from the previous sprint and weren't moved over to the current sprint.&lt;/li&gt;
&lt;li&gt;GitHub issues and pull requests you've opened for third-party libraries. These issues sometimes take months to be addressed, but it is worthwhile to keep tabs on them so you can help push them along.&lt;/li&gt;
&lt;li&gt;GitHub review requests.&lt;/li&gt;
&lt;li&gt;Other requests not captured by a Jira ticket.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;BeyondDone has a tool called the &lt;a href="https://www.beyonddone.com/forgotten-task-finder"&gt;Forgotten Task Finder&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tool will guide you through connecting your GitHub and optionally your Jira account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dukuri630l5l3wwxfqo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dukuri630l5l3wwxfqo.png" alt="Screenshot of the Forgotten Task Finder starting page" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After connecting your accounts you'll see a summary of the findings. It even calculates the depth of disappointment you have created in your coworkers. After running through this tool, I learned I created 3 shot glasses full of coworker tears from ignoring their mentions, calculated assuming 0.5 ml tears, a crying rate of 15 ml/minute, and an average of 2 minutes of crying per forgotten mentions. Perhaps a little dramatic, but it drove the point home for me. Even if my coworkers aren't crying, I'm certainly making them feel unimportant by not addressing the comments they've directed at me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqey2bz73cil1t3mfxqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqey2bz73cil1t3mfxqv.png" alt="Screenshot of the Forgotten Task Finder results summary" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the summary, you'll see a full log of your regrets, including every unaddressed mention, as well as any open GitHub prs, GitHub issues, Jira tickets, and other tasks across your GitHub and Jira accounts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcywmtaqyd5guvu94e5e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcywmtaqyd5guvu94e5e6.png" alt="Screenshot of the log of regret" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/fHShdj8uN00"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The BeyondDone &lt;a href="https://www.beyonddone.com/forgotten-task-finder"&gt;Forgotten Task Finder&lt;/a&gt; is an excellent tool to use to see all the software engineering tasks that have fallen through the cracks.&lt;/p&gt;

&lt;p&gt;If you want to use this tool regularly, you'll need to reconnect your GitHub and Jira accounts over and over.&lt;/p&gt;

&lt;p&gt;Thankfully, BeyondDone allows users to sign up for accounts. After signing up for an account, you only need to connect your GitHub and Jira accounts once. You'll then get access to a Todos list that gets updated with the latest information every minute. You'll also get access to automatically generated standup updates, a log of your activities, and the ability to add custom todos/accomplishments that exist outside of the GitHub, Jira, and Confluence platforms.&lt;/p&gt;

&lt;p&gt;I use BeyondDone every day and it has turbocharged my ability to stay on top of things and sell myself better in standup.&lt;/p&gt;

&lt;p&gt;I encourage you all to take a look at &lt;a href="https://www.beyonddone.com"&gt;BeyondDone's features&lt;/a&gt; and &lt;a href="https://www.beyonddone.com/auth/signup"&gt;sign up today&lt;/a&gt;. There's a 30-day free trial and no payment information is required up-front.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>softwareengineering</category>
      <category>career</category>
      <category>agile</category>
    </item>
    <item>
      <title>How to remember everything for standup</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Wed, 12 Jun 2024 13:38:59 +0000</pubDate>
      <link>https://dev.to/sdotson/how-to-remember-everything-for-standup-11a8</link>
      <guid>https://dev.to/sdotson/how-to-remember-everything-for-standup-11a8</guid>
      <description>&lt;p&gt;Do you have trouble remembering your software engineering accomplishments and todos for your standup update? Perhaps you work hard. You juggle a lot of tasks. You help your coworkers. But when the daily standup meeting comes around, you can't seem to remember everything. &lt;/p&gt;

&lt;p&gt;I'll review the advantages and disadvantages of some common standup preparation strategies so you'll never sell yourself short or forget a task again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option #1 Take notes
&lt;/h2&gt;

&lt;p&gt;Many experienced engineers take notes whenever they switch to a different task or leave their desks. They write what they're currently working on, what they've done, and some thoughts on the current task they are working on. You can do the same. &lt;/p&gt;

&lt;p&gt;I've encountered a lot of engineers who keep a journal and pen around, but you could also use a note-taking app like &lt;a href="https://support.apple.com/guide/notes/welcome/mac"&gt;Notes&lt;/a&gt;, &lt;a href="https://obsidian.md/"&gt;Obsidian&lt;/a&gt;, or &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reference these notes before or during standup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Full creative control. You can have whatever you want in your notes. You are limited only by your imagination.&lt;/li&gt;
&lt;li&gt;The notes are wherever you want to keep them, whether that is in a physical journal or your favorite note-taking app.&lt;/li&gt;
&lt;li&gt;If you are very particular, extremely disciplined, and extremely organized this may be the path for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Every item needs to be manually entered or written down.&lt;/li&gt;
&lt;li&gt;The notes are only as good as your consistency and discipline. If you forget to write something down, that thing won't be in your notes.&lt;/li&gt;
&lt;li&gt;Your ability to quickly grok what's going on in your professional life for a standup update depends upon the quality of your note-taking organization.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #2 Use bookmarks
&lt;/h2&gt;

&lt;p&gt;The second option involves setting up bookmarks in your web browser so you can quickly review what you've done 5-10 minutes before the standup meeting. &lt;/p&gt;

&lt;p&gt;Take a look at our guide on how to track your &lt;a href="https://www.beyonddone.com/blog/posts/github-todos-and-accomplishments"&gt;GitHub todos and accomplishments&lt;/a&gt; and how to track your &lt;a href="https://www.beyonddone.com/blog/posts/jira-todos-and-accomplishments"&gt;Jira todos and accomplishments&lt;/a&gt;. From there, you can set up some bookmarked pages to reference before the standup meeting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses dashboards maintained by GitHub and Jira.&lt;/li&gt;
&lt;li&gt;Less reliant on self-discipline and superhuman organizational skills.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The dashboards are not comprehensive and do not include all your todos and accomplishments.&lt;/li&gt;
&lt;li&gt;The dashboards are platform-specific. You'll need at least two browser tabs to thoroughly review where you are at. &lt;/li&gt;
&lt;li&gt;You'll have to look at timestamps to determine what has happened since the last standup update.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #3 BeyondDone App
&lt;/h2&gt;

&lt;p&gt;The final option is the BeyondDone app, which offers you the ability to see all your todos and accomplishments in one special automatically generated standup update page.&lt;/p&gt;

&lt;p&gt;There's even a copy/paste button so you can quickly drop the update in Slack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayac202x3h9406dzlai1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayac202x3h9406dzlai1.png" alt="Image description" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BeyondDone allows you to configure the cadence and times of your standups so that the standup page always shows the relevant todos and accomplishments since your last standup meeting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc8ixe2yafptffu7yuf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc8ixe2yafptffu7yuf9.png" alt="Image description" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I use BeyondDone every day and it has turbocharged my ability to stay on top of things and sell myself better in standup.&lt;/p&gt;

&lt;p&gt;I encourage you all to take a look at &lt;a href="https://www.beyonddone.com"&gt;BeyondDone's features&lt;/a&gt; and  &lt;a href="https://www.beyonddone.com/auth/signup"&gt;sign up today&lt;/a&gt;. There's a 30-day free trial and no payment information is required up-front.&lt;/p&gt;

</description>
      <category>standup</category>
      <category>productivity</category>
      <category>career</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>How to track your Jira todos and accomplishments</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Fri, 31 May 2024 12:37:18 +0000</pubDate>
      <link>https://dev.to/sdotson/how-to-track-your-jira-todos-and-accomplishments-1920</link>
      <guid>https://dev.to/sdotson/how-to-track-your-jira-todos-and-accomplishments-1920</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkij9utwo47rc1g2u677o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkij9utwo47rc1g2u677o.png" alt="Image description" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi all. Last week we covered &lt;a href="https://dev.to/sdotson/how-to-track-your-github-todos-and-accomplishments-3n59"&gt;GitHub todos and accomplishments&lt;/a&gt;. This week, we'll take a look at Jira.&lt;/p&gt;

&lt;p&gt;Jira presents many opportunities for tasks and accomplishments to fall through the cracks. Just like in GitHub, your coworkers can mention you in a comment on an issue assigned to someone else. Assigned tickets can sometimes fall off the Jira Board you look at with your team.&lt;/p&gt;

&lt;p&gt;Rest assured that you are not alone. These are challenges faced by a lot of engineers. Thankfully there are solutions for these challenges. I'll describe the Jira todos and accomplishments most software engineers want to track then describe five solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jira todos and accomplishments
&lt;/h2&gt;

&lt;p&gt;Here is a short list of Jira events and the todo action required from the software engineer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jira ticket assigned - Start research and investigation. Write code. Open a pull request. Get the code deployed to production.&lt;/li&gt;
&lt;li&gt;Username mentioned in a comment - Respond to the coworker who addressed you in a comment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, there are Jira accomplishments that the software engineer should remember for standup and their reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jira tickets created and updated&lt;/li&gt;
&lt;li&gt;Jira tickets started&lt;/li&gt;
&lt;li&gt;Jira tickets completed&lt;/li&gt;
&lt;li&gt;Comments and discussions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #1 Watch your email inbox
&lt;/h2&gt;

&lt;p&gt;The first alternative is to configure your notifications so that you receive notifications to your email inbox. The exact URL will depend on your Jira configuration, but generally the URL will be &lt;code&gt;https://${your-subdomain}.atlassian.net//jira/settings/personal/notifications&lt;/code&gt;, being careful to replace &lt;code&gt;${your-subdomain}&lt;/code&gt; with your subdomain name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Real-time notifications when things happen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If there are more than just a few of these notifications, it can be easy to lose or forget about them, especially when mixed with your other email.&lt;/li&gt;
&lt;li&gt;You still have to devise some sort of system for marking when items are completed. This could be with email filters, tags, or deletion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #2 Jira Your Work page
&lt;/h2&gt;

&lt;p&gt;The second alternative is Jira's Your Work page that you can find at &lt;code&gt;https://${your-subdomain}.atlassian.net/jira/your-work&lt;/code&gt;. Here you can see a list of tickets you've worked on, viewed, starred, or been assigned.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built and supported by Jira.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No sense of completion. You only see tickets that you've "worked on", whatever that means.&lt;/li&gt;
&lt;li&gt;No sense of what is a lingering todo item.&lt;/li&gt;
&lt;li&gt;Requires you to use this page as your main task management systems. Activity on other platforms, such as on GitHub, are not included.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #3 Jira Board
&lt;/h2&gt;

&lt;p&gt;If you're a software engineer using Jira, you're probably doing using it within the context of a team and looking at the board for their team. The URL will look something like &lt;code&gt;https://${your-subdomain}.atlassian.net/jira/core/projects/${project}/board&lt;/code&gt;, replacing the &lt;code&gt;${your-subdomain}&lt;/code&gt; and the &lt;code&gt;${project}&lt;/code&gt; with the appropriate values.&lt;/p&gt;

&lt;p&gt;The Jira board makes it really easy to see the state of specific tasks, assuming they're represented by a Jira ticket. You can see what needs to be started, what is in progress, and what is completed. There is also a filter where you can toggle only the items you've been assigned.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built and supported by Jira.&lt;/li&gt;
&lt;li&gt;The state of tasks is readily apparent.&lt;/li&gt;
&lt;li&gt;Relevant GitHub pull requests can be seen by clicking on a specific issue.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Only Jira tickets that fit the current criteria for the board are displayed. If your Lead or Product Manager forgets to move a ticket from one sprint to the next, the ticket is not visible.&lt;/li&gt;
&lt;li&gt;Only work captured by a Jira ticket is displayed. Your comments and Jira ticket updates or ticket creations are not included.&lt;/li&gt;
&lt;li&gt;Your tasks are mixed in with everybody else's on your team.&lt;/li&gt;
&lt;li&gt;Informal tasks are not captured like being mentioned in a comment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #4 JQL Queries
&lt;/h2&gt;

&lt;p&gt;Jira has its own query language because of course it does. Atlassian gazed across a landscape of unimaginable splendor, a real cornucopia of options, and somehow saw a desert.&lt;/p&gt;

&lt;p&gt;Look at the &lt;a href="https://support.atlassian.com/jira-service-management-cloud/docs/use-advanced-search-with-jira-query-language-jql/"&gt;JQL documentation page&lt;/a&gt; to learn how to use the language. I'll see you in two weeks.&lt;/p&gt;

&lt;p&gt;The page to construct your own JQL queries is at &lt;code&gt;https://${your-subdomain}.atlassian.net/issues/DEMO-7?jql=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can use these queries to gather issues in a more detailed way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current todos: &lt;code&gt;assignee = currentUser() AND statusCategory not in (Done)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Mentions: &lt;code&gt;comment ~ currentUser() AND statusCategory not in (Done)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are some other queries for completed actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your activity in a given range: &lt;code&gt;(updated &amp;gt;= ${startDateIso}) AND (creator = currentUser() OR assignee = currentUser() OR assignee was currentUser() OR reporter = currentUser() OR commentedBy = currentUser()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open up a few browser tabs, learn a bespoke query language, and explore to your heart's content!&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built and supported by Jira.&lt;/li&gt;
&lt;li&gt;Addresses many disadvantages of a Jira Board or the Your Work page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You have to learn the Jira Query language JQL.&lt;/li&gt;
&lt;li&gt;You must open several tabs or navigate Jira's interface to find the JQL query page.&lt;/li&gt;
&lt;li&gt;Information about updated Jira tickets and when you updated them is lost.&lt;/li&gt;
&lt;li&gt;There's no way to tell if you've responded to a mention.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #5 BeyondDone App
&lt;/h2&gt;

&lt;p&gt;The final option is the BeyondDone app, which lets you see all your Jira todos and accomplishments in one view.&lt;/p&gt;

&lt;p&gt;BeyondDone goes beyond what is offered through the Jira platform in many ways. Jira mentions are displayed and marked done when you respond to the comment. All the Jira tickets you update are included. The diff and date of each update are included. Your Jira comments are displayed and mixed in with all your other activities for your reference.&lt;/p&gt;

&lt;p&gt;BeyondDone also aggregates your todos and activity from GitHub. GitHub activity related to Jira tickets is grouped together. You can add your todos and accomplishments when you have items that don't currently have a BeyondDone integration. I've used these to remind myself to resolve Slack conversations or capture work not covered by a Jira ticket.&lt;/p&gt;

&lt;p&gt;I use BeyondDone every day and it has turbocharged my ability to stay on top of things and sell myself better in standup and with my supervisor.&lt;/p&gt;

&lt;p&gt;I encourage you all to &lt;a href="https://www.beyonddone.com?utm_source=devto&amp;amp;utm_medium=blog"&gt;sign up today&lt;/a&gt;. There's a 30-day free trial and no payment information is required up-front.&lt;/p&gt;

</description>
      <category>jira</category>
      <category>webdev</category>
      <category>softwaredevelopment</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to track your GitHub todos and accomplishments</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Wed, 29 May 2024 13:56:56 +0000</pubDate>
      <link>https://dev.to/sdotson/how-to-track-your-github-todos-and-accomplishments-3n59</link>
      <guid>https://dev.to/sdotson/how-to-track-your-github-todos-and-accomplishments-3n59</guid>
      <description>&lt;p&gt;Have you ever seen a GitHub notification, made a mental note to circle back, and then later forgot where it happened or couldn’t find it? Ever get pulled away to attend standup and froze when you were asked what you did and what you still need to do?&lt;/p&gt;

&lt;p&gt;Rest assured that you are not alone. These are challenges faced by many software engineers. Thankfully there are solutions. I’ll list the Github todos and accomplishments most software engineers want to track before presenting three solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Github todos and accomplishments
&lt;/h2&gt;

&lt;p&gt;Here is a short list of GitHub events and the todo action required from the software engineer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pull request reviewed, changed requested — Make changes.&lt;/li&gt;
&lt;li&gt;Pull request reviewed, approved — Look it over, perhaps test again, and merge.&lt;/li&gt;
&lt;li&gt;Pull request reviewed, commented — Address the comments.&lt;/li&gt;
&lt;li&gt;Pull request in need of review — Request reviews in GitHub and/or some other communication medium.&lt;/li&gt;
&lt;li&gt;Pull request with failing status check — Investigate what is breaking the status check and fix it.&lt;/li&gt;
&lt;li&gt;Request for pull request review — Review the pull request.&lt;/li&gt;
&lt;li&gt;Issue assigned — Work to resolve the issue.&lt;/li&gt;
&lt;li&gt;Open Issue — Manage moving the open issue forward by responding to comments.&lt;/li&gt;
&lt;li&gt;Mention — Respond to messages directed to them with a reaction or comment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, there are GitHub accomplishments that the software engineer should remember for standup and their own reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pull requests reviewed, commented, approved, opened, and merged&lt;/li&gt;
&lt;li&gt;Repos and issues created&lt;/li&gt;
&lt;li&gt;Comments and discussions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #1 Watch your email inbox or phone
&lt;/h2&gt;

&lt;p&gt;The first alternative is to configure GitHub notifications so that you receive notifications to your phone and email inbox.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Real-time notifications when things happen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If there are more than just a few of these notifications, it can be easy to lose or forget about them, especially when they’re mixed with your other email and text messages.&lt;/li&gt;
&lt;li&gt;The software engineer still has to devise some sort of system for marking when items are completed. This could be with email filters, tags, or deletion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #2 GitHub Notifications
&lt;/h2&gt;

&lt;p&gt;The second alternative is to look at the GitHub Notifications page. The filter option allows the software engineer to view only notifications of interest and decrease the noise on the page. There is also the ability to mark items done. For this option to work, the software engineer needs to look at the Notifications page daily and manually mark items as “done” as they complete them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built and supported by GitHub.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Very manual. The software engineer needs to mark things like open pull requests as “done” to remove them from the main Notifications view even when they’re obviously done, such as is the case for merged pull requests.&lt;/li&gt;
&lt;li&gt;Requires the software engineer to use the GitHub Notifications page as their task management system. Might be ok if all their work is within the walls of Github, but if they do things in other platforms such as Jira, Slack, or Confluence, it means they’re juggling several different task management systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option #3 BeyondDone App
&lt;/h2&gt;

&lt;p&gt;The final option is the BeyondDone app, which allows you to see all your GitHub todos and accomplishments in one view.&lt;/p&gt;

&lt;p&gt;BeyondDone goes beyond what is offered through the GitHub platform in many ways. GitHub todo items are automatically marked done and transferred to an Activity page, where it is organized by date or time. In addition, these items are included in an automatically generated standup update ready for your next standup. The Todos page displays the status checks for your pull requests, so you know when there is a failing build to investigate.&lt;/p&gt;

&lt;p&gt;Beyond the GitHub platform, BeyondDone aggregates your todos and activity from Jira and Confluence. Github activity related to Jira tickets is grouped. You can add your todos and accomplishments when you have items that don’t currently have a BeyondDone integration. I’ve used these to remind myself to resolve Slack conversations or capture work not covered by a Jira ticket.&lt;/p&gt;

&lt;p&gt;I use BeyondDone daily, which has turbocharged my ability to stay on top of things and sell myself better in standup and meetings with my supervisor.&lt;/p&gt;

&lt;p&gt;I encourage you all to &lt;a href="https://www.beyonddone.com?utm_source=devto&amp;amp;utm_medium=blog"&gt;sign up today&lt;/a&gt;. There’s a 30-day free trial with no payment information required.&lt;/p&gt;

</description>
      <category>github</category>
      <category>taskmanagement</category>
      <category>productivity</category>
    </item>
    <item>
      <title>4 things I learned writing tests for my CLI</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Mon, 20 Apr 2020 19:34:51 +0000</pubDate>
      <link>https://dev.to/sdotson/4-things-i-learned-writing-tests-for-my-cli-1fk0</link>
      <guid>https://dev.to/sdotson/4-things-i-learned-writing-tests-for-my-cli-1fk0</guid>
      <description>&lt;p&gt;I recently updated tests in my open source library &lt;a href="https://www.npmjs.com/package/get-open-prs"&gt;get-open-prs&lt;/a&gt;. My goal was to get as close as I possibly could to 100% test coverage. However, there were a few obstacles I had to overcome to do so. &lt;a href="https://www.npmjs.com/package/get-open-prs"&gt;get-open-prs&lt;/a&gt; is a CLI and has a lot of side effects like printing to the console or waiting for user input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stub out console.log
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let consoleStub;  

beforeEach(() =&amp;gt; {
    consoleStub = sinon.stub(console, 'log');  
});

afterEach(() =&amp;gt; {
    consoleStub.restore();
})

// ...then later after executing function with console.log side effect.
assert(consoleStub.calledWith('there'), 'console.log should be called with argument 2');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Stub out a 3rd party module or your own
&lt;/h3&gt;

&lt;p&gt;In my case, I was using &lt;a href="https://github.com/SBoudrias/Inquirer.js/"&gt;Inquirer&lt;/a&gt; to print cool prompts to the console to get input from the user. Well, similar to how I did &lt;code&gt;console.log\&lt;/code&gt; in the previous tip.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const inquirer = require('inquirer’);
const inquirerStub = sinon.stub(inquirer, 'prompt');

inquirerStub.withArgs(question).resolves({
  prToOpen: 'pr-url-1'
});

assert(inquirerStub.calledWith(question), 'inquirer.prompt for pr question should be called');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I also implemented a dependency-injection pattern to build the main function orchestrating the various dependencies of printing output, getting prs, and updating configuration values. This makes testing this function a whole lot easier and more precise as I just test the business logic and not “how it is done”. The “how” is tested in other unit tests. You can see what I did here: &lt;a href="https://github.com/sdotson/get-open-prs/blob/master/src/getOpenPrs.js"&gt;https://github.com/sdotson/get-open-prs/blob/master/src/getOpenPrs.js&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Vary how functions respond on successive calls
&lt;/h3&gt;

&lt;p&gt;Sometimes functions were called multiple times with the same args, but with different results. Did I write crappy non-deterministic code? Not exactly but I did involve a source of entropy in the program: human input. Inquirer prints prompts to the console that is then responded to by our human entropy source. Sinon has this great chaining syntax to describe this scenario:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const inquirerStub = sinon.stub(inquirer, 'prompt');      
inquirerStub.withArgs(question)        
  .onFirstCall().resolves({          
    githubToken: ''        
  })        
  .onSecondCall().resolves({          
    githubToken: 'TOKEN'        
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The only downside is that that in the assertion part of the test, you can’t chain &lt;code&gt;callCount&lt;/code&gt; to the result of &lt;code&gt;calledWith()&lt;/code&gt;. So in the case of &lt;code&gt;Inquirer.prompt()&lt;/code&gt;, which is essentially called for every single question, you’ll have to count all invocations instead of just the easier-to-read count for a given set of arguments. Something like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assert(inquirerStub.callCount === 4, 'inquirer should be called twice for continue and twice for prs');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  reset() and restore()
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;beforeEach(() =&amp;gt; {
  sinon.reset();  
});

afterEach(() =&amp;gt; {    
  inquirerStub.restore();  
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;One important function to remember is &lt;code&gt;sinon.reset()&lt;/code&gt;, which resets both the behavior and history of all stubs. If you just want to reset a specific stub you can use &lt;code&gt;stub.reset()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another is &lt;code&gt;stub.restore()&lt;/code&gt;, which is used to restore the original functionality to the stubbed function. You want your tests to be independent of each other and adding this to stubbed methods will help guarantee that.&lt;/p&gt;

&lt;p&gt;If you’d like to learn more about sinon, take a look at the official documentation: &lt;a href="https://sinonjs.org/releases/latest/stubs/"&gt;https://sinonjs.org/releases/latest/stubs/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>sinon</category>
      <category>testing</category>
    </item>
    <item>
      <title>Python lists, dicts, and functions for Javascript Engineers</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Wed, 01 Apr 2020 03:06:43 +0000</pubDate>
      <link>https://dev.to/sdotson/python-lists-dicts-and-functions-for-javascript-engineers-434</link>
      <guid>https://dev.to/sdotson/python-lists-dicts-and-functions-for-javascript-engineers-434</guid>
      <description>&lt;p&gt;I’ve been getting really into Python recently. There’s been times in the past where I’ve dabbled or built things in Python but something about this recent “build a microservice” project at work has inspired me to learn more and increase my expertise. That project has since left my team’s hands due to sudden company restructuring but I feel happy to pursue the world of Python in my own time for now. Here’s even more things I’ve learned.&lt;/p&gt;

&lt;p&gt;For the curious, here’s my previous post: &lt;a href="https://stuartdotson.com/blog/7-python-basics-for-javascript-engineers/"&gt;7 Python basics for JavaScript Engineers&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Merging Arrays/Lists
&lt;/h3&gt;

&lt;p&gt;In Javascript:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// spread two arrays
[...array1, ...array2]

// concat one array onto another
// does not mutate array1
array1.concat(array2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In Python:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// mutates original list
list1.extend(list2)

// equivalent of spread operator for Python lists
combined_list = [*list1, *list2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Merging Objects
&lt;/h3&gt;

&lt;p&gt;In Javascript:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// merge multiple objects together
Object.assign({}, object1, object2);

// spread operator for objects is still ... in JavaScript
const mergedObject = { ...object1, ...object2 };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In Python:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Python uses ** to spread dicts
merged_dict = { **dict1, **dict2 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Shallow copying gotchas
&lt;/h3&gt;

&lt;p&gt;In the above solutions, only shallow copies are created. If you modify deeply nested  values on one, the other will change as well! That’s because objects and arrays more than a level deep are copied by reference and refer to the same place in memory. JavaScript and Python are very similar in this way.&lt;/p&gt;

&lt;p&gt;For example in Python:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a = [{ "foo": { "bar": "foobar" }}]
b = [*a]
b[0]["foo"]["bar"] = "foo whoa”
print(a)// [{'foo': {'bar': 'foo whoa'}}]a[0] is b[0]
// True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I talked about this already in-depth in the &lt;a href="https://stuartdotson.com/blog/javascript-magic-show/"&gt;JavaScript magic show post&lt;/a&gt;, but here’s a quick example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a = [{ foo: { bar: 'foobar' }}];
const b = [...a];
b[0].foo.bar = 'foo whoa';
console.log(a);
// [{foo: { bar: 'foo whoa'}}]
Object.is(a[0], b[0]);
// true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Most of the time this doesn’t matter, but if you need real deep copies of nested objects and arrays, you need something like &lt;a href="https://docs.python.org/2/library/copy.html"&gt;copy.deepcopy&lt;/a&gt; in Python or &lt;a href="////github.com/kolodny/immutability-helper"&gt;immutability-helper&lt;/a&gt; for JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyword and positional function arguments
&lt;/h3&gt;

&lt;p&gt;In Python, you can give folks the option of using keywords for your function arguments or just the standard order position you may be more familiar with. I’ll give an example of each.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def my_func(arg1, arg2, arg3):
  return arg1, arg2, arg3

// called with keywords
my_func(arg1="arg1 value", arg2="arg2 value", arg3="arg3 value")

// called positionally
my_func("arg1 value", "arg2 value", "arg3 value")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can even mix the different argument styles with the caveat that you cannot do a positional argument after a keyword argument.&lt;/p&gt;

&lt;p&gt;This is ok:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_func("arg1 value", arg2="arg2 value", arg3="arg3 value")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is not ok:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_func("arg1 value", arg2="arg2 value", "arg3 value")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In Javascript, every function argument is positional. You can get close to keyword arguments by having a object and destructuring like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myFunc = ({  arg1,  arg2,  etc}) =&amp;gt; {
  return [arg1, arg2, etc];
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Default function arguments
&lt;/h3&gt;

&lt;p&gt;Default function arguments work the same in JavaScript and Python.&lt;/p&gt;

&lt;p&gt;JavaScript:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myFunc = (
  arg1 = “arg1 default”,  
  arg2 = “arg2 default”
) {
  return [arg1, arg2];
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def my_func(arg1="arg1 default value", arg2="arg2 default value"):
  return arg1, arg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I hope this has been helpful for everybody and look forward to sharing more about my journey.&lt;/p&gt;

</description>
      <category>python</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How I handled configuration in my Node CLI package</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Mon, 23 Mar 2020 02:10:13 +0000</pubDate>
      <link>https://dev.to/sdotson/how-i-handled-configuration-in-my-node-cli-package-33fd</link>
      <guid>https://dev.to/sdotson/how-i-handled-configuration-in-my-node-cli-package-33fd</guid>
      <description>&lt;p&gt;Many folks in the United States are now working from home and social distancing. I am one of them. After cleaning, noodling on the guitar, reading, and pacing around for some time I decided to revisit an open source project I haven’t touched in a year or two: &lt;a href="https://github.com/sdotson/get-open-prs"&gt;get-open-prs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sdotson/get-open-prs"&gt;get-open-prs&lt;/a&gt; is CLI that allows people to quickly see the pull requests opened by their teammates from the command line. Not only that, it’ll allow you to quickly toggle through them with the arrow keys, and when you hit enter, your browser will automatically open that pull request. It does this by saving a Github personal access token and a list of Github usernames representing your teams. Of course this is overridable and changeable at any point.&lt;/p&gt;

&lt;p&gt;I’d like to talk about the biggest change I made to this package, which related to configuration.&lt;/p&gt;

&lt;p&gt;I moved away from environment variables for the Github usernames and token to a library called &lt;a href="https://github.com/sindresorhus/conf#readme"&gt;conf&lt;/a&gt;. Environment variables were a quick and dirty solution but not terribly user-friendly in my opinion. I had considered &lt;a href="https://github.com/lorenwest/node-config"&gt;node-config&lt;/a&gt; as well, but it seems like that solution is more geared towards backend services and not CLIs. The biggest disadvantage is that node-config doesn’t work correctly for globally installed packages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sindresorhus/conf#readme"&gt;conf&lt;/a&gt; does work because it sets the configuration in a file that is in the operating system default location for application configurations. For mac that would be &lt;code&gt;/Users/username/Library/Preferences&lt;/code&gt;. This is determined by a dependency called &lt;a href="https://github.com/sindresorhus/env-paths#pathsconfig"&gt;env-paths&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I added more prompts to automatically guide the user through setting these values for the first time and save them with conf. I feel that this makes this tool way more user-friendly.&lt;/p&gt;

&lt;p&gt;The other change I made inspired was inspired partly by &lt;a href="https://engineering.upside.com/eternal-sunshine-of-the-spotless-architecture-75f4298125e1"&gt;my experiences with Clean Architecture&lt;/a&gt;. I refactored the main function so that dependencies are injected into a higher order function that then builds the function I use for the app. There’s still more that I can do but I feel a lot more secure that this CLI does what it’s supposed to do with these tests. When I have time, I’d like to write more tests for some of those dependencies to get the code coverage up, and perhaps switch to typescript so I can more explicitly define some of the interfaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sdotson/get-open-prs"&gt;Check it out&lt;/a&gt;! I’m definitely open to feedback, suggestions, and of course, pull requests.&lt;/p&gt;

</description>
      <category>node</category>
      <category>cli</category>
      <category>npm</category>
    </item>
    <item>
      <title>7 Python basics for JavaScript engineers</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Mon, 16 Mar 2020 19:38:31 +0000</pubDate>
      <link>https://dev.to/sdotson/7-python-basics-for-javascript-engineers-4e5m</link>
      <guid>https://dev.to/sdotson/7-python-basics-for-javascript-engineers-4e5m</guid>
      <description>&lt;p&gt;I’ll be honest. My main expertise and experience is in JavaScript with Node and frontend frameworks like React. I took a &lt;a href="https://www.edx.org/course/introduction-to-computer-science-and-programming-7"&gt;Python Introduction to Computer Science course through EdX&lt;/a&gt; a few years back and have only really needed to use it sporadically since then. That all changed two weeks ago when a new project started at work. My team was tasked with rapidly getting ramped up on Python and writing a new back-end service in the language.&lt;/p&gt;

&lt;p&gt;Here are 7 things I’ve learned so far writing in the Python language every day:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Python version management
&lt;/h3&gt;

&lt;p&gt;I feel like it’s less common for folks to alternate between different versions of Node these days but the tool to do that in nvm. Python has competing solutions for this problem. Two of those are &lt;a href="https://docs.conda.io/en/latest/"&gt;conda&lt;/a&gt; and &lt;a href="https://github.com/pyenv/pyenv"&gt;pyenv&lt;/a&gt; with &lt;a href="https://github.com/pyenv/pyenv-virtualenv"&gt;pyenv-virtualenv&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;pyenv&lt;/code&gt; allows you to use different versions of python and and &lt;code&gt;pyenv-virtualenv&lt;/code&gt; allows you to sandbox different environments with those different python versions so they don’t conflict. For a while &lt;code&gt;pyenv&lt;/code&gt; and &lt;code&gt;pyenv-virtualenv&lt;/code&gt; were working fine until one day I kept getting really cumbersome openssl issues preventing me from installing dependencies with &lt;a href="https://pypi.org/project/pip/"&gt;pip&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I switched to &lt;code&gt;conda&lt;/code&gt;. &lt;code&gt;conda&lt;/code&gt; is both an environment and package manager. A practice I learned recently was to create a new environment for each project you are working on. So far no issues. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Python dependency management
&lt;/h3&gt;

&lt;p&gt;In JavaScript, you are typically using a &lt;a href="https://www.npmjs.com/"&gt;NPM package registry&lt;/a&gt;, using &lt;code&gt;yarn&lt;/code&gt; or &lt;code&gt;npm&lt;/code&gt; to download those dependencies to your local machine, and the &lt;code&gt;package.json&lt;/code&gt; file to list the dependencies that need to be downloaded.&lt;/p&gt;

&lt;p&gt;In Python the public package registry is the &lt;a href="https://pypi.org/"&gt;Python Package Index (PyPI)&lt;/a&gt;(&lt;a href="https://pypi.org/"&gt;https://pypi.org/&lt;/a&gt;), you use &lt;code&gt;pip&lt;/code&gt; to download dependencies, and the list of dependencies are in &lt;code&gt;requirements.txt&lt;/code&gt; and &lt;code&gt;requirements_test.txt&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Python property/method reference
&lt;/h3&gt;

&lt;p&gt;You can refer to properties in many different ways in JavaScript and you can use any of them regardless of context. You can refer to the &lt;code&gt;assign&lt;/code&gt; property of &lt;code&gt;Object&lt;/code&gt; with &lt;code&gt;Object.assign&lt;/code&gt; or &lt;code&gt;Object["assign"]&lt;/code&gt;, the only real rule being that string property names are generally referred to with dot notation and number property names must use the bracket notation.&lt;/p&gt;

&lt;p&gt;In Python dot notation and bracket notation communicates the relationship of the property to the object. Classes must use the dot notation and dicts must use the bracket notation. Don’t worry, Python will let you know when you make a mistake with &lt;code&gt;AttributeError&lt;/code&gt; if you try to use dot notation with a dict and &lt;code&gt;object is not subscriptable&lt;/code&gt; when you use bracket notation for a class property. Those errors are forever burned into my mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Python async/await
&lt;/h3&gt;

&lt;p&gt;Finally something familiar to JavaScript folks and more or less works the same. In JavaScript async/await works out of the box assuming you’re using a recent enough version of Node. In Python you need to import in &lt;a href="https://docs.python.org/3/library/asyncio.html"&gt;asyncio&lt;/a&gt; and make sure the &lt;a href="https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/"&gt;async/await happens within the context of a created event loop&lt;/a&gt;. JavaScript also doesn’t allow you to &lt;code&gt;await&lt;/code&gt; in a global context. This might change with the &lt;a href="https://github.com/tc39/proposal-top-level-await"&gt;proposal for global await&lt;/a&gt; but for now you have to use &lt;code&gt;await&lt;/code&gt; within the context of a &lt;code&gt;async&lt;/code&gt; function.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Python types
&lt;/h3&gt;

&lt;p&gt;Most of the JavaScript I write these days is with TypeScript. Python has the &lt;a href="https://docs.python.org/3/library/typing.html"&gt;typing&lt;/a&gt; standard library package which can be extended with &lt;a href="https://pydantic-docs.helpmanual.io/usage/models/"&gt;pydantic&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Python case
&lt;/h3&gt;

&lt;p&gt;JavaScript favors camelCase. Python favors snake_case. I suppose you see a bit of both in out in the wild in terms of API JSON formats. &lt;/p&gt;

&lt;p&gt;One way Python tackles this is you can use &lt;code&gt;pydantic&lt;/code&gt; for your type models so that you can use the idiomatic snake_case in your Python service yet use camelCase for the output when you JSON serialize. &lt;a href="https://medium.com/analytics-vidhya/camel-case-models-with-fast-api-and-pydantic-5a8acb6c0eee"&gt;Here’s one tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Python anonymous functions
&lt;/h3&gt;

&lt;p&gt;In JavaScript, anonymous functions are declared like so: &lt;code&gt;() =&amp;gt; {}&lt;/code&gt;. You can assign this to a var &lt;code&gt;const myFunc = () =&amp;gt; {}&lt;/code&gt; or even declare and invoke in place as an immediately invoked anonymous function &lt;code&gt;(() =&amp;gt; {})()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Python the equivalent is a lambda function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example we are declaring a function that accepts argument &lt;code&gt;x&lt;/code&gt; and returns &lt;code&gt;x + 1&lt;/code&gt;. You might be wandering why on Earth this is called a “lamba function”. According to this &lt;a href="https://realpython.com/python-lambda/"&gt;informative article from Real Python&lt;/a&gt;, lamba functions have roots in something called “lambda abstractions” that were developed as a part of “lambda calculus” in the 1930s, which is one of the foundational building blocks of functional programming..&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope to write a few more of these posts as long as I’m continuing to write Python at work and learning things. I’m enjoying it quite a bit, in a way that feels different than when I was in a similar situation learning Go for another service at work some time ago.&lt;/p&gt;

</description>
      <category>python</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Javascript Magic Show: Mutability</title>
      <dc:creator>Stuart Dotson</dc:creator>
      <pubDate>Thu, 27 Feb 2020 00:36:53 +0000</pubDate>
      <link>https://dev.to/sdotson/javascript-magic-show-mutability-10ee</link>
      <guid>https://dev.to/sdotson/javascript-magic-show-mutability-10ee</guid>
      <description>&lt;p&gt;Ladies and gentlemen, boys and girls, welcome to the Javascript magic show!&lt;/p&gt;

&lt;p&gt;Today we will explore a few mysterious and tantalizing feats of magic. Hold on to your socks as we dive into the first trick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Magic Trick #1
&lt;/h2&gt;

&lt;p&gt;Take a look at this box, completely empty, no trapdoors, no hidden pouches, just a regular ‘ole Javascript object.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; 
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// {}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you take a look in our very stylish hat, it is also a regular run of the mill Javascript object.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// {}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re going to place this bunny rabbit in the box, say a few magic words, and voila, the rabbit is going to teleport into the hat. Don’t worry folks, there’s breathing holes in the box. We’re not going to have an unconscious bunny on our hands.&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="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rabbit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi there&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;“Abracadabra!”, I say as I wave my hands over the closed box.&lt;/p&gt;

&lt;p&gt;What’s in the hat now? Any guesses?&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// { rabbit: 'hi there' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rabbit is now in the hat! Truly incredible. How about we check what’s in the box?&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// { rabbit: 'hi there' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh dear. This is a little disturbing. It seems that we’ve cloned the rabbit instead of teleporting it. Is it the exact same rabbit rabbit in the hat and box or is it two separate rabbits? We can check for equality to find out.&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hat&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;gasps in the audience&lt;/em&gt;. The same exact rabbit exists in two places at once! In fact, according to this equality check, the hat and the box are the same thing. What manner of sorcery is this? Let’s go further down the rabbit hole…&lt;/p&gt;

&lt;h2&gt;
  
  
  Magic Trick #2
&lt;/h2&gt;

&lt;p&gt;For the next trick we’ll have several boxes within the box. This time, we’ll use &lt;code&gt;Object.assign&lt;/code&gt; to copy the entire object and use that structure for the hat as well. Both the &lt;code&gt;hat&lt;/code&gt; and the &lt;code&gt;box&lt;/code&gt; will have several boxes inside.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;innerBox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;innerMostBox&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="c1"&gt;// we're creating a copy here, right? TOTAL SAFETY. Right? RIGHT?!?!?!?! &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// { innerBox: { innerMostBox: { rabbit: 'hi there' } } }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s put the &lt;code&gt;rabbit&lt;/code&gt; in the &lt;code&gt;box&lt;/code&gt; and take a look at what’s in the &lt;code&gt;hat&lt;/code&gt;.&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="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerMostBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rabbit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi there&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we had that misstep with magic trick #1, let’s see if we’ve done anything disturbing with the fabric of space and time.&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hat&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// false &lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerBox&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;hat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerBox&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// true &lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerMostBox&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;hat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerMostBox&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// true &lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerMostBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rabbit&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;hat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerMostBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rabbit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow. Only slightly less disturbing. The hat and the box are no longer the same exact thing but not the inner boxes and the rabbits are referring to one thing in two places. Uhhh…let’s try something else here…&lt;/p&gt;

&lt;h2&gt;
  
  
  Magic Trick #3
&lt;/h2&gt;

&lt;p&gt;I really liked the movie Inception. Let’s get a few volunteers from the audience and send them on a hypothetical mission. This trick will be a combination of the previous tricks. Don’t worry! They were outliers. There’s no way something disturbing could happen three times in a row.&lt;/p&gt;

&lt;p&gt;First we’ll define their adventures.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startHypotheticalAdventure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;alertTeam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;awakenTeamInDreamWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;team&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;resultsOfAdventure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sendTeamOnAdventure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alertTeam&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resultsOfAdventure&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;sendTeamOnAdventure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// lucky team member is killed with a coffee mug&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;luckyTeamMember&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;teamMember&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;teamMember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&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="nx"&gt;luckyTeamMember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// luckier team member is beaten up by a bunch of school children &lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;luckierTeamMember&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;teamMember&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;teamMember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rick&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="nx"&gt;luckierTeamMember&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;teamMember&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="nx"&gt;luckierTeamMember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dignity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// luckiest team member hides and loses self-respect&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;luckiestTeamMember&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;teamMember&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;teamMember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Matt&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;hidingPlace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;secretPassageway&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;secretRoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;trapDoor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
          &lt;span class="na"&gt;closet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;luckiestTeamMember&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="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloneOfHidingPlace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;hidingPlace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;cloneOfHidingPlace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secretPassageway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secretRoom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trapDoor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closet&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;selfRespect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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="nx"&gt;luckyTeamMember&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;luckierTeamMember&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;luckiestTeamMember&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;awakenTeamInDreamWorld&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;team&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;teamMember&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;teamMember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;awakenedInDreamWorld&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;teamMember&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;Then we’ll define our team, put them to sleep, and send them on this hypothetical adventure.&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;// we're hoping this will just happen in our imagination &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;team&lt;/span&gt; &lt;span class="o"&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;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;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dignity&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="na"&gt;selfRespect&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="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;Rick&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dignity&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="na"&gt;selfRespect&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="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;Matt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dignity&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="na"&gt;selfRespect&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hypotheticalTeam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;startHypotheticalAdventure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// hypothetical team is a mess, no dignity, no self-respect, &lt;/span&gt;
&lt;span class="c1"&gt;// and not alive! Good thing this is a dream.... &lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hypotheticalTeam&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// the team is still intact here. Right? RIGHT?!?!? &lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;team&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OHHHH THE HUMANITY!!!! WHAT HAVE WE DONE!?!?! &lt;em&gt;shakes fist at the clouds&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What was supposed to be a hypothetical exercise has turned into a real tragedy. Matt has no self-respect, Rick has no dignity, and Bob is dead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pulling back the curtain
&lt;/h2&gt;

&lt;p&gt;Since you all look pretty frightened and disturbed, I’m going to break the cardinal rule of magic and explain how these tricks work.&lt;/p&gt;

&lt;p&gt;These tricks work on the principle that Javascript arrays and objects are passed not as new values, but references to values. So when we assign hat to the value of box we are actually saying that those two variables will refer to the same place in memory. Same thing goes for arrays and objects we pass into functions of any sort, whether they are &lt;code&gt;forEach&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;, or anything else.&lt;/p&gt;

&lt;p&gt;For the first trick, when we assigned hat to the value of box, it was kind of like we showed the audience a box, put a sheet over it, then revealed the box again, only this time we’re calling it a hat. This is less disturbing because our concept of reality isn’t threatened, but rather, your concept of my mental stability.&lt;/p&gt;

&lt;p&gt;The second trick employed &lt;code&gt;Object.assign&lt;/code&gt;, which contrary to popular belief, only performs a root level copy of the object. If there are nested objects and arrays, those will still refer to the same place in memory.&lt;/p&gt;

&lt;p&gt;Finally, for the third trick, I wrote some awful code that represents the kinds of problems these Javascript phenomenon can cause in the wild. Imagine a more complex example where there are more variables involved. More mutations. You’d have quite a mess on your hands. In the unfortunate case of magic trick #3 we accidentally sent our team on a real adventure instead of a hypothetical one and Bob is dead.&lt;/p&gt;

&lt;p&gt;Here are a few suggestions I have for avoiding accidental “magic” in the real world:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use map properly&lt;/strong&gt;. A map is designed to return a new array but only if you return a new value in the iterator function and avoid mutations. If you are mutating things, or interacting with state outside the function scope, you should take a look at perhaps forEach or a for loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t lie to me&lt;/strong&gt;. When I see a function that returns a value and that value being assigned to a new var, my assumption is that the function isn’t changing the value being passed in as an argument. I’m expecting that a whole new value is being returned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you are mutating the original reference, don’t make it seem like the function is creating a new value&lt;/strong&gt;. Return nothing and perhaps add a comment. For example, &lt;code&gt;mutateOriginalArray(array)&lt;/code&gt; instead of &lt;code&gt;const newArray = mutateOriginalArray(array)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be aware of the limitations of &lt;code&gt;Object.assign&lt;/code&gt; as a way of copying objects&lt;/strong&gt;. This only returns a new object at the root level. Perhaps this is ok. If you are hoping for a deep copy, it’ll be more work, because you’ll need to make copies of every nested objected and array as well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make copies of objects and arrays where practical&lt;/strong&gt;.  Consider using an immutability library. Other options include using &lt;code&gt;Array&lt;/code&gt; methods that return a new array like &lt;code&gt;.slice()&lt;/code&gt;, &lt;code&gt;.filter()&lt;/code&gt;, and &lt;code&gt;.map()&lt;/code&gt;. The spread operator &lt;code&gt;...&lt;/code&gt; and &lt;code&gt;Object.assign&lt;/code&gt; are good options as well, keeping in mind their limitations.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>immutability</category>
    </item>
  </channel>
</rss>
