<?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>Forem: Martin Graham</title>
    <description>The latest articles on Forem by Martin Graham (@martinandersongraham).</description>
    <link>https://forem.com/martinandersongraham</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%2F783312%2Fdcaae6f3-d088-423f-9ea5-177bb35aaa9d.png</url>
      <title>Forem: Martin Graham</title>
      <link>https://forem.com/martinandersongraham</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/martinandersongraham"/>
    <language>en</language>
    <item>
      <title>Using Github Actions to Deploy Updates to my VPS</title>
      <dc:creator>Martin Graham</dc:creator>
      <pubDate>Fri, 12 Aug 2022 19:41:47 +0000</pubDate>
      <link>https://forem.com/martinandersongraham/using-github-actions-to-deploy-updates-to-my-vps-40el</link>
      <guid>https://forem.com/martinandersongraham/using-github-actions-to-deploy-updates-to-my-vps-40el</guid>
      <description>&lt;p&gt;I self-host my &lt;a href="https://www.martingraham.dev"&gt;martingraham.dev&lt;/a&gt; website on a VPS on &lt;a href="https://www.linode.com"&gt;Linode&lt;/a&gt;.  The source code is hosted on &lt;a href="https://github.com/martin-anderson-graham/martingraham-dot-dev"&gt;github&lt;/a&gt;, and so every time I wanted to committed updates I had to remote into my VPS to pull the latest version of the repo, build the site and restart the relevant processes.  What is this, 1985?  Enter &lt;a href="https://github.com/features/actions"&gt;Github Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Github actions introduction
&lt;/h3&gt;

&lt;p&gt;Github actions are customizable automations that can be triggered by various github-related events.  In my case, my action occurs when a commit to my &lt;code&gt;main&lt;/code&gt; branch occurs.&lt;/p&gt;

&lt;p&gt;We define our actions in a &lt;code&gt;.yml&lt;/code&gt; file located in &lt;code&gt;.github/workflows&lt;/code&gt;.  Its worth saying at the top - this file will be visible in our repository, so we want to be careful about what information is exposed.  Security first!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update Linode VPS Action&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;main'&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Push-to-linode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'push' &amp;amp;&amp;amp; github.ref == 'refs/heads/main'&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure SSH&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;mkdir -p ~/.ssh/&lt;/span&gt;
          &lt;span class="s"&gt;echo "$SSH_KEY" &amp;gt; ~/.ssh/staging.key&lt;/span&gt;
          &lt;span class="s"&gt;chmod 600 ~/.ssh/staging.key&lt;/span&gt;
          &lt;span class="s"&gt;cat &amp;gt;&amp;gt;~/.ssh/config &amp;lt;&amp;lt;END&lt;/span&gt;
          &lt;span class="s"&gt;Host staging&lt;/span&gt;
            &lt;span class="s"&gt;HostName $SSH_HOST&lt;/span&gt;
            &lt;span class="s"&gt;User $SSH_USER&lt;/span&gt;
            &lt;span class="s"&gt;IdentityFile ~/.ssh/staging.key&lt;/span&gt;
            &lt;span class="s"&gt;StrictHostKeyChecking no&lt;/span&gt;
          &lt;span class="s"&gt;END&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;SSH_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.STAGING_SSH_USER }}&lt;/span&gt;
          &lt;span class="na"&gt;SSH_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.STAGING_SSH_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;SSH_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.STAGING_SSH_HOST }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run npm run deploy&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;ssh staging 'cd ~/martingraham-dot-dev; npm run deploy'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;main'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This bit defines when the action will run.  Mine is super simple, but events are very configurable for advanced deployments.&lt;/p&gt;

&lt;p&gt;A workflow can have multiple jobs - mine only has one, entitled &lt;code&gt;Push-to-linode&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Push-to-linode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This conditional isn't doing anything (due to my event setup), but I left it in for my own future reference of the capability&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'push' &amp;amp;&amp;amp; github.ref == 'refs/heads/main'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I should mention the &lt;code&gt;runs-on: ubuntu-latest&lt;/code&gt; line.  Github actions run on so-called runners.  In our case, the runner is operated by github.  Our later commands will be run from within this runner environment.  You can self-host your own runner, but that could potentially expose the machine to arbitrary code execution (say you have an action that runs on PRs or forks), and so hosting your own run is discouraged for public repos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Push-to-linode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SSH and secrets
&lt;/h3&gt;

