<?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: James Walsh</title>
    <description>The latest articles on DEV Community by James Walsh (@jameswalshdev).</description>
    <link>https://dev.to/jameswalshdev</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%2F218982%2F6421352c-0156-4ad1-919d-e5684755524e.jpg</url>
      <title>DEV Community: James Walsh</title>
      <link>https://dev.to/jameswalshdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jameswalshdev"/>
    <language>en</language>
    <item>
      <title>PNPM has both Yarn &amp; NPM beat.</title>
      <dc:creator>James Walsh</dc:creator>
      <pubDate>Fri, 07 Jul 2023 19:12:04 +0000</pubDate>
      <link>https://dev.to/jameswalshdev/pnpm-has-both-yarn-npm-beat-1fge</link>
      <guid>https://dev.to/jameswalshdev/pnpm-has-both-yarn-npm-beat-1fge</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;One of the biggest complaints you'll hear about the Javascript ecosystem is the &lt;em&gt;tendency of the community to reinvent the wheel&lt;/em&gt;. Admittedly, while I find this to be one of the biggest &lt;strong&gt;strengths&lt;/strong&gt; of the community, the shade thrown our way is not completely unwarranted. I think this is most succinctly proven by the fact that at the time of writing this article we have &lt;strong&gt;&lt;em&gt;3 package managers&lt;/em&gt;&lt;/strong&gt;. In any other language or runtime, this would be unheard of. And our package management isn't our worst offender. Right now by my accounting, there are 5-7 popular ways to build &amp;amp; transpile JS/TS so that it can run on a server or in the browser. Compare this setup to most other languages, where you just use &lt;em&gt;the language's compiler,&lt;/em&gt; and we can maybe start to understand why our ecosystem can sometimes be justifiably on the end of some jokes.&lt;/p&gt;

&lt;h2&gt;
  
  
  History Lesson: Yarn vs NPM
&lt;/h2&gt;

&lt;p&gt;At the same time, the competition in our ecosystem is unrivaled, and it consistently pushed us forward. There is no doubt that Yarn gaining popularity led to many big enhancements to NPM, including simple things we now take for granted.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;For instance, you can thank the yarn team for the fact that NPM has a lock file. Yarn launched with a lock file out of the box with high praise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Yarn also invented the idea of a workspace, which forced NPM to support workspaces too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/#toc-why-would-you-want-to-do-this"&gt;Yarn resolutions&lt;/a&gt; helped get developers out of security jams when dependabot wasn't enough.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of these tools are industry standards, and we have the yarn team to thank for the pressure to get them into their current state. My point is that &lt;strong&gt;&lt;em&gt;this competition is a good thing&lt;/em&gt;&lt;/strong&gt; , and developers having a choice counts for something.&lt;/p&gt;

&lt;p&gt;I hope that if you're using NPM or Yarn you'll install pnpm and give it a fair run. Yes, they reinvented the wheel. Again. But I think they did it justice. I've made the switch to pnpm painlessly, and I'm not looking back anytime soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes PNPM Different?
&lt;/h2&gt;

&lt;p&gt;All of this information is readily available in &lt;a href="https://pnpm.io/motivation"&gt;PNPM's Motivation White Paper&lt;/a&gt;. Here is the &lt;strong&gt;&lt;em&gt;TLDR;&lt;/em&gt;&lt;/strong&gt; so that you can make quick decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problems with Flat Node Modules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Both yarn classic &amp;amp; npm hoist all dependencies, including dependencies of dependencies to the root of the &lt;code&gt;node_modules&lt;/code&gt; directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is slow, and can sometimes create problems with resolutions that take up time as dependency graphs resolve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PNPM only installs the specified dependencies in your &lt;code&gt;package.json&lt;/code&gt; to the &lt;code&gt;node_modules&lt;/code&gt; directory. All "dependencies of dependencies" are symlinked from the &lt;strong&gt;content addressable store&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Content Addressable Store
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;When using npm, if you have 100 projects using a dependency, you will have 100 copies of that dependency saved on disk. With pnpm, the dependency will be stored in a content-addressable store&lt;/p&gt;

&lt;p&gt;All the files are saved in a single place on the disk. When packages are installed, their files are hard-linked from that single place, consuming no additional disk space. This allows you to share dependencies of the same version across projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Saving disk space is becoming increasingly relevant. In a world where we ever increasingly rely on GitHub Actions, GitLab pipelines, and other CI/CD vendors, this benefit can make a real world difference in your development flow. Since most of our web applications &amp;amp; services are running inside docker containers &lt;em&gt;(or abstractions around docker containers)&lt;/em&gt; these disk space wins will also convert to time and money saved as our pipelines flow code into customer's hands. And this benefit costs nothing since &lt;strong&gt;&lt;em&gt;PNPM is built on top of NPM and has compatibility with its CLI&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Symlinked Node Modules
&lt;/h3&gt;

&lt;p&gt;In the last section, we talked about symlinking dependencies from the content addressable store. And I'd like to focus on why that's powerful. Check out this super common use case outlined in the white paper.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you depend on different versions of the dependency, only the files that differ are added to the store. For instance, if it has 100 files, and a new version has a change in only one of those files, &lt;code&gt;pnpm update&lt;/code&gt; will only add 1 new file to the store, instead of cloning the entire dependency just for the singular change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is fundamentally no different than how frontend engineers handle caching HTTP requests to improve SPA performance. Intelligent caching works hand in hand with improving your normal development flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nice Features To Know About
&lt;/h2&gt;

&lt;h3&gt;
  
  
  You Can Get Rid of NVM
&lt;/h3&gt;

&lt;p&gt;Thats right. You can completely uninstall tools like NVM or FNM and have pnpm manage which NodeJS version youre on. Here are some steps to test this out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You'll want to uninstall both npm and node globally from whatever mechanism you used to install them. Be it &lt;code&gt;nvm&lt;/code&gt;, &lt;code&gt;brew&lt;/code&gt;, &lt;code&gt;choco&lt;/code&gt; or some other means.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, you'll want to install pnpm using &lt;a href="https://pnpm.io/installation"&gt;the pnpm install scripts&lt;/a&gt; mentioned in their documentation. On POSIX machines like Mac &amp;amp; Linux you can run the following:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you have a clean fresh machine with pnpm installed, use the &lt;code&gt;env&lt;/code&gt; command to install the latest LTS version of &lt;code&gt;node&lt;/code&gt; :&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   pnpm env use --global lts

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;To make sure everything is installed correctly use the following:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;6.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   pnpm env ls

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;To double-check that your global node version is managed by pnpm directly run:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;8.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   which node

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

&lt;/div&gt;



&lt;p&gt;The output should be something like &lt;code&gt;/&amp;lt;your-home-directory&amp;gt;/Library/pnpm/node&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you ever want to change your node version as you would normally with NVM you can use the same command mentioned in step 5. In this example pin our global node version to &lt;code&gt;18.16.1&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  PNPM is Fast
&lt;/h3&gt;