&lt;p&gt;Our job runs a few steps, the first of which is to configure an SSH connection to my VPS.  The &lt;code&gt;run&lt;/code&gt; command executes command within the runner environment, so here we are creating an ssh configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;mkdir -p ~/.ssh/&lt;/span&gt;
  &lt;span class="s"&gt;echo "$SSH_KEY" &amp;gt; ~/.ssh/staging.key&lt;/span&gt;
  &lt;span class="s"&gt;chmod 600 ~/.ssh/staging.key&lt;/span&gt;
  &lt;span class="s"&gt;cat &amp;gt;&amp;gt;~/.ssh/config &amp;lt;&amp;lt;END&lt;/span&gt;
  &lt;span class="s"&gt;Host staging&lt;/span&gt;
    &lt;span class="s"&gt;HostName $SSH_HOST&lt;/span&gt;
    &lt;span class="s"&gt;User $SSH_USER&lt;/span&gt;
    &lt;span class="s"&gt;IdentityFile ~/.ssh/staging.key&lt;/span&gt;
    &lt;span class="s"&gt;StrictHostKeyChecking no&lt;/span&gt;
  &lt;span class="s"&gt;END&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$SSH_USER&lt;/code&gt; is a pretty weird user account to use on my VPS, no?  In fact, I don't want the whole internet to know the name of my VPSs internal user accounts.  And I certainly don't want them to have a copy of my private SSH key.  That's where &lt;code&gt;env:&lt;/code&gt; comes in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;SSH_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.STAGING_SSH_USER }}&lt;/span&gt;
  &lt;span class="na"&gt;SSH_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.STAGING_SSH_KEY }}&lt;/span&gt;
  &lt;span class="na"&gt;SSH_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.STAGING_SSH_HOST }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sets up environment variable on the runner which can be accessed by my jobs.  In our Github repository we head into the settings and we can define secrets (SSH keys, API keys, etc) that are accessible by our Github Actions.  Apparently they are also are redacted in logs, but you should always be careful about not logging such values.&lt;/p&gt;

&lt;h3&gt;
  
  
  NPM scripts
&lt;/h3&gt;

&lt;p&gt;The next step uses my newly configured SSH connection to connect to my VPS and run commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run npm run deploy&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;ssh staging 'cd ~/martingraham-dot-dev; npm run deploy'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice &lt;code&gt;ssh staging&lt;/code&gt; - if you look up above you will see that in the configuration file we named the target by writing &lt;code&gt;HOST staging&lt;/code&gt;, and that is what is being referenced here.&lt;/p&gt;

&lt;p&gt;In my case, I am running a node app (&lt;a href="https://kit.svelte.dev/"&gt;SvelteKit&lt;/a&gt; to be precise) that requires a build step, and then the &lt;code&gt;pm2&lt;/code&gt; process associated with the app has to be restarted.  I utilize an &lt;code&gt;npm script&lt;/code&gt; to pull the latest version of the repo, build the app and restart the process.  I like this way fo doing it because if I need to change my build process I don't need to mess with my github action configuration.&lt;/p&gt;

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

&lt;p&gt;So there's a simple introduction to Github Actions - go and save yourself some steps!&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@agk42?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Alex Knight&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/automation?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>githubactions</category>
    </item>
    <item>
      <title>On Mastery of the Fundamentals (Part 1/n)</title>
      <dc:creator>Martin Graham</dc:creator>
      <pubDate>Sat, 23 Jul 2022 21:06:25 +0000</pubDate>
      <link>https://forem.com/martinandersongraham/on-mastery-of-the-fundamentals-part-1n-57md</link>
      <guid>https://forem.com/martinandersongraham/on-mastery-of-the-fundamentals-part-1n-57md</guid>
      <description>&lt;p&gt;As a part of our &lt;a href="https://launchschool.com/capstone"&gt;Capstone preparation&lt;/a&gt; we are working our way through part of the excellent &lt;a href="https://fullstackopen.com"&gt;Full Stack Open&lt;/a&gt; course, much of which has centered on React.  LaunchSchool's Core program is explicit about focusing on JavaScript fundamentals instead of frameworks out of the gate, and my experience of learning React has really demonstrated the wisdom in that approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comfort with the underlying JavaScript
&lt;/h2&gt;

&lt;p&gt;Going through this course I am regularly pleased with how easy it is to pick up the React functionality and not get tripped on on the JavaScript.  Consider the following common line:&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsername&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&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;In this one line are ideas that spanned many different fundamental JavaScript lessons, not limited to (and in no particular order):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Array destructuring is a handy way to return multiple values from a function (and superior to object destructuring in this case)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useState&lt;/code&gt; must be a function based on how it is used - but what exactly the &lt;code&gt;''&lt;/code&gt; argument is doing requires consulting the docs&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setUserName&lt;/code&gt; is now a function to be invoked or passed around as we need&lt;/li&gt;
&lt;li&gt;... (omitted for brevity)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Imagine if this was the first time you had seen array destructuring or higher-order functions - it would take much longer to parse this one line.  And we wouldn't even have touched on the scope of these variables and how to pass them to components defined in other files...&lt;/p&gt;

&lt;h2&gt;
  
  
  An understanding of the problems React solves
&lt;/h2&gt;

&lt;p&gt;Caveat, as a new developer I'm sure I only have a surface level understanding of the problems that React solves, but even so I see some big ones.  In our study of JavaScript fundamentals we covered the DOM manipulation APIs made available to us by the browser.  We did things like:&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;let&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&amp;gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertAdjacentElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterBegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertAdjacentElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterBegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And don't get me started on toggling the visibility of elements.  Understanding the pain of manipulating the DOM manually illuminates how much simpler using React to build applications is.  And I haven't even gotten to complex applications yet - I imagine the benefits scale with application size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Targeting points of confusion
&lt;/h2&gt;

&lt;p&gt;Having a strong mastery of the fundamentals has also been helpful when encountering entirely new syntax. Consider the following return from a React functional component:&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Log&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleLogin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;//...continued&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I had an unsteady grasp on JavaScript I might think you can just write HTML in a .js file.  But I knew better - there is something different going on here, because that is not the way you create and manipulate HTML elements in JavaScripts.  From here it was easy to locate what is actually going on (in this case, JSX).&lt;/p&gt;

&lt;p&gt;And here is the rub - because of my comfort with basic JS and HTML writing JSX is super-easy to pick-up!  One's mastery can be built upon.&lt;/p&gt;

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

&lt;p&gt;I have no regrets of the time I spent on mastery of the fundamentals of JavaScript, and will definitely take this viewpoint with me as I move further into my career.&lt;/p&gt;




&lt;p&gt;Cover Photo by &lt;a href="https://unsplash.com/@jakobustrop?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jakob Braun&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/brick-wall?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>launchschool</category>
      <category>capstone</category>
      <category>fundamentals</category>
    </item>
    <item>
      <title>The Internet and the Beauty of Encapsulation</title>
      <dc:creator>Martin Graham</dc:creator>
      <pubDate>Sun, 10 Apr 2022 03:01:36 +0000</pubDate>
      <link>https://forem.com/martinandersongraham/the-internet-and-the-beauty-of-encapsulation-1e5b</link>
      <guid>https://forem.com/martinandersongraham/the-internet-and-the-beauty-of-encapsulation-1e5b</guid>
      <description>&lt;h2&gt;
  
  
  Or how I learned trust the other person to do their job.
&lt;/h2&gt;

&lt;p&gt;Networking (and by extension, the internet) has a beautiful quality possessed by civilization itself - division and specialization of labor.&lt;/p&gt;