&lt;p&gt;At the end of the day, this is the feature that will make or break a package manager in my opinion. &lt;em&gt;The only real job of a package manager is to deliver your dependencies from a registry in an efficient way&lt;/em&gt;. Rest assured that &lt;strong&gt;pnpm is fast&lt;/strong&gt;. Plain and simple. Check out this link to &lt;a href="https://pnpm.io/benchmarks"&gt;openly maintained benchmarks&lt;/a&gt; by the Yarn / Meta team. They run every 4 hours and are administered against two use cases; a fresh Nextjs install and a fresh Gatsby install. The Yarn team broadcasts the performance honestly, even when yarn isn't always the clear winner &lt;em&gt;(which has been the case up until recently)&lt;/em&gt;. While I think it's important to let people read benchmarks and decide for themselves on interpretation, one small caveat I'd like to add here is that yarn's performance metrics come with a small catch. Most people right now are using yarn classic. At the time of this writing, the non-classic version of yarn still makes up a huge minority of yarn installs. While its performance looks promising, a more fair comparison of how people are using package managers in the real world would be to compare npm, pnpm, and yarn classic.&lt;/p&gt;

&lt;p&gt;While I'm beyond happy with pnpm's performance &lt;em&gt;(and think it speaks for itself)&lt;/em&gt;, I'll add that recently the performance wins between pnpm, npm, and yarn are all beginning to reach a plateau. This is a good thing for the entire NodeJS ecosystem. But after careful consideration of the benchmarks you can rest assured that not only will pnpm not slow you down, but in common everyday use cases will speed you up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package Manager Interoperability
&lt;/h2&gt;

&lt;p&gt;PNPM seems to play nicely with &lt;code&gt;corepack&lt;/code&gt;. If you haven't heard about &lt;code&gt;corepack&lt;/code&gt; don't worry, I'm still in the dark here too. At the time of this writing, corepack feels promising but still painful and early.&lt;/p&gt;

&lt;p&gt;Corepack seems to promise to unlock some level of interoperability between package managers. If you want more information on this, &lt;a href="https://blog.shalvah.me/posts/why-arent-node-js-package-managers-interoperable#corepack"&gt;Shalvah has a great blog post going more in depth&lt;/a&gt;. Using &lt;code&gt;corepack&lt;/code&gt; to specify your package manager is sort of the opposite of using &lt;code&gt;pnpm env&lt;/code&gt;. Instead of having &lt;code&gt;pnpm&lt;/code&gt; manage your node version, &lt;strong&gt;&lt;em&gt;node would manage all your different package management tools&lt;/em&gt;&lt;/strong&gt; for interoperability. There are trade-offs to this approach, and Shalvah goes into more detail about what they are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;So you can ditch using node version manager, benefit from the full power of the content addressable store, and every time you run &lt;code&gt;pnpm install&lt;/code&gt; you're gonna sleep easy at night knowing no meaningful amount of your day will be spent waiting for dependencies installation to finish. PNPM deserves your attention, I know it will continue to have mine.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Next.js - A React starter kit you can stick with</title>
      <dc:creator>James Walsh</dc:creator>
      <pubDate>Mon, 18 Jan 2021 18:34:33 +0000</pubDate>
      <link>https://dev.to/jameswalshdev/next-js-a-react-starter-kit-you-can-stick-with-ln0</link>
      <guid>https://dev.to/jameswalshdev/next-js-a-react-starter-kit-you-can-stick-with-ln0</guid>
      <description>&lt;p&gt;I've tried just about all the popular react starter kits.  In 2016 the first npm package I ever installed to begin learning react was &lt;code&gt;create-react-app&lt;/code&gt;. After ejecting the package my first time, I then quickly moved on to creating my own custom react starter kit, but quickly realized I had no intention of maintaining it. From there I built toy projects using Gatsby, react-redux-starter-kit,  and the list goes on.&lt;/p&gt;

&lt;p&gt;While I could compare Next.js to both Gatsby and Create React App, for brevity and showcasing its power today I'm choosing to pick on Create React App (CRA).&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking on CRA
&lt;/h2&gt;