&lt;p&gt;Consider for a moment - what would happen if all the auto mechanics suddenly vanished from the earth?  The reality that none of us know how our car works with sufficient detail to recreate it would set in rather rapidly.  Some say this is a &lt;em&gt;sad&lt;/em&gt; reality.  Nay!  It is a &lt;em&gt;happy&lt;/em&gt; one!  The tremendous wealth that human civilization has as a part of its foundation a division and specialization of labor that frees any one person from having to know everything.  So to with network communication.&lt;/p&gt;

&lt;p&gt;(I actually like working on my car - ours is a special age where rather than &lt;em&gt;must&lt;/em&gt; we &lt;em&gt;can&lt;/em&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  The Physical Layer
&lt;/h2&gt;

&lt;p&gt;The point is most clear with the physical means by which we transmit information.  Most of our network communication involves transmitting bits (i.e. 1s or 0s) - any physical medium that can be in one of two states will allow us to accomplish this.  And over the years we have developed several different way to communicate this - electrical signals on wire, electromagnetic waves and even flashes of light.  &lt;/p&gt;

&lt;p&gt;Each of these mediums was developed to address issue the others were incapable of meeting.  Just a few examples from my own experience running IT at a small school&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copper wires work great at transmitting electrical signals, especially when you can add them during construction of a building&lt;/li&gt;
&lt;li&gt;Fiber optics (using light to transmit bits) is made primarily of glass and plastic and so won't be affected by nearby lightning strikes (I've had to replace switches due to this actually!).  Also distance and bandwidth improvement over copper.&lt;/li&gt;
&lt;li&gt;But everyone looked at me strange when I tried to plug a Cat6 ethernet cable into my phone.  Wifi lets us brake free of the wires, man!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...I'm also wondering at this moment if anyone has built an automatic smoke-signal system that integrates with the internet.  Knowing humanities creative capacity and penchant for the ridiculous, I'm putting my money on yes.  I also wonder under what conditions a router might decide that our smoke signal link is the best route. And here is the key point - &lt;strong&gt;the rest of the network protocols would be totally agnostic to this type of network link&lt;/strong&gt; - it might take a while to load, but you could watch a YouTube video delivered over a smoke signal link.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ethernet
&lt;/h2&gt;

&lt;p&gt;Moving up to the next layer of network protocols we see the benefit of the layers being agnostic to one another.  When I pull the security camera footage of our building up on my phone the information flows over all three medium types I mentioned above!  Imagine if my phone app had to tailor its request differently depending on the type of medium - the complexity added by any update to the system would cause updates to cease.&lt;/p&gt;

&lt;p&gt;Or, to return to the car, imagine if driving an electric car was totally different from driving a car with an combustion engine.  A massive barrier to adoption would be thrown up, and there would be no discernable benefit (save vendor lock-in).  &lt;/p&gt;

&lt;p&gt;Rather, each layer can rely upon the layers below to do what they promise, no matter how they do it.  Just as we can rely upon the brake to stop us, no matter how it does.  Ethernet can bundle up the transmitted bits into an abstraction that works no matter the physical medium.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Internet Layer
&lt;/h2&gt;

&lt;p&gt;For the sake of example we can move up yet another layer.  Ethernet relies on unique addresses (MAC addresses) for each host on the local network - and though IPv6 might allow this for all devices on the internet, the amount of information the routers would have to store would be quite prohibitive.  Enter the Internet Protocol - a way for information to pass between networks.&lt;/p&gt;

&lt;p&gt;Again, we see that passing information between networks works best if the protocol is agnostic to the structure of those networks (as Ethernet is agnostic to the physical medium that is actually transmitting the bits).  'Give me the packet' says IP 'and tell me where it should go - I don't care about the rest'.  &lt;/p&gt;

&lt;p&gt;Perhaps for our car we now discuss the roads.  Be you truck, car, minivan, bus, front-loader, ebike, fishing-trolley-outfitted-with-wheels, you take to the roads to reach your destination.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Though we could, let us go no further
&lt;/h2&gt;