&lt;p&gt;I've never used create-react-app without eventually needing to run "eject". When you do, you're met with a consortium of various configurations for webpack, babel, eslint, jest, and other tools, many of which you are not sure if you'll need. But this process leaves me feeling somewhat afraid about what is okay to remove. Once you do run "eject" you are completely on your own. So you get the choice between having a project which has one dependency, &lt;code&gt;create-react-app&lt;/code&gt; which will conceal the bloat. Or owning all of the dependencies it conceals and managing the bloat yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/R54jhpzpARmVy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/R54jhpzpARmVy/giphy.gif" alt="Angry face" width="320" height="194"&gt;&lt;/a&gt;&lt;br&gt;
This process often leads me to throw my hands up in the air and saying "well fine, I'll just make my own simple webpack config for this small project I'm working on". CRA is inherently opinionated. I should be clear, I don't think that's necessarily a bad thing &lt;em&gt;(especially if you're just barely getting into React and need to hit the ground running quickly)&lt;/em&gt;. If you like the out of the box tooling CRA ships with then you should have pretty smooth sailing. &lt;/p&gt;

&lt;h2&gt;
  
  
  My Needs
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;For context, I decided to revamp my portfolio site. I wanted to do this quickly, in a week or less. It didn't make sense to tinker with client configs for days on end getting things "just perfect" only to discover once my project was out in the wild that it was sorely unoptimized. So a bootstrapper was needed and made sense.&lt;/li&gt;
&lt;li&gt;I wanted a starter kit that was testing agnostic. Jest is great and has come a long way over the last few years, but I still prefer to use something on top of Jest like &lt;code&gt;react-testing-library&lt;/code&gt;, paired with some smokescreen e2e tests written in Cypress. Because of this need, I would prefer to manage the test setup code completely on my own.&lt;/li&gt;
&lt;li&gt;I wanted a lot of control over the client-side libraries I chose to use and needed something flexible.&lt;/li&gt;
&lt;li&gt;Typescript. I love TS what more can I say. While CRA &lt;em&gt;does&lt;/em&gt; include support for Typescript, the support isn't the best. You have to initialize CRA with a custom template command. Afterward, CRA then attempts to use Babel and Typescript together, which has some interesting side effects, like for example, no enum or namespace support.&lt;/li&gt;
&lt;li&gt;I don't want to ever have to worry about being involved with a process like "ejecting". I want a client-side starter kit that will shallowly allow for me to disagree on some things, and use my own customizations for things one would expect.&lt;/li&gt;
&lt;li&gt;For most of my side projects, like my portfolio site, a completely separate server written in Express, GraphQL, etc is just way overkill. Some level of serverside support goes a &lt;strong&gt;long way&lt;/strong&gt; for a project like this, so I can write some simple light-weight API endpoints as a cherry on top.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Enter Next.js
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The first magical moment with Next.js was the second I wanted to add Typescript to the project. The Next.js philosophy is "no config needed". And that's what they try and do. Stay out of your way while you build. I followed the short setup guide for TS, and it was one of those apple moments where "it just worked ™". I didn't have to worry about what webpack was doing under the hood, or concern myself with any constraints on Typescript &lt;em&gt;(like enums and namespaces not working in CRA)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The second magic moment was how Next.js handled clientside routing. The &lt;code&gt;next/Link&lt;/code&gt; component can be used anywhere and will handle any and all internal linking that you want to do. React components placed in the &lt;code&gt;/pages&lt;/code&gt; directory are automatically registered as a route based on the naming convention of the file. Non-page components &lt;em&gt;(like reusable, shared components)&lt;/em&gt; can be placed outside of the &lt;code&gt;/pages&lt;/code&gt; directory in a directory of your choice to avoid exposing them as a route.&lt;/li&gt;
&lt;li&gt;The API layer. Inside of the &lt;code&gt;/pages/api&lt;/code&gt; directory Next.js includes support for writing your own thin Next endpoints. In my case, a paper-thin client API was all I needed so this worked great. As the project grows they have support for adding custom middlewares, following the express/koa-like syntax of using function callbacks that contain a &lt;code&gt;(request, response, next)&lt;/code&gt; argument convention. In addition, there is no need to worry about cross-origin requests as the same server which serves up the client also serves up the client API. Vercel also owns the &lt;a href="https://www.npmjs.com/package/swr"&gt;SWR&lt;/a&gt; package, which they recommend pairing with the Client API. SWR follows the &lt;code&gt;stale-while-revalidate&lt;/code&gt; cache invalidation strategy through easy to use react hooks which assist in client request caching.&lt;/li&gt;
&lt;li&gt;The areas where Next lacks in opinion was refreshing. I threw together my own testing suite and didn't have to worry about magical test frameworks behind the scenes stepping on my toes. I began adding font libs, animation libs, prettier, eslint.&lt;/li&gt;
&lt;li&gt;Secret sharing. Next.js has a built-in mechanism for sharing secrets. It's a fairly standard procedure here. Environment variables specified in a &lt;code&gt;.env.local&lt;/code&gt; are attached to &lt;code&gt;process.env&lt;/code&gt; and can be used on both the client/server in that manner.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When You Need To Go Beyond
&lt;/h2&gt;

&lt;p&gt;Vercel seems to understand that eventually you may just wanna dip out from their defaults and try your own thing.  When that happens, rather than "ejecting" from next, you can specify some of the traditional build flows in a webpack config through using the &lt;code&gt;next.config.js&lt;/code&gt; file. Vercel's docs include examples of swapping out the defaulted CSS Modules setup with JSS, or Sass, as well as adding PostCSS support and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;I won't go too deep on all of the benefits Next.js promises. But there is a whole slew of features that Vercel has packed in here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-rendering components leads to better performance and SEO.&lt;/li&gt;
&lt;li&gt;Fast Refresh feels like webpack hot-reloading decided to start taking performance enhancement drugs.&lt;/li&gt;
&lt;li&gt;Image serving/caching is a really fantastic experience using the &lt;code&gt;next/Image&lt;/code&gt; component.&lt;/li&gt;
&lt;li&gt;Vercel's deployment platform was built specifically for paired use with Next.js, and has a really compelling free tier. The two when used together provided yet another "magic moment" for me.&lt;/li&gt;
&lt;li&gt;To learn more I recommend looking at [Why Next.js].(&lt;a href="https://nextjs.org/"&gt;https://nextjs.org/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Caveats &amp;amp; Dislikes
&lt;/h2&gt;

&lt;p&gt;While I believe Next.js is a great tool for my needs, no npm package ever deployed is a silver bullet. There are some downsides, and admittedly a few strong opinions that Next.js has.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JSS&lt;/strong&gt;. Next ships with default support for CSS Modules. While there is nothing stopping you from going your own way,  there is one technical constraint put on using JSS. Namely that you cannot use it in server-side components. Decisions like this do push the codebase toward the direction of using CSS Modules and being okay with it. Ultimately this tradeoff didn't impact me, but that may not be the case for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TS Config&lt;/strong&gt;, if you change it, Next.JS will just re-generate the config back to what it's expecting. This isn't all the way bad though, as the standard TS Config is pretty flexible for most project needs. I wanted to make my compiler a bit more strict, and that was where I started running into issues. There are workarounds &lt;em&gt;(like using good eslint rules which TS plugins)&lt;/em&gt;. I ended up using the following which I was happy with:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"airbnb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:cypress/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:react/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:react/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"prettier/@typescript-eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:prettier/recommended"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;I've never moved faster on a side project than when I picked up Next.js. It got me out of the boilerplate and into writing the more interesting parts of my codebase fast. The package was able to do this in such a way that I still felt like I was in control and never had to worry about any process like "ejecting". I'm completely won over, and moving forward I would have to look for good reasons not to use Next.js on any new front end project that comes my way.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Tenets of Functional Programming</title>
      <dc:creator>James Walsh</dc:creator>
      <pubDate>Tue, 01 Dec 2020 02:58:44 +0000</pubDate>
      <link>https://dev.to/jameswalshdev/tenets-of-functional-programming-a-beginner-s-guide-1594</link>
      <guid>https://dev.to/jameswalshdev/tenets-of-functional-programming-a-beginner-s-guide-1594</guid>
      <description>&lt;p&gt;Over the last year, I've experimented with a handful of different programming languages. Some of these have been functional &lt;em&gt;(which I will refer to as FP)&lt;/em&gt;, some object-oriented, and most of which are hybrid languages. A few days ago I asked myself the question, if I were first being introduced to FP concepts today, what would I want to know first? The following is my response to that question.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, Some FP Wins 💙
&lt;/h2&gt;

&lt;p&gt;I'm going to make four claims that I'll back up later. So here's the elevator pitch on why embracing FP concepts is going to make you as happy as a dog eating a hot dog.&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%2Fi%2Fotgxgaqezbzfk8el4wj4.gif" 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%2Fi%2Fotgxgaqezbzfk8el4wj4.gif" alt="Alt Text" width="274" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By adhering to these tenets I believe you will win:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Testability&lt;/li&gt;
&lt;li&gt;Refactorability&lt;/li&gt;
&lt;li&gt;Readability&lt;/li&gt;
&lt;li&gt;Better Control Flow&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Next, Some Baby Steps 🐣
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"James, what makes a language an FP language, OOP language, or a hybrid language?"&lt;/em&gt; I'll try to make this clear as mud by illustrating some language features from technologies I've explored.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions as a First-Class Citizen
&lt;/h3&gt;

&lt;p&gt;All popular programming languages have support for functions. But not all of them have &lt;strong&gt;first-class&lt;/strong&gt; support for functions. So what exactly does it mean for a function to be "first-class?". &lt;/p&gt;

&lt;p&gt;Here are some simple rules for you to suss that out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Functions can be declared at the top level.&lt;/li&gt;
&lt;li&gt;Functions can be assigned as values to variables.&lt;/li&gt;
&lt;li&gt;A function may accept another function as a parameter.&lt;/li&gt;
&lt;li&gt;You may declare nested functions within functions &lt;em&gt;(turtles all the way down)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The language allows you to "compose", or arrange smaller functions into larger functions.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;While FP patterns &lt;em&gt;DO exist&lt;/em&gt; in the languages below, functions are treated as 2nd class citizens. With that in mind let's eliminate them as a thought exercise.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C# (OOP)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;We have the ability to assign functions to variables, and pass functions to other functions &lt;em&gt;(using anonymous methods, LINQ, etc)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;But&lt;/strong&gt; only within the scope of a method inside of a class inside of a namespace. So while some functional patterns exist, functions are not "first-class".&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruby (OOP):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Similar to C#, lambda expressions &lt;em&gt;(anonymous functions)&lt;/em&gt; exist. These can be defined inline and assigned as a value to a variable.&lt;/li&gt;
&lt;li&gt;You can declare methods within methods (function nesting)&lt;/li&gt;
&lt;li&gt;But ultimately whatever is being defined must exist within the scope of a class and its methods. Functions cannot exist on their own.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JS (Hybrid):&lt;/strong&gt; You can declare functions, objects, and classes at the topmost level. Functions can be assigned as values to other variables and accepted as parameters. Function nesting is also allowed. But there is a fascinating little quirk about JS that isn't immediately recognized.

&lt;ul&gt;
&lt;li&gt;In your browser devtools run the JS code &lt;code&gt;(function(){}).constructor&lt;/code&gt;. Did you catch it? Every JS function is actually just a &lt;code&gt;Function&lt;/code&gt; &lt;strong&gt;&lt;em&gt;object&lt;/em&gt;&lt;/strong&gt;. Function itself is not the base type.&lt;/li&gt;
&lt;li&gt;That's right, at the end of the day you are actually constructing JS objects when you declare new functions. This has led many engineers to say "JS is actually Object-Oriented".&lt;/li&gt;
&lt;li&gt;While I think there is merit to the statement above, because these Function objects behave like traditional functions, pass every check in the first-class citizen test, and the language does not enforce the same strict namespacing/class encapsulation strictness in other OOP languages, I sit firmly in the "hybrid language" camp.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scala (Hybrid):&lt;/strong&gt; In Scala it's the same story as JS, but with a slightly different flavor.

&lt;ul&gt;
&lt;li&gt;Every function is a value. Functions may be nested. Functions may be declared at the top level and passed as parameters. For brevity, the first-class test is met.&lt;/li&gt;
&lt;li&gt;However, types and behaviors in Scala are defined by classes, traits, sub-classes, mixins, and all those other mechanisms you've come to expect from an OOP language.&lt;/li&gt;
&lt;li&gt;As you can see in Scala, similar to JS, they leave things completely up to you how deeply you decide to take one approach.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elixir (Strict FP):&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;functions are first-class citizens.&lt;/li&gt;
&lt;li&gt;Functions actually replace classes &amp;amp; objects as the root level data type.&lt;/li&gt;
&lt;li&gt;No support for classical inheritance but instead, expect you to use something called "&lt;strong&gt;Function Composition&lt;/strong&gt;" to achieve similar goals.&lt;/li&gt;
&lt;li&gt;Functions may be treated as values, but when you inspect under the hood you won't find an "object" type being used ephemerally.&lt;/li&gt;
&lt;li&gt;No support for popping back into OOP Land when you want to use traditional dependency injection, inheritance, or class instantiation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After reading this blog post, I don't expect you to run off and convert your Ruby project to Elixir. In fact, the opposite. I wanted to introduce the idea that most modern tech stacks have sprinkles of FP across their language features. As we jump into the meat of these tenets I hope you can find something that applies to you wherever you're working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tenet 1: Higher-Order Functions 🧗
&lt;/h2&gt;

&lt;p&gt;If you have experience with React you've probably heard the term "we favor composition over inheritance". What's being described here isn't just a React best practice, it's the first Tenet of FP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Imperative VS Declarative Programming
&lt;/h3&gt;

&lt;p&gt;In classical OOP, shared functionality &amp;amp; state is often defined in classes that can be inherited. The Dog class may inherit from the Canine class which defines useful universal methods like &lt;code&gt;Run()&lt;/code&gt;, &lt;code&gt;Bark()&lt;/code&gt;, &lt;code&gt;Pant()&lt;/code&gt;. You can write something like &lt;code&gt;Dog extends Canine&lt;/code&gt; and some level of base functionality &amp;amp; state management will be inherited. This type of thinking is referred to as &lt;strong&gt;"imperative"&lt;/strong&gt; thinking.&lt;br&gt;
In the following article, &lt;a href="https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2"&gt;CodeBurst Declarative vs Imperative Programming&lt;/a&gt;, the bit of knowledge to glean is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Imperative programming&lt;/strong&gt; is a programming paradigm that uses statements that change a program’s state.&lt;br&gt;
&lt;strong&gt;Declarative programming&lt;/strong&gt; is a programming paradigm that expresses the logic of a computation without describing its control flow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In functional programming, developers prefer "declarative" thinking. Functions aren't concerned about when they are called or by whom they are called, and aren't concerned about the program state.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Where an imperative approach may look like: &lt;code&gt;new Dog().Bark()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The declarative approach may look more like: &lt;code&gt;bark(() =&amp;gt; dog)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The bark function isn't really concerned about &lt;strong&gt;who&lt;/strong&gt; is barking &lt;strong&gt;when&lt;/strong&gt; they are barking during program execution, or why. It's only a function that takes in another function as a parameter, and barks on whatever the return value of that function parameter is. What you may have already realized is that we just inadvertently composed our first function.&lt;/p&gt;
&lt;h3&gt;
  
  
  Function Composition 🎼
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Function composition is the process of combining two or more functions to produce a new function. Composing functions together is like snapping together a series of pipes for our data to flow through.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or to illustrate the point differently, I like to think of function composition in similar terms to music composition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Musical notes simply exist, much like functions. But it is up to the composer to arrange the notes in their proper order to make up a song.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To go back to the Dog example, &lt;code&gt;bark()&lt;/code&gt;, &lt;code&gt;run()&lt;/code&gt;, &lt;code&gt;bite()&lt;/code&gt; are all arranged as individual pieces. They can be arranged in any order. You may arrange &lt;strong&gt;(compose)&lt;/strong&gt; them so that a dog runs up to someone, barks at them, and then bites them, but you may also "compose" these functions in any number of interesting ways. It may not be a dog that bites the user, but it may actually be &lt;code&gt;biteUser(() =&amp;gt; cat)&lt;/code&gt;. In this case, &lt;code&gt;biteUser&lt;/code&gt; is the &lt;em&gt;Higher-Order Function&lt;/em&gt; which takes in the entity that is doing the biting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt; 🧪: You can imagine how using these higher-order functions allow for a pretty great testing experience. &lt;code&gt;biteUser()&lt;/code&gt; can be tested in isolation, as can &lt;code&gt;dog()&lt;/code&gt;. Later on, you can write an additional unit or integration test to figure out what happens when these functions are composed together in different ways.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control Flow&lt;/strong&gt; ⚙️: You can imagine how we might change the order of bite, run, etc. That is because &lt;em&gt;what&lt;/em&gt; is now separated from &lt;em&gt;when&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Tenet 2: Function Purity 😇 &lt;em&gt;(Side Effects)&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;What makes a function pure? There is a simple test you can run to determine if a function is "pure" or "impure".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A function is considered pure if given the same input it always produces the same output&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To illustrate this point:&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;// pure&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addTwoNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// impure&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getRandomNumberWithMax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;maxNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;maxNumber&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;ul&gt;
&lt;li&gt;If we run &lt;code&gt;addTwoNumbers(2, 4)&lt;/code&gt; we will &lt;strong&gt;always&lt;/strong&gt; get 6.&lt;/li&gt;
&lt;li&gt;If we run &lt;code&gt;getRandomNumberWithMax(10)&lt;/code&gt; we might sometimes get the same output, but very rarely.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Side Effects 💥
&lt;/h3&gt;

&lt;p&gt;It's obvious that using &lt;code&gt;Math.random&lt;/code&gt; would make for an impure function. But in the real world, there are usually &lt;em&gt;really good reasons&lt;/em&gt; why our functions might not produce the same output.&lt;/p&gt;

&lt;p&gt;That reason is side effects. &lt;strong&gt;Side effects are things that happen outside your function or local environment that you cannot control including&lt;/strong&gt;:&lt;br&gt;
    - Referencing the global state&lt;br&gt;
    - Updating a record in the database&lt;br&gt;
    - Making an external HTTP request&lt;br&gt;
    - Querying the DOM&lt;br&gt;
    - Logging to the file system&lt;/p&gt;

&lt;p&gt;The first time I was exposed to this idea, I threw my hands up in the air and said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"So any time any real work needs to be done, I have a side effect, so what's the point?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think it's important to understand that the goal isn't to eliminate all side effects or to shame yourself when you write an impure function. But rather to think about testing, flow control, and encapsulation.&lt;/p&gt;

&lt;p&gt;Thinking about things this way leads to questions like: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How can I encapsulate side effects so that they don't' trickle out across the entire codebase".&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  Practicing Side Effect Forgiveness
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;In many cases we can use composition to inject side effects through function parameters rather than declaring them inline in the function body. This helps keep the function pure and side effect free.&lt;/li&gt;
&lt;li&gt;There is nothing wrong with a properly encapsulated side-effect producing function. As long as we keep striving to isolate our side effects to just a few spots instead of everywhere.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Tenet 3: Immutability 💾
&lt;/h2&gt;

&lt;p&gt;Immutability is pretty straight forward to understand but has some powerful ramifications. Immutability simply put is defined as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Data that may not be mutated, only copied&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this works, however, this var can be changed later on&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myMutableString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;James Walsh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// first change 😭&lt;/span&gt;
&lt;span class="nx"&gt;myMutableString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; is a really cool guy!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;changeString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// second change&lt;/span&gt;
  &lt;span class="nx"&gt;myMutableString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;something entirely different&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;immutableString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;James Walsh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Throws the error Uncaught TypeError: Assignment to constant variable.&lt;/span&gt;
&lt;span class="nx"&gt;immutableString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;J. Walsh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;That's pretty much it. Because we strive to have side-effect-free &amp;amp; "stateless functions", when we need to change data we copy the data first, then modify it. This achieves function purity by eliminating the temptation to modify a state outside of the function's direct scope.&lt;/li&gt;
&lt;li&gt;In redux, immutability enables features like "time-travel" debugging that allows you to see how data is changing as each function manipulates a given data set.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tenet 4: Referential Transparency 🧮
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"If a function references another function, it may be swapped out with that function's implementation and will still return the same result."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When we work with immutable data and pure functions, we gain referential transparency. We can substitute out a function call with the function body and nothing should change.&lt;/p&gt;

&lt;p&gt;Consider this simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;num2&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;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Same result is produced in many different ways with referential transparency&lt;/span&gt;

&lt;span class="c1"&gt;// Ex 1: Using function references&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// Ex 2: Replace function references with values that are function references&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Ex 2: Replace values with add function refs, with the function implementation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Ex 3: Replace divide function ref with the function implementation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;
&lt;span class="c1"&gt;// Ex 4: Replace all references with pure single line implementation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;No matter which implementation or reference we substituted, the value of the result will always be &lt;code&gt;0.66&lt;/code&gt; (repeating).&lt;/li&gt;
&lt;li&gt;Referential transparency delivers on the promise of being able to refactor, as well as write comprehensive tests where you can use test data in your test case, or mock functions which return appropriate test data, without fear that results will look wildly different in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tenet 5: Functors ⚡️
&lt;/h2&gt;

&lt;p&gt;Now that you have a good foundation, we can learn about Functors which are going to give you an insane amount of readability with tons of expressiveness. Functors are the primary way we are going to modify any immutable data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functor Definitions
&lt;/h3&gt;

&lt;p&gt;So what is a functor? Ask any developer and I guarantee they will each give you a different answer. So in order to cover my bases, I'm going to give you a few different definitions to work with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;A functor is a set of values arranged in a shape that can be mapped over &lt;strong&gt;(or changed)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A functor is a collection that can be passed a function and apply it non-destructively to all of its elements, returning another functor.&lt;/li&gt;
&lt;li&gt;Functions or Objects which have implemented &lt;code&gt;.map&lt;/code&gt; or variation of &lt;code&gt;map&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Little confused? You're not alone. Let's take a look at an example you may already be using. Let's explore the JavaScript &lt;code&gt;Array.map&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario
&lt;/h3&gt;

&lt;p&gt;Let's say our user is an animal shelter that wants to be able to provide a new pet owner with a list of the &lt;em&gt;names&lt;/em&gt; of all the cats that are &lt;em&gt;female&lt;/em&gt; that don't have &lt;em&gt;long hair&lt;/em&gt;. They'd also like this list sorted by kitties that are used to being &lt;em&gt;indoors&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here is our data set:&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;cats&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;Tony&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;coat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isIndoorCat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;Tinkerbell&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;coat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isIndoorCat&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;Whiskers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;coat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isIndoorCat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;Snickers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;coat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isIndoorCat&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;Nala&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;coat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isIndoorCat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;Selina&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;coat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isIndoorCat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;Gusto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;coat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isIndoorCat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Imperative Code 🤮
&lt;/h4&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;catsToShow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;//mutatable state we can reference from inside our loop&lt;/span&gt;
  &lt;span class="k"&gt;for &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;cat&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;cats&lt;/span&gt;&lt;span class="p"&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coat&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isIndoorCat&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="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;catsToShow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// sort indoor first&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isIndoorCat&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="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;catsToShow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// sort outdoor last&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="k"&gt;for &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;cat&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;catsToShow&lt;/span&gt;&lt;span class="p"&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// only display the names&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's wrong with this code?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We're mutating a lot of state.&lt;/li&gt;
&lt;li&gt;Control flow is hard to keep track of.&lt;/li&gt;
&lt;li&gt;We can't reason about one part of our requirements without reasoning about the whole of the program.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's see how Functors can make simple tasks much easier to look at and think about.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Functors (Round 1)
&lt;/h4&gt;

&lt;p&gt;Now since Array is a functor it returns &lt;em&gt;(itself)&lt;/em&gt; another functor.&lt;br&gt;
The Array Functor provides a few useful methods that perform mappings.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;.filter()&lt;/code&gt; which takes a function as a parameter that returns a truthy value to specify which items in the collection should be included in the new Functor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.map()&lt;/code&gt; which takes a function as a parameter that returns a new &lt;em&gt;copied and changed&lt;/em&gt; version of index in the collection which will be included in the new Functor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.sort()&lt;/code&gt; which takes a function that's return value specifies the sort order of the items returned by the new Functor.
&lt;/li&gt;
&lt;/ol&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;filteredCats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coat&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&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;sortedCats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filteredCats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isIndoorCat&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;namesOfCats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedCats&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;cat&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;namesOfCats&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isn't that a little easier on the eyes?&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Functors (Round 2)
&lt;/h4&gt;

&lt;p&gt;We can simplify this further.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Functors always return a new Functor, so we can use function chaining to pipe outputs to new functors as inputs.&lt;/li&gt;
&lt;li&gt;Let's also add some syntax sugar that lots of popular languages support including implicit function returns, &amp;amp; removing function braces.
&lt;/li&gt;
&lt;/ol&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cats&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coat&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isIndoorCat&lt;/span&gt;&lt;span class="p"&gt;)&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;cat&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Function Composition&lt;/strong&gt; &lt;em&gt;(Higher Order Functions which compose other functions)&lt;/em&gt; help us achieve things we'd achieve through Inheritance but with the advantage of achieving some sweet de-coupling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure Functions&lt;/strong&gt; help us increase our code predictability, testing, simplicity, and force us to think about how to properly encapsulate volatile parts of the codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Immutability&lt;/strong&gt; helps us achieve function purity through "copying data first" before changing state. And also helps enable us to practice time travel debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referential Transparency&lt;/strong&gt; helps us mock data during testing, refactor our code with confidence, and structure our code in flexible ways.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Functors&lt;/strong&gt; help us change immutable data with ease, usually end up shortening the amount of code we need to write, and further help us de-couple control flow.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Extra Credit: Monads, Memoization, Currying, Recursion
&lt;/h2&gt;

&lt;p&gt;I view the 5 tenets above as a good way to begin exploring FP concepts. But you will find that they serve as a good baseline to explore more interesting behaviors.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exploring Functors will eventually lead you to Monads &lt;em&gt;(which are a type of functor which makes working with side effects easier)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Composition will lend itself well to function currying&lt;/li&gt;
&lt;li&gt;Function Purity can lead to memoization which has the potential to offer system performance and tuning wins.&lt;/li&gt;
&lt;li&gt;Recursion is useful when performing data branching logic, but use cases outside of that may be on the rarer side.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>functional</category>
      <category>javascript</category>
      <category>fpvsoop</category>
    </item>
    <item>
      <title>From BootCamp to College</title>
      <dc:creator>James Walsh</dc:creator>
      <pubDate>Wed, 10 Jun 2020 23:00:17 +0000</pubDate>
      <link>https://dev.to/jameswalshdev/from-bootcamp-to-college-43on</link>
      <guid>https://dev.to/jameswalshdev/from-bootcamp-to-college-43on</guid>
      <description>&lt;p&gt;At the time of writing, I am 26 years old.&lt;br&gt;
I'm a college drop out.&lt;br&gt;
I’m a boot camp grad.&lt;br&gt;
I've been working as a software engineer for 5+ years full time.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I adore my career in software development.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’m beyond happy with how everything has panned out and the success I’ve personally felt. I love this field.&lt;/p&gt;

&lt;p&gt;Now time to queue the click bait. &lt;em&gt;&lt;strong&gt;As of a week ago I’ve committed to going back to school to finish my CS education&lt;/strong&gt;&lt;/em&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  A Moment of Caution
&lt;/h2&gt;

&lt;p&gt;I'd like to spend some time explaining how I got here. But before I do I'll start by painting a picture around my current, unfiltered worldview:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I do not believe a Bachelors Degree in Computer Science is a requirement for becoming an excellent, productive software engineer who can write clean code and deliver value to the business. &lt;em&gt;(Especially if you already have a degree that would be considered complementary toward a transition into tech)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;I do not believe that all boot camps adequately prepare their students for the onslaught of responsibility that is about to be thrown their way. I do not believe bootcamps are a shortcut or a replacement for college. &lt;em&gt;&lt;strong&gt;However&lt;/strong&gt;&lt;/em&gt; I do believe that bootcamps are &lt;em&gt;a more capitalistic approach to education that allows you the freedom to take your learning and accountability toward success into your own hands&lt;/em&gt;. I also believe boot camps do a better job than colleges at teaching you "how to teach yourself".&lt;/li&gt;
&lt;li&gt;No one really knows what they are doing. We are all trying to learn from each other. There is no 1 size fits all solution to starting your career. I don't believe my experience will be true for everyone. The following is not a recommendation. Just a cautionary tale about how I arrived here.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Boot Camp
&lt;/h2&gt;

&lt;p&gt;From time to time I've heard friends, family members, colleagues, and acquaintances ask about my boot camp cohort with sincere desire for understanding. I've personally felt whether perceived or projected a plethora of responses both positive and negative toward pursuing the bootcamp life. I've sensed that some have felt some level of envy &lt;em&gt;(esp after a 4 year investment at a large institution)&lt;/em&gt;. While others have may have expressed in some sense an understanding that fresh bootcamp grads may not be as qualified as their graduate counterpart. Others yet may take a more middle of the road approach and feel that each candidate is expressly unique and dig at their true qualifications.&lt;/p&gt;

&lt;p&gt;The truth is all are correct.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Pros of Bootcamps
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Personally, I do not regret breaking into the industry as young and as unskilled as I was &lt;em&gt;(Barely 21 and with only a basic understanding of JS and a tiny bit of Ruby on Rails)&lt;/em&gt;. I was able to get an entry level web developer position with no debt, and one semester's worth of really hard work. Do I regret that? No.&lt;/li&gt;
&lt;li&gt;I'm confident in my ability to teach myself and ask questions of mentors when I find gaps. Boot camps are fundamentally all about this. They give you some direction then send you off to fail on your own. Afterward they expect you to come back with answers, or questions that will get you closer to the truth. This style is much more applied and hands on which jives my personal style.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons of Bootcamps
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Despite the praise I've given above&lt;/em&gt;, and even years later I still find myself occasionally plagued by knowledge gaps and imposter syndrome. And each time I've felt that imposter syndrome. I've been able to alleviate it through self lead education. &lt;em&gt;Which sometimes leaves me puzzled as to what I actually paid for when most everyone knows how to google.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Even if you find success with a bootcamp you will still be required to pursue the right books, the correct mentors, and most importantly of all learning on the job. In my case by being able to write code with experienced devs on healthy teams was crucial. My coworkers helped foster my skillset and grow talent organically outside the classroom.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bootcamps are unregulated. No two bootcamps are created equal&lt;/strong&gt;. In my conversations with other bootcamp grads our education varied from cohort to cohort, company to company, and even instructor to instructor. The truth is some people are just going to luck out with their instruction and some people aren't. I don't like to admit it, but I played the lottery and happened to win. My experience was better than others.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What left me with an overall positive impression of boot camps was that my cohort left me with strong basic fundamentals to build upon later. Fast forward to day and I owe my current skillset not to the bootcamp, but rather to my coworkers who mentored me, the business problems that we're thrown at me, and the companies that were willing to take a chance and invest on me. Did the boot camp help kick start all of that? Absolutely. And fast as hell.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Failings of Modern Education
&lt;/h2&gt;

&lt;p&gt;So what's the answer then? Here I've gone giving a mixed review on boot camps. But do I feel any better about colleges? Generally speaking no. Modern education has failed us. It's expensive. It's hard. You are required to learn things that are not applicable to the job you will have. Modern testing has proven to be a terrible indicator of knowledge retention and job preparedness.&lt;/p&gt;

&lt;p&gt;So if I feel as strongly as I do about why #CollegeSucks what would cause me to re-enter the educational cog as I approach my late 20s?&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter WGU &amp;amp; Targeted Self Paced Education
&lt;/h2&gt;

&lt;p&gt;Full disclosure. &lt;strong&gt;This is not a plug for WGU specifically, but rather the underlying principle&lt;/strong&gt;. This is not an endorsement and I'm not being paid by the University. There are many other programs similar to this one across the country that mimic these principles. But I do think WGU is a great working example of what to do and how colleges can better adapt to a changing generation with different demands.&lt;/p&gt;

&lt;p&gt;Because I have the job experience that I have WGU will allow me to potentially do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Before starting a course, student's are given the ability to take what is called a "Pre-Assessment". The pre-assessment tells you which areas of the curriculum you can skip, vs which areas of the course you need to study hard at. These pre-assessments are all about the student proving that they understand the concepts. If however, you pass the Pre-Assessment with flying colors, the course final is unlocked for you immediately allowing you to complete the class in record time &lt;em&gt;(In my case this is useful as some of the more basic programming courses I would intend to fly past as quickly as possible)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ditching the idea of traditional semesters in leu of &lt;em&gt;self paced education&lt;/em&gt;, moderated at the individual level. At WGU students are responsible for their workload. You come up with your own incremental schedule rather than be beholden to the traditional college semester paradigm. You take as many or as little classes as you can manage within a given time period, and go at a self-paced cadence to complete courses you've started. &lt;strong&gt;It may take 1 year, it may take 3 years. You decide&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;And most importantly...&lt;/em&gt; Getting rid of the fluff &amp;amp; busy work. WGU helps students work towards super targeted Bachelors &amp;amp; Masters programs only. There are no needless generalized courses. All courses listed on their SD program are cohesive &amp;amp; work directly toward my major of choice &lt;em&gt;(in my case BS in Software Development)&lt;/em&gt;. For example, take the math credit that is required for this diploma.&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;
  
  
  Ex: Math Credit (Applied Algebra)
&lt;/h5&gt;

&lt;blockquote&gt;
&lt;p&gt;Applied Algebra is designed to help candidates develop competence in working with functions, working with the algebra of functions, and using some applied properties of functions...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It doesn't make sense for me at this point in my career to be taking intro algebra classes, nor advanced calculus. However, one could make the argument that &lt;em&gt;programming languages are fundamentally just applied algebra&lt;/em&gt;. When I saw the syllabus this clicked for me. Each course credit is working toward me, not needlessly against me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I do believe programs similar to this one pose a healthy middle of the road solution to CS education&lt;/strong&gt;. Coding Bootcamps that promise that in 12 short weeks they will take you from zero to hero are just plain false. Conversely spending 4 years of your life and potentially many thousands of dollars on outdated principles and high level theory before joining the workforce seems excessive at best, and totally unreasonable at worst.&lt;/p&gt;

&lt;p&gt;Our education system is broken. But I do think things are changing for the better. And I intend to be the guinea pig.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loose Opinions Loosely Held
&lt;/h2&gt;

&lt;p&gt;The decision to go back does not come from a desire for career growth. Most employers support the concept of learning on the job. Especially where our tech stacks and tooling are every changing month by month and year by year. If you are a boot camp grad who has found success, please don't think my argument is for you to pursue higher education. It isn't.&lt;/p&gt;

&lt;p&gt;What it all boils down to is this... &lt;strong&gt;In the last 5+ years my love for computer science has grown to a point that furthering my education is the logical next step&lt;/strong&gt;. I feel a drive to harness deeper knowledge about how computation works. It fascinates me, it frustrates me, and it continues to humble me.&lt;/p&gt;

&lt;p&gt;I want to learn more. I want to be more. I feel that I can take this deeper. I’ve justified not going back on a physical, mental, spiritual, and monetary level &lt;em&gt;(and just maybe I'll be proven right in that justification)&lt;/em&gt;. But when it comes down to it this is just something I feel I’ve left undone.&lt;/p&gt;

&lt;p&gt;So what's the answer? Boot camp or college? Ask me in 2 years and I'll let you know.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A Mac Guy’s Guide to Windows Development</title>
      <dc:creator>James Walsh</dc:creator>
      <pubDate>Thu, 29 Aug 2019 01:40:03 +0000</pubDate>
      <link>https://dev.to/jameswalshdev/the-mac-guy-guide-to-windows-development-4m5c</link>
      <guid>https://dev.to/jameswalshdev/the-mac-guy-guide-to-windows-development-4m5c</guid>
      <description>&lt;p&gt;I've been writing NodeJS on a 2016 Macbook Pro since well... &lt;em&gt;2016&lt;/em&gt;. And the experience has been gr8. Except for one small problem....&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gJOUdiw9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.iskysoft.com/images/blog/11.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gJOUdiw9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.iskysoft.com/images/blog/11.jpg" alt=" Gaming on A Mac" width="650" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am an avid PC gamer. And I'm not holding my breath for a "Gaming Macbook Air" to come out any time soon... Beyond that, I also love building PCs. I know each and every component in my gaming rig because I hand picked everything. There is a certain craftsmanship aspect to it that has always intrigued me.&lt;/p&gt;

&lt;p&gt;When I come home at the end of the day and need some time to decompress 2 things come to mind. Do I want to pwn N00bs, or work on side projects? Depending on my answer I'll be on entirely different hardware, which &lt;strong&gt;SUCKS&lt;/strong&gt;. So for &lt;em&gt;years&lt;/em&gt; I've been trying to make my experience at home with gaming &amp;amp; writing Node just a bit smoother.&lt;/p&gt;

&lt;p&gt;The fact remains that beyond gaming there may be many reasons why you are interested in moving to Windows. This is my journey 🚀.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alpha Solution: "Cordy McCord Face"
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sy0TeX06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blogs.synopsys.com/tousbornottousb/files/2016/12/Dongle-Hell.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sy0TeX06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blogs.synopsys.com/tousbornottousb/files/2016/12/Dongle-Hell.jpg" alt="Dongle Hell" width="464" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The alpha solution is one I'm pretty sure many reading this article already do or know... I call this solution &lt;em&gt;"Cordy McCord Face"&lt;/em&gt;. What you do is buy a nice laptop stand, a display switcher, and a USB hub that connects to a central keyboard and mouse. That way you can dock your MacBook, press 3 buttons total &lt;em&gt;(switch display, switch USB, power on device)&lt;/em&gt; and BOOM. Now you're cooking with avocado oil, and can 👏 "seamlessly" 👏 switch 👏 between 👏 your 👏 gaming 👏 rig 👏 and 👏 mac.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cordy McCord Face Problems
&lt;/h4&gt;

&lt;p&gt;If you like to re-arrange your office, ever move, have the ports on your laptop change, or have lots of dongles... it can just be a huge pain. Cable management also sucks if you need to have your office look "clean".&lt;/p&gt;

&lt;h2&gt;
  
  
  The Beta Solution: Dual Boot
&lt;/h2&gt;

&lt;p&gt;Dual boot Ubuntu &lt;em&gt;(or some other distro)&lt;/em&gt;. The thing that makes NodeJS development so great on Mac is because Linux &amp;amp; Mac are so closely related. After all, MacOS &lt;em&gt;is&lt;/em&gt; Unix based. I love using tools like &lt;code&gt;zsh&lt;/code&gt;, and most of the dependencies I need for app development are available via &lt;code&gt;homebrew&lt;/code&gt; or a simple &lt;code&gt;apt-get&lt;/code&gt;. So I felt like I would feel right at home on Ubuntu.&lt;/p&gt;

&lt;h4&gt;
  
  
  Dual Boot Problems
&lt;/h4&gt;

&lt;p&gt;Let's face it. No matter &lt;em&gt;how good&lt;/em&gt; the Linux desktop environment is getting, &lt;strong&gt;it will never be as polished as Mac &amp;amp; Windows&lt;/strong&gt;. Maybe that will change some day. I hope so. I personally ran into an obscure issue with Grub, where it would reset my Ubuntu OS instance to a fresh install whenever I switched between operating systems. Ugh... I'm sure there was a solution. But I dont &lt;em&gt;want&lt;/em&gt; to spend time debugging those things. Those are issues I know I will never have on Windows or Mac. And if I'm going to write code on my PC the development experience needs to be &lt;em&gt;just as good as Mac&lt;/em&gt; otherwise I know I won't do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Going All In On Windows
&lt;/h2&gt;

&lt;p&gt;For me to go all in on Windows I needed a few things to happen.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I needed to be able to use&lt;code&gt;bash&lt;/code&gt;, or even more preferable: &lt;code&gt;zsh&lt;/code&gt; with &lt;code&gt;oh-my-zsh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I needed all of my editor settings to seamlessly transfer over.&lt;/li&gt;
&lt;li&gt;I needed Node through &lt;em&gt;&lt;a href="https://github.com/nvm-sh/nvm"&gt;Node Version Manager&lt;/a&gt;&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;I needed Yarn for package management.&lt;/li&gt;
&lt;li&gt;I needed Docker.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Shell
&lt;/h3&gt;

&lt;p&gt;The best part about going all in on Windows, is that I actually bypassed Windows all together. My development environment is totally isolated from my gaming environment.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the &lt;a href="https://www.microsoft.com/en-us/p/ubuntu/9nblggh4msv6?activetab=pivot:overviewtab"&gt;Ubuntu app&lt;/a&gt; from the Windows Store. Once this install is complete, you will have the &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10"&gt;Windows Subsystem for Linux&lt;/a&gt; running on your PC. &lt;em&gt;(WSL also supports a handful of other distros, I just prefer Ubuntu)&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PVH0vFR4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/65bnmr86xziuut0wyndw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PVH0vFR4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/65bnmr86xziuut0wyndw.png" alt="WSL Distro Choices" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the new &lt;a href="https://www.youtube.com/watch?v=8gw0rXPMMPE"&gt;Windows Terminal app&lt;/a&gt; from the Windows Store.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YVk2UEH8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/hylwd64ekvc7rexbhmbb.png" alt="Windows Terminal App" width="800" height="416"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The new terminal app is &lt;strong&gt;sleek&lt;/strong&gt;. It's minimal, it stays out of the way, it actually supports re-sizing &lt;em&gt;(cough cough command prompt)&lt;/em&gt;, and here's the best part... If you have WSL installed it has automatic support for WSL. Just open a new WSL tab and &lt;em&gt;boom&lt;/em&gt;. You're running Linux bois. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Drops Mic.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note that the Terminal app is still in Preview. I haven't had any issues with it as of 08-28-2019.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;From there the rest was history. I could fly free. I followed the Ubuntu specific guides for installing docker, git, yarn, node version manager, and all my other dependencies. &lt;code&gt;sudo apt-get&lt;/code&gt; worked great with no hiccups. I tried to find things to poke at, but in my personal experience things worked exactly the way they did when I was using the terminal in Ubuntu natively.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Editor
&lt;/h3&gt;

&lt;p&gt;I use VS Code. But I had so many small details configured just the way I wanted on Mac that I didn't want to have to setup again.&lt;/p&gt;

&lt;p&gt;I discovered a handy extension in the marketplace called &lt;a href="https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync"&gt;Settings Sync&lt;/a&gt; that has worked wonders.&lt;/p&gt;

&lt;p&gt;Because all settings in VS Code eventually become some sort of &lt;code&gt;json&lt;/code&gt; object. What Setting Sync does is save your VS Code Settings to a Github Gist. You can then push settings up to a gist and pull settings down to a new editor instance on a different machine. It's a thing of beauty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential "Gotchas" 😳
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;If you're coming from Mac/Ubuntu then all of your line endings are &lt;code&gt;LF&lt;/code&gt;. VS Code uses &lt;code&gt;CLRF&lt;/code&gt; on Windows by default. You will want to make sure you go user settings and set &lt;code&gt;files.eol: 'lf'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;code&lt;/code&gt; command works great inside of WSL. If you are using Webstorm, or a different IDE, it can be a bit tricky to setup commands in your path to be able to open up the IDE from the command line.&lt;/li&gt;
&lt;li&gt;You may want to set up symlinks from &lt;code&gt;/mnt/c/**&lt;/code&gt; -&amp;gt; your User directory in Windows so that you can find your files inside of the File Explorer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Use WSL&lt;/li&gt;
&lt;li&gt;Use the new Windows Terminal App&lt;/li&gt;
&lt;li&gt;Use VSCode.&lt;/li&gt;
&lt;li&gt;Switch between gaming &amp;amp; coding like an absolute bad ass.&lt;/li&gt;
&lt;li&gt;Profit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I had such a great experience switching to this setup that I was even able to generate a &lt;a href="https://jameswalsh.tech"&gt;super small portfolio site&lt;/a&gt; completely in windows with my Mac tightly closed in my backpack. I took plenty of Overwatch breaks because for the first time... &lt;em&gt;I could&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>linux</category>
      <category>ubuntu</category>
      <category>vscode</category>
    </item>
  </channel>
</rss>