&lt;p&gt;I will end the story there, though we have only just begun.  We could talk about network resiliency, reliability built on top of unreliability and security built on top of insecurity we will not.  I will also not discuss highway rules, traffic lights and taxis.  But you get the idea.&lt;/p&gt;

&lt;p&gt;Let us instead marvel at the the brilliance of division and specialization of labor.&lt;/p&gt;

</description>
      <category>launchschool</category>
      <category>theinternet</category>
    </item>
    <item>
      <title>Spaced Repetition Studying with Anki</title>
      <dc:creator>Martin Graham</dc:creator>
      <pubDate>Mon, 24 Jan 2022 21:15:34 +0000</pubDate>
      <link>https://forem.com/martinandersongraham/spaced-repetition-studying-with-anki-3d4</link>
      <guid>https://forem.com/martinandersongraham/spaced-repetition-studying-with-anki-3d4</guid>
      <description>&lt;h1&gt;
  
  
  My brand new study tool - spaced repetition with Anki
&lt;/h1&gt;

&lt;p&gt;I just completed my second assessment at &lt;a href="//launchschool.com"&gt;LaunchSchool&lt;/a&gt; and thought I would take a moment to highlight a study tool I was introduced to during the prepwork - &lt;em&gt;spaced repetition studying&lt;/em&gt; using &lt;a href="https://apps.ankiweb.net/"&gt;Anki&lt;/a&gt;.  For clarification, Anki is an open-source implementation of the SRS technique - I'm not familiar with any other implementations but there are several other popular ones.  Based on the most popular shared decks the two most common users are language learners and medical students - however I think this technique could be useful to anyone.&lt;/p&gt;

&lt;p&gt;The goal of SRS?  Help you memorize information.  A lot of information.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;em&gt;spaced repetition study&lt;/em&gt; (SRS)?
&lt;/h2&gt;

&lt;p&gt;Think flashcards.  Except computerized - &lt;em&gt;ooh...aah&lt;/em&gt;.  Flashcards that you can add images to. Flash cards that you add audio to.  Flash cards that can blank out phrases and then fill them in.  Flash cards where you can go to sites and download collections of thousands of high-quality cards that other people made.&lt;/p&gt;

&lt;p&gt;Sounds like a real revolution of the paradigm so far?  Well we haven't actually gotten to the SRS part!  &lt;em&gt;Spaced repetition study&lt;/em&gt; is at heart an algorithm that gives an answer to the question &lt;em&gt;when do I need to review this card next?&lt;/em&gt;  If you ponder for a moment you may come up with the answer &lt;em&gt;right before I forget the card&lt;/em&gt;.  Wouldn't it be great if you had an app that would show you a flashcard five minutes before you forget it?&lt;/p&gt;

&lt;p&gt;Well, mind-reading is perhaps not within our grasp.  However forgetting curves are pretty well studied - these are functions that generally model how large a gap between reviews of a piece of information are allowed before the information is forgotten. Crucially, these gaps widen with each repetition.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jIunTaS_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nybgqhovthv9p3d7bhrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jIunTaS_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nybgqhovthv9p3d7bhrz.png" alt="The forgetting curve" width="449" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The upshot is that cards are reviewed, and each review is pushed further into the future.  However, the card should come up again before you forget the information, and thus your gradually widening review is locking that information into your memory.&lt;/p&gt;

&lt;p&gt;It should be noted that SRS is a memory technique, not a learning technique.  In order to work properly you really need to have learned and understood the information first.  For instance, the flashcards aren't so good for learning a poem from scratch, but once you have it memorized the subsequent reviews will help you retain the information.&lt;/p&gt;

&lt;p&gt;For those that want a little more technical analysis &lt;a href="https://www.gwern.net/Spaced-repetition"&gt;this article&lt;/a&gt; gives a great outline of the studies that have been done on SRS.  I especially like her analysis on how you decide which pieces of information to make cards for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like in practice
&lt;/h2&gt;

&lt;p&gt;Here is an example of a card I used when studying OOP in JavaScript - &lt;br&gt;
&lt;strong&gt;Front:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BLDfUdIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgl7yydqc4ulwn8tj91e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BLDfUdIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgl7yydqc4ulwn8tj91e.png" alt="The front of a review card" width="761" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Back:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z7H3lazf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fanqwq1ddp3d2gulw1i8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z7H3lazf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fanqwq1ddp3d2gulw1i8.png" alt="The back of a review card" width="880" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key lies in the options revealed after clicking 'show answer'. These buttons will set how long the gap until the card is reviewed again.  Each time you see a card these numbers increase - I have some cards that are up to several months!&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zr_hweiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qxft1t2ecn14bez5f132.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zr_hweiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qxft1t2ecn14bez5f132.png" alt="Timing options after answering" width="502" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result of the review spacing I only review a small subset of my cards daily - and if you don't add new cards the daily review total falls over time.  The blue numbers represent how many new cards to review in a deck, and the green how many review cards.  I have heard the upper-end of users have 10,000+ cards, yet they review 200 or so a day.  Here we see the advantage SRS has over traditional flashcards - more efficient use of review times means larger decks can be used (or review times decreased).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YVDIXzY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2v7t9a61s05fwp7mml7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YVDIXzY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2v7t9a61s05fwp7mml7e.png" alt="A list of cards to be reviewed today" width="492" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My tip for beginners - use cloze deletion
&lt;/h2&gt;

&lt;p&gt;On a lark I &lt;a href="https://ankiweb.net/shared/decks/"&gt;downloaded a deck&lt;/a&gt; of US Capitals that my wife and I review daily (I've always thought I need to learn my capitals better).  Recently I decided to update these cards into &lt;em&gt;cloze deletion&lt;/em&gt; cards - these have natural fill in the blanks.&lt;/p&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X5J5BBh3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uym7wvf1adcv7jkffy3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X5J5BBh3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uym7wvf1adcv7jkffy3r.png" alt="A non-cloze card" width="507" height="127"&gt;&lt;/a&gt;&lt;br&gt;
After:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KM8H41J8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rjl8zbbiia4uwdx2atij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KM8H41J8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rjl8zbbiia4uwdx2atij.png" alt="A cloze card" width="397" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cloze cards are much more naturally to look at, and you can cloze out any part you want - you can even have multiple parts hidden and revealed together!  Overall they are much better than the basic cards.&lt;/p&gt;

&lt;p&gt;Each card actually has two cloze deletions, and Anki automatically makes two review notes (one with each deletion), which is handy.&lt;/p&gt;

&lt;h2&gt;
  
  
  In the classroom
&lt;/h2&gt;

&lt;p&gt;I've been thinking for a bit that SRS would actually be really beneficial for the high school students I teach - one of the real issues I encounter if poor information retention by my students.  Expecting my students to create and review decks daily is a big ask, so I opted for a different approach - Anki warmups.&lt;/p&gt;

&lt;p&gt;I've created a review deck for each class, and I have set the number of cards fairly low (only 3 new cards and 10 max cards per day).  Each day we start class by reviewing cards, and I'm planning on keeping the review intervals on the shorter side.  I'm only one week into this, but I'm very optimistic on the benefit so far.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mi3BYtka--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/exn42dgyvst6z768w30l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mi3BYtka--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/exn42dgyvst6z768w30l.png" alt="A card for my physics class" width="516" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Interestingly enough I got a marketing email (the sort I ignore dozens of daily) from a startup wanting to make SRS software targeting the classroom.  I actually think this could be brilliant - teacher shared/controlled decks and a dashboard of information about student reviews would be a game-changer for school use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;A few thoughts about getting started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before starting you should understand that commitment and discipline are required for this method.  You could &lt;em&gt;maybe&lt;/em&gt; review every other day - daily is best however.  Skip a week and many cards pile up - so you procrastinate - so more cards pile up - and now you aren't using the method at all.&lt;/li&gt;
&lt;li&gt;Head on over to &lt;a href="https://apps.ankiweb.net/"&gt;AnkiWeb&lt;/a&gt; to browse tutorial and create an AnkiWeb account (or find an alternative you like)&lt;/li&gt;
&lt;li&gt;There are mobile apps for &lt;a href="https://itunes.apple.com/us/app/ankimobile-flashcards/id373493387"&gt;iOS&lt;/a&gt; and &lt;a href="https://play.google.com/store/apps/details?id=com.ichi2.anki"&gt;Android&lt;/a&gt;.  The iOS app costs $24.99 - if that seems like a lot to you, consider that the &lt;a href="https://www.raptitude.com/2022/01/everything-must-be-paid-for-twice/"&gt;time commitment&lt;/a&gt; is much more costly.  Most users say the app is easily worth the cost.&lt;/li&gt;
&lt;li&gt;If you are the sort, give &lt;a href="https://reddit.com/r/anki"&gt;r/anki&lt;/a&gt; a browse&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>launchschool</category>
      <category>anki</category>
    </item>
    <item>
      <title>A subtle error I made with constructors</title>
      <dc:creator>Martin Graham</dc:creator>
      <pubDate>Thu, 30 Dec 2021 22:48:44 +0000</pubDate>
      <link>https://forem.com/martinandersongraham/a-subtle-error-i-made-with-constructors-3kc7</link>
      <guid>https://forem.com/martinandersongraham/a-subtle-error-i-made-with-constructors-3kc7</guid>
      <description>&lt;h2&gt;
  
  
  In which I almost didn't notice a mistake
&lt;/h2&gt;

&lt;p&gt;I was able to track down a subtle but important error I was making when using constructors with sub-classes and manually setting prototypes.&lt;/p&gt;

&lt;p&gt;Consider the following code (from an implementation of rock-paper-scissors):&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;function&lt;/span&gt; &lt;span class="nf"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;(){&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;move&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="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setMove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;move&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HumanPlayer&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;HumanPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;player1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HumanPlayer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;player2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HumanPlayer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;player1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paper&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;player1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;player2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//paper null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the error ended up not being a major issue here, notice where the move property of player1 and player2 is initially stored - the object referenced by &lt;code&gt;HumanPlayer.prototype&lt;/code&gt; - and this object is shared by all &lt;code&gt;HumanPlayer&lt;/code&gt; objects!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2r4l4a12j1hldd5bipyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2r4l4a12j1hldd5bipyh.png" alt="The prototypal relationships"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both players access their &lt;code&gt;move&lt;/code&gt; property from &lt;code&gt;Human.prototype&lt;/code&gt; - meaning they share &lt;code&gt;this.move&lt;/code&gt;!  Let's confirm this by checking the value of &lt;code&gt;move&lt;/code&gt; using &lt;code&gt;getPrototypeOf()&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;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;player1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;move&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//null&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;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paper&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;player1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//paper&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only does &lt;code&gt;player1&lt;/code&gt; not have an own property move, setting &lt;code&gt;player2.[[Prototype]].move&lt;/code&gt; to &lt;code&gt;paper&lt;/code&gt; is accessed by &lt;code&gt;player1.move&lt;/code&gt;!  We don't actually have &lt;code&gt;move&lt;/code&gt; defined as individual state for each instance of &lt;code&gt;HumanPlayer&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Oddly enough, the program worked fine - consider the &lt;code&gt;setMove()&lt;/code&gt; function:&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;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setMove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;move&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mv&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;When invoking this function using &lt;code&gt;player1.setMove('paper')&lt;/code&gt;, &lt;code&gt;this&lt;/code&gt; refers to player1.  Since player1 doesn't have an own property &lt;code&gt;move&lt;/code&gt;, one is created!  Each player calls &lt;code&gt;setMove()&lt;/code&gt;, each now has their own &lt;code&gt;move&lt;/code&gt; property, and the &lt;code&gt;move&lt;/code&gt; on &lt;code&gt;HumanPlayer.prototype&lt;/code&gt; is never used again.&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;player1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;player2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paper&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;player1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;player2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//rock paper&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We got lucky - this time.  How to properly fix 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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;(){&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;move&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HumanPlayer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;HumanPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;player1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HumanPlayer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;player2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HumanPlayer&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;player1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;move&lt;/span&gt;&lt;span class="dl"&gt;'&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;Focus on the &lt;code&gt;HumanPlayer&lt;/code&gt; constructor - we've added a call to the &lt;code&gt;Player&lt;/code&gt; constructor.  Now creating a new HumanPlayer invokes the Player constructor, (using the context of the object first created due to &lt;code&gt;new&lt;/code&gt;), and sets the &lt;code&gt;move&lt;/code&gt; property on this object.  Now each player has their own properties.  All is well with the world.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>oop</category>
      <category>launchschool</category>
    </item>
    <item>
      <title>Learning about OOP in JavaScript</title>
      <dc:creator>Martin Graham</dc:creator>
      <pubDate>Thu, 30 Dec 2021 20:44:25 +0000</pubDate>
      <link>https://forem.com/martinandersongraham/learning-about-oop-in-javascript-5gj6</link>
      <guid>https://forem.com/martinandersongraham/learning-about-oop-in-javascript-5gj6</guid>
      <description>&lt;h2&gt;
  
  
  In which I make a resolution to blog
&lt;/h2&gt;

&lt;p&gt;I am one class into my &lt;a href="//www.launchschool.com"&gt;LaunchSchool&lt;/a&gt; experience, and so far it living up to my expectations.  Coming from a 'jack-of-all-trades-one-person-IT-department' at my small school, LaunchSchool seems to be offering some much needed polish to my technical background.&lt;/p&gt;

&lt;h2&gt;
  
  
  JS-120 - Or How I Learned To Stop Worrying and Love OOP
&lt;/h2&gt;

&lt;p&gt;Consider learning about OOP in JavaScript - definitely some ideas that I'm used to, but also some new twists.  Props to LaunchSchool's mastery method - if I had a hazy understanding of object references then prototypes would be straight out.&lt;/p&gt;

&lt;p&gt;So for today, a brief summary of the OOP patterns (did I mention I'm an amateur - if you are reading this for information...maybe go elsewhere)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Constructor functions&lt;/li&gt;
&lt;li&gt;OLOO - (objects linking other objects)&lt;/li&gt;
&lt;li&gt;ES6 classes&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Constructor functions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;new&lt;/code&gt; keyword is crucial - our constructor function won't actually return anything, but invoking with &lt;code&gt;new&lt;/code&gt; causes the creation of a new object (and it is set as the execution context - i.e. &lt;code&gt;this&lt;/code&gt; within the constructor), and the implicit return of the new object - also &lt;code&gt;Car.prototype&lt;/code&gt; is assigned to the &lt;code&gt;[[Prototype]]&lt;/code&gt; property of our new object.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  OLOO - Objects Linked to Other Objects
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;CarPrototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;drive&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;let&lt;/span&gt; &lt;span class="nx"&gt;car1&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="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CarPrototype&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we make a prototype object and use &lt;code&gt;Object.create()&lt;/code&gt; to set up the prototypal relationship - the conventional &lt;code&gt;init&lt;/code&gt; method is used to set initial properties easily.  Notice how &lt;code&gt;init&lt;/code&gt; returns &lt;code&gt;this&lt;/code&gt; - absolutely necessary for method chaining to work.&lt;/p&gt;

&lt;h3&gt;
  
  
  ES6 classes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;drive&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;let&lt;/span&gt; &lt;span class="nx"&gt;myCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coming from my dabbling in Java and Python, this is the pattern I am naturally drawn to.  Note the &lt;code&gt;constructor&lt;/code&gt; method - invoked with the use of &lt;code&gt;new&lt;/code&gt;, and will be important when subclassing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remaining questions I have, in no particular order
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Is one pattern generally used?&lt;/li&gt;
&lt;li&gt;What are the gotcha's for each method - (for instance, subclassing with constructor functions seems to have some quirks)?&lt;/li&gt;
&lt;/ol&gt;

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