<?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: Hunter Miller</title>
    <description>The latest articles on Forem by Hunter Miller (@arthyn).</description>
    <link>https://forem.com/arthyn</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%2F31030%2F8ad6babd-aa41-4527-8e3e-e75b27f8e1b9.jpg</url>
      <title>Forem: Hunter Miller</title>
      <link>https://forem.com/arthyn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/arthyn"/>
    <language>en</language>
    <item>
      <title>What Can You Do with Tailwind 2?</title>
      <dc:creator>Hunter Miller</dc:creator>
      <pubDate>Tue, 24 Nov 2020 16:26:29 +0000</pubDate>
      <link>https://forem.com/thisdotmedia/what-can-you-do-with-tailwind-2-6jo</link>
      <guid>https://forem.com/thisdotmedia/what-can-you-do-with-tailwind-2-6jo</guid>
      <description>&lt;p&gt;Tailwind CSS finally announced it's new 2.0 version on November 18th, 2020. &lt;/p&gt;

&lt;p&gt;If you've been around the industry lately, you've probably heard of Tailwind CSS, because they seem to be everywhere! But maybe you haven't, and in that case, it's time for a short introduction. If you have, skip to 2.0 Features&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro to Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;Something that started out as some handcrafted CSS used personally by &lt;a href="https://adamwathan.me" rel="noopener noreferrer"&gt;Adam Wathan&lt;/a&gt; became an extremely popular, productivity-boosting CSS framework used by millions over the last three years. The core mindset behind Tailwind is that CSS should be composed of small single-purpose utility classes which pull from a standard set of values.&lt;/p&gt;

&lt;p&gt;At first you may think, "This seems like inline styles, why would I want to bloat my markup and aren't those bad anyway?", and while your statement about inline styles is correct, Tailwind's utility classes aren't that at all. Here's why:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By sticking with only classes, styles all stay at the same specificity.&lt;/li&gt;
&lt;li&gt;By using classes instead of inline styles, we encourage reuse and ensure that we're sticking to a standard set of values.&lt;/li&gt;
&lt;li&gt;While our markup may be larger than those who use other CSS methodologies, we always know exactly what styles are coming from our classes because there is a 1-to-1 mapping.&lt;/li&gt;
&lt;li&gt;The breadth of utility classes allows us to write 95-100% of our CSS using just utilities. This encourages a small footprint and very little maintenance overhead.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are other benefits like increased authoring speed and others that I'd like to cover in a more thorough post later. &lt;/p&gt;

&lt;p&gt;In case you're wondering, what does this look like? Here's an example component from Tailwind's homepage:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.tailwindcss.com/l9ALzKSRFV" rel="noopener noreferrer"&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%2Fi%2Fcmieck1gqbwjsqap4biq.png" alt="Example component on Tailwind Play"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you've gotten a short introduction, let's get back to why we're here.&lt;/p&gt;

&lt;h2&gt;
  
  
  2.0 Features
&lt;/h2&gt;

&lt;p&gt;Since this is a major version, it needed a major launch which included not only a &lt;a href="https://twitter.com/tailwindcss/status/1326963053200543744" rel="noopener noreferrer"&gt;teaser&lt;/a&gt; and &lt;a href="https://twitter.com/tailwindcss/status/1329129585024372741" rel="noopener noreferrer"&gt;trailer&lt;/a&gt;, but also a whole new &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;website&lt;/a&gt; and &lt;a href="https://tailwindcss.com/docs" rel="noopener noreferrer"&gt;docs&lt;/a&gt;! If this isn't maximalist launching, I don't know what is! Let's see the most exciting changes, with a few examples that you couldn't make without customizing version 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  Theming and Design
&lt;/h3&gt;

&lt;p&gt;I don't think it would be a major version launch if Tailwind didn't touch these two topics because they are the main pillars of why we use Tailwind in the first place. They didn't just touch these though, they brought big changes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Colors
&lt;/h4&gt;

&lt;p&gt;With regards to theming and design, the biggest of change is colors. The Tailwind team created an all new color palette which includes 17 colors and 5 grays. &lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/zojzzdop0fzx/1uMqHZ3QRxZFJXCVhEFxYg/f422d9f1cbf86d4341bed1402eed9637/colors.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/zojzzdop0fzx/1uMqHZ3QRxZFJXCVhEFxYg/f422d9f1cbf86d4341bed1402eed9637/colors.png" alt="Tailwind 2.0 Color Palette"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a huge jump in expressiveness for designs, especially with alternate grays because the old gray was on the cool side. The new sets add two cooler grays and two warmer grays so you can have something that jives better with your design's palette.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tailwindcss.com/docs/customizing-colors" rel="noopener noreferrer"&gt;Color docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Dark Mode
&lt;/h4&gt;

&lt;p&gt;Another big change is the new support for dark mode. Tailwind doesn't force one color to another for dark mode, but instead let's you control which colors get applied through the new modifier &lt;code&gt;dark:&lt;/code&gt;. This will apply whatever style follows whenever a &lt;code&gt;.dark&lt;/code&gt; class is above it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tailwindcss.com/docs/dark-mode" rel="noopener noreferrer"&gt;Dark Mode docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  New Breakpoint and Extended Scales
&lt;/h4&gt;

&lt;p&gt;In an effort to support even more refined designs, the team has added support for a larger breakpoint &lt;code&gt;2xl&lt;/code&gt; which now allows more specification for larger layouts. I often added this as a custom breakpoint anyway. &lt;a href="https://tailwindcss.com/docs/breakpoints" rel="noopener noreferrer"&gt;Breakpoint docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They also added extended scales for spacing, typography, and opacity. For spacing, a few half values were added near the bottom for nudging smaller spacing layouts. For typography, a few values were added to the top end for larger hero text. Opacity had the largest set of adds with steps every 10, and a few half steps at the ends. &lt;a href="https://tailwindcss.com/docs/customizing-spacing" rel="noopener noreferrer"&gt;Spacing&lt;/a&gt;, &lt;a href="https://tailwindcss.com/docs/font-size" rel="noopener noreferrer"&gt;typography&lt;/a&gt;, and &lt;a href="https://tailwindcss.com/docs/opacity" rel="noopener noreferrer"&gt;opacity&lt;/a&gt; docs.&lt;/p&gt;

&lt;h4&gt;
  
  
  A Practical Look at New Theming Changes
&lt;/h4&gt;

&lt;p&gt;I've put together a small demo of landing page hero to show off the new changes. Try toggling the &lt;code&gt;dark&lt;/code&gt; class to see dark mode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.tailwindcss.com/fahHWZNDYd" rel="noopener noreferrer"&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%2Fi%2Fxgg1cwewvtwa0epl3v7g.png" alt="Theming example on Tailwind Play"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  New and Extended Utilities
&lt;/h3&gt;

&lt;p&gt;It wouldn't be Tailwind without utilities, and in a major launch like this, we're going to see some new ones. I think both the new forms plugin and &lt;code&gt;ring&lt;/code&gt; utilities are big wins for accessibility, because they encourage good practice. The new colors are sure to help us get good contrast!&lt;/p&gt;

&lt;h4&gt;
  
  
  Forms
&lt;/h4&gt;

&lt;p&gt;Forms have always been a struggle to style. We often resort to hacks and custom implementations with Javascript to be able to make them look good and match our designs. The Tailwind team has worked hard to make standard HTML form inputs able to be styled without custom elements or hacks. There are some limitations here, but I think the result looks great.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tailwindlabs/tailwindcss-forms" rel="noopener noreferrer"&gt;Forms plugin docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Ring
&lt;/h4&gt;

&lt;p&gt;Another issue that we often encounter when auditing the accessibility of our apps is showing clear focus indicators. The default web version of this is accomplished through the &lt;code&gt;outline&lt;/code&gt; property. Unfortunately, &lt;code&gt;outline&lt;/code&gt; ignores &lt;code&gt;border-radius&lt;/code&gt; and isn't quite as customizable as something like &lt;code&gt;box-shadow&lt;/code&gt;. The new &lt;code&gt;ring&lt;/code&gt; utility will use &lt;code&gt;box-shadow&lt;/code&gt; and that will work alongside the standard &lt;code&gt;shadow&lt;/code&gt; utilities in Tailwind without overriding them. Our focus indicators can now look as good as the rest of our UI! 💅&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tailwindcss.com/docs/ring-width" rel="noopener noreferrer"&gt;Ring docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Text Overflow
&lt;/h4&gt;

&lt;p&gt;A small change, but still helpful: you can now specify &lt;code&gt;overflow-ellipsis&lt;/code&gt; and &lt;code&gt;overflow-clip&lt;/code&gt; to control text overflow in a multi-line scenario. &lt;a href="https://tailwindcss.com/docs/text-overflow" rel="noopener noreferrer"&gt;Text-overflow docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Default Line-heights
&lt;/h4&gt;

&lt;p&gt;Something that I feel I'm always tweaking is &lt;code&gt;line-height&lt;/code&gt;. I think good line-heights can make or break type styles. In an effort to help improve the quality of typography in Tailwind, the team has shipped default line-heights for each text size, and like always, you can change that with the &lt;code&gt;leading&lt;/code&gt; utility. &lt;a href="https://tailwindcss.com/docs/font-size" rel="noopener noreferrer"&gt;Font-size docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Practical Example of New Utilities
&lt;/h4&gt;

&lt;p&gt;I've put together a small form component to show off the new utilities:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.tailwindcss.com/COwsvh6vfw" rel="noopener noreferrer"&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%2Fi%2Fb8m9zw4pua9lgjfhfm5y.png" alt="Utilities example on Tailwind Play"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Mechanics Changes
&lt;/h3&gt;

&lt;p&gt;Quite a few internal changes have taken place, one major one being that Tailwind dropped support for IE11 in 2.0. Given that IE11 has very little representation globally and is officially unsupported by Microsoft, I think this was a good move, especially because it allows them to do even more with the framework.&lt;/p&gt;

&lt;p&gt;In addition, &lt;code&gt;@apply&lt;/code&gt; can now work with all variants which is a huge boost to anyone who heavily used it. Previously, you were required to implement those variants as you would normal CSS, but no longer, yay!&lt;/p&gt;

&lt;p&gt;Two things changed with config. You can easily extend variant's by adding an &lt;code&gt;extend&lt;/code&gt; property to your variants config object. This allows you to just add new variants without having to list out all of the default variants which is just a lot nicer. &lt;/p&gt;

&lt;p&gt;The other new thing in config is that we can now set default transition timings and easing functions. This allows us to no longer need to specify a duration or easing function if we're just fine with the default, which is probably 80% of the time for me personally.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tailwindcss.com/docs/functions-and-directives#apply" rel="noopener noreferrer"&gt;@apply&lt;/a&gt;, &lt;a href="https://tailwindcss.com/docs/configuring-variants#enabling-extra-variants" rel="noopener noreferrer"&gt;variant&lt;/a&gt;, and &lt;a href="https://tailwindcss.com/docs/transition-property" rel="noopener noreferrer"&gt;transition&lt;/a&gt; docs&lt;/p&gt;

&lt;h2&gt;
  
  
  The Road to 2.0
&lt;/h2&gt;

&lt;p&gt;Whether you already use Tailwind or you just got converted above, there's a lot to be excited about with version 2.0. A ton of work went into it and it shows in the quality of what was launched. &lt;/p&gt;

&lt;p&gt;Creating and maintaining Tailwind quickly became the work of a small company, unfortunately Adam is only so powerful 🤣. He and Steve Schoger needed extra help which they found this year using funds made from their launch of &lt;a href="https://tailwindui.com/" rel="noopener noreferrer"&gt;TailwindUI&lt;/a&gt; and &lt;a href="https://refactoringui.com/" rel="noopener noreferrer"&gt;RefactoringUI&lt;/a&gt;. They hired &lt;a href="https://twitter.com/bradlc" rel="noopener noreferrer"&gt;Brad Cornes&lt;/a&gt;, &lt;a href="https://twitter.com/malfaitrobin" rel="noopener noreferrer"&gt;Robin Malfait&lt;/a&gt;, and &lt;a href="https://twitter.com/simonswiss" rel="noopener noreferrer"&gt;Simon Vrachliotis&lt;/a&gt; to assist with developing the entire ecosystem that surrounds Tailwind and to push out this new version.&lt;/p&gt;

&lt;p&gt;The team's desires for the new version were deliberated at length over many of Adam's tweets, Github issues/discussions, and even podcast episodes from Adam's very own &lt;a href="https://fullstackradio.com/" rel="noopener noreferrer"&gt;Full Stack Radio&lt;/a&gt;. Something especially important to point out is the team's desire to stick to &lt;a href="https://medium.com/the-non-traditional-developer/semantic-versioning-for-dummies-45c7fe04a1f8" rel="noopener noreferrer"&gt;semantic versioning&lt;/a&gt;. Creating a new version opens up a lot of doors for change which is great, but that door also closes at the same time. Now the Tailwind team has to wait until 3.0 to make changes that will break, but I think they made good calls on what to include in this version.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;If you're as excited as I am, you can head straight to this &lt;a href="https://tailwindcss.com/docs/upgrading-to-v2" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt; to dig through what changes you might need to make in your current Tailwind codebase. If you'd like to hear more straight from the creators themselves head on over to their &lt;a href="https://blog.tailwindcss.com/tailwindcss-v2" rel="noopener noreferrer"&gt;announcement blog post&lt;/a&gt; to get an in-depth look at each change.&lt;/p&gt;

&lt;p&gt;For some of us, it might not be time to change and that's ok. The current version is still a serious piece of craftsmanship with all the same well-thought features. Version 1.9 will be the last update in version one and will retain support for IE11.&lt;/p&gt;

&lt;p&gt;I think Tailwind has proved to be more future-thinking than most frameworks to date including frameworks in other languages. Their attention to detail and quest for excellence shows up in the quality of their work. As a company, they're just getting started. Hopefully the future holds even more new innovations in this lovely little CSS framework, and beyond!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit &lt;a href="https://www.thisdotlabs.com" rel="noopener noreferrer"&gt;thisdotlabs.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This Dot Media is focused on creating an inclusive and educational web for all.  We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit &lt;a href="https://www.thisdot.co" rel="noopener noreferrer"&gt;thisdot.co&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Front-end Practices That Changed My Life</title>
      <dc:creator>Hunter Miller</dc:creator>
      <pubDate>Sat, 25 Apr 2020 20:35:43 +0000</pubDate>
      <link>https://forem.com/arthyn/front-end-practices-that-changed-my-life-56md</link>
      <guid>https://forem.com/arthyn/front-end-practices-that-changed-my-life-56md</guid>
      <description>&lt;p&gt;Hey there! My name is Hunter Miller and I've been developing web software for about 6 years now. Along the way I've taken many paths to produce effective software, some that worked well and some that didn't. I've collected those that I found most influential so that maybe you can get a jump start. Although I've had some success using "larger" patterns I find the smaller ones more powerful and better for overall quality. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;By no means is this an exhaustive list. Also please excuse some of the examples, I had to make most of them up. 😂&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  General
&lt;/h2&gt;

&lt;h3&gt;
  
  
  You're Never Too Far Along to Learn/Relearn the Fundamentals
&lt;/h3&gt;

&lt;p&gt;It's awesome to jump in, start building things, and get something working especially as a beginner. Without learning the fundamentals though, you will often find that you aren't quite sure precisely why something is happening, leading to lots of headaches when trying to fix bugs. The fundamentals help you narrow down what's happening so that you can piece it together. For HTML that means learn the basic tags and when it's appropriate to use them. For CSS that means knowing all the different properties that affect layout and how they interact together. For JS it means knowing what &lt;code&gt;this&lt;/code&gt; is at all times 😂. &lt;/p&gt;

&lt;h3&gt;
  
  
  Prefer the Simplest Tech When Possible
&lt;/h3&gt;

&lt;p&gt;When building web experiences, I try and use HTML first, CSS second, and finally JS if necessary. HTML + CSS can get you really far before you have to reach for JS. It's often simpler and more performant to not have to handle such interactions in JS. &lt;/p&gt;

&lt;h3&gt;
  
  
  Read Documentation and Source Code (Especially MDN for the web)
&lt;/h3&gt;

&lt;p&gt;Documentation and source code are your gateways into learning how things really work. Every time you take the time to read the documentation/source code you gain new little bits that you've never noticed before. There's lots of functionality in the web that you probably don't know. And if you only ever read blogs, tutorials, and Stack Overflow you'll never see the full potential of the tools you are using. It's especially helpful for open source libraries where authors don't always have time to write documentation. This made me a better programmer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility Is Necessary
&lt;/h3&gt;

&lt;p&gt;Without proper accessibility your site will be unusable by those who need to use screen readers, high-contrast text, keyboard navigation, etc. Taking the time to learn the accessibility features of the browser will set you up for success the next time you're trying to create a new experience. I found these people and organizations helped a lot when learning more about accessibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://heydonworks.com/"&gt;Heydon Pickering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laurakalbag.com/"&gt;Laura Kalbag&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://a11yproject.com/checklist/"&gt;A11y Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://simplyaccessible.com/article/listening-web-part-one-thinking-accessibility/"&gt;Simply Accessible&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Learn How the Browser Loads Resources
&lt;/h3&gt;

&lt;p&gt;This one's tricky because browser's aren't always opaque on how they prioritize loading different types of resources. But you can learn a lot about performance from these people and organizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://csswizardry.com/"&gt;CSS Wizardry by Harry Roberts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://varvy.com/pagespeed/"&gt;Varvy by Patrick Sexton&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://timkadlec.com/"&gt;Tim Kadlec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.filamentgroup.com/lab/"&gt;Filament Group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/fast/"&gt;web.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CSS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Atomic or Utility-first CSS
&lt;/h3&gt;

&lt;p&gt;Atomic CSS is a way of structuring your CSS classes which mimics the properties and values available in CSS. At first this sounds pretty crazy. There are tons of properties in CSS and each has multiple or even infinite values, so how could this possibly work? Well, first off you don't actually produce a class for each and every value. For those properties with numerical values, we come up with a standard set to use so that will benefit us the most. &lt;/p&gt;

&lt;p&gt;For example, we might have a set of classes for various vertical margins. They might be &lt;code&gt;my-0 my-1 my-2 my-3&lt;/code&gt;...where each number represents some "level" of margin. So maybe &lt;code&gt;my-1&lt;/code&gt; equals &lt;code&gt;margin-top: .25rem; margin-bottom: .25rem;&lt;/code&gt;, and each level after is just + .25rem. Now we have a very useful set of classes to apply pretty much whatever vertical margin we need, and we no longer have to write margins in CSS unless it's an extremely specific case. Not only that, but we've given everyone who uses this a standard set of values to choose from. A third benefit is that we know exactly what the class does, there's no guesswork or hidden values. Finally, we've now opened the possibility for any element or component to have their margin changed, if the situation arises, without making a specific override in CSS. This is probably the most powerful pattern in CSS that I've encountered, even more so than LESS/SASS/SCSS.&lt;/p&gt;

&lt;p&gt;If you want to read more about it here are some great links, &lt;a href="https://frontstuff.io/in-defense-of-utility-first-css"&gt;In Defense of Utility-First CSS&lt;/a&gt;, &lt;a href="https://tailwindcss.com/docs/utility-first/"&gt;Tailwind CSS&lt;/a&gt;, &lt;a href="http://tachyons.io/"&gt;Tachyons CSS&lt;/a&gt;, and a whole slew of articles linked at &lt;a href="https://johnpolacek.github.io/the-case-for-atomic-css/"&gt;The Case for Atomic CSS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistently Ordering Properties
&lt;/h3&gt;

&lt;p&gt;This is really small and has no actual effects on your CSS (unless it's duplicate properties for fallbacks of properties that aren't supported). However I find it really helpful when reading/writing CSS to stick with a consistent order. My preferred order is layout/positioning, sizing, spacing, typography, colors/visual effects, transition/animations, and then finally "miscellaneous". Within each category I try to stay ordered as well. It helps to spot bugs and speed things up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Class Specificity
&lt;/h3&gt;

&lt;p&gt;I learned this the hard way after nesting way too much SASS and before I got deep into atomic CSS. I was working at a design agency building boutique level websites so everything was very creative and unsystematic or at least each component had lots of exceptions 😉. I quickly found that it was becoming difficult to override CSS I had previously written because everything varied in specificity. By flattening all of it to as close to one class level of specificity it became much easier to override properties on a class. This works hand-in-hand with atomic CSS because as long as your utility classes come last (or have important applied because let's face it if you put that class on their you wanted it) it'll override the component class. This leads to much less specificity wars.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performant Transitions and Animations
&lt;/h3&gt;

&lt;p&gt;This one is very simple, but can be annoying in practice. There are only two properties in CSS that can be reliably performant, &lt;code&gt;transform&lt;/code&gt; and &lt;code&gt;opacity&lt;/code&gt;. Everything else is subject to more expensive operations that can cause jank. In general I try to use only these, but I still use &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;background-color&lt;/code&gt;, and &lt;code&gt;border-color&lt;/code&gt; often in low-impact situations, like links or buttons. Read more here about &lt;a href="https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/"&gt;high performance animations&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Semantics, aka Learn the Basic Tags
&lt;/h3&gt;

&lt;p&gt;There are so many HTML elements. It's hard to know them all and everything that they do, but they will help you build web experiences that are more accessible and maybe even help you write less CSS and JS. Proper HTML also helps your site get crawled by search engines, which helps your content get found. They are the basic bits of the web and using them properly helps you create websites that work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Responsive Images
&lt;/h3&gt;

&lt;p&gt;Here's the best way to save bytes on your images. Responsive images allow you to serve just the right size to your users by giving you channels to describe images of different sizes and when those sizes will apply. There's a great doc written by MDN that explains it &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &amp;lt;input&amp;gt; + &amp;lt;label&amp;gt; = interaction (&amp;lt;dialog&amp;gt;, &amp;lt;details&amp;gt;, and more)
&lt;/h3&gt;

&lt;p&gt;There are a lot of interactions built into the default browser elements. We can leverage those to build interactive elements that do not require Javascript. And since they don't require JS, they're just a little more robust. Sometimes though, JS is required to really make a set of elements usable and accessible. In those cases we start with the HTML+CSS and layer on the additional functionality required with JS.&lt;/p&gt;

&lt;p&gt;We can build custom toggles, file inputs, and many other types of elements using an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; + &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; combination by simply using the &lt;code&gt;:checked&lt;/code&gt; selector to update the state of the visible element.&lt;/p&gt;

&lt;p&gt;Popovers and collapsible elements can also be built with the details element. A great presentation on this: &lt;a href="https://github.com/muan/details-on-details"&gt;The Details on Details by Mu-An Chiou&lt;/a&gt; and a similar one on modals/dialogs by the same author &lt;a href="https://docs.google.com/presentation/d/1BOfauRVTJnGGBQUeNa75N5AzoHCX_sFHpmxcKEKMEB8/edit#slide=id.p"&gt;A Dialog on Dialogs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  JS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  State and Special Attributes as Strings (or getting rid of boolean addiction)
&lt;/h3&gt;

&lt;p&gt;When writing Javascript we have a tendency when starting out to write states as a set of boolean flags. We might simply start with one state, &lt;code&gt;isError&lt;/code&gt;, and assign that a boolean value. And at first this might be fine if it's the only state we're tracking. Soon though we'll probably add more, maybe we need an &lt;code&gt;isInProgress&lt;/code&gt; state. Now we have two flags to represent what should realistically only be one state for the whole component. If both of those states are &lt;code&gt;true&lt;/code&gt;, then what state should we be in? We quickly get into situations where invalid states are possible. &lt;/p&gt;

&lt;p&gt;The simplest way to resolve this is to track state with a string. The string should be part of a limited set that represents all the states that our component can be in. This helps clean up all the &lt;code&gt;isX&lt;/code&gt; properties that litter our components and we can simply check the state with a function that returns a boolean value. &lt;/p&gt;

&lt;p&gt;Here's a basic example of an ajax call to a server to load some data:&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;loaderStates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;initial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loaderStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&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;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; 
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;loadTodos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loaderStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&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;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loaderStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loaderStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="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;You can see we've created an object to hold our states called &lt;code&gt;loaderStates&lt;/code&gt;. We also created a function which lets us check if the current state matches a state we want to know about, equivalent to what we had before &lt;code&gt;isError&lt;/code&gt; vs &lt;code&gt;is(loaderStates.error)&lt;/code&gt;. Now we can use this function to trigger things like spinners when loading or error messages when we're in an error state.&lt;/p&gt;

&lt;p&gt;A much more advanced version of this pattern is called &lt;em&gt;state machines&lt;/em&gt; which you can find out more about &lt;a href="https://www.youtube.com/watch?v=czi24DqUfSA"&gt;here&lt;/a&gt; from David K Piano where he uses the library he wrote &lt;a href="https://github.com/davidkpiano/xstate"&gt;xstate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, we tend to use these types of boolean flags to describe attributes like &lt;code&gt;CanUpdate&lt;/code&gt;, &lt;code&gt;CanEdit&lt;/code&gt;, etc. which is just as unmaintainable. In the same way as above, we can move to strings to give us a more succinct way to represent some set of attributes. This is also gives us the added benefit of being able to iterate through the set of strings with array functions, whereas before we might have had to have a huge if-else statement to check all the attributes.&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;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="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;Hunter Miller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canEdit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canPublish&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canManageUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canApprove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canViewOtherUsersContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canAccessBackend&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vs.&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;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="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;Hunter Miller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;edit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;publish&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;manage-users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;approve&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;view-others-content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;access-backend&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Making Maps
&lt;/h3&gt;

&lt;p&gt;There's a common pattern in JS where we want to run some functionality or get some data based on a key. Instead of using a chain of if statements or a switch with cases, we can use an object to associate a particular key with whatever we need, and then just access what we need with &lt;code&gt;map[key]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Data we're working with:&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;transaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;33.93&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;loginId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hmillerdev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hunter@hmiller.dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;paymentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;e2b7291d-8838-4435-942a-ec6bec938673&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="na"&gt;paymentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;credit-card&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;Using ifs:&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="nx"&gt;processTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;credit-card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processCreditCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;);&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;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paypal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processPaypal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;);&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;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processBank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;);&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;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bitcoin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processBitcoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;);&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;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;seashells&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processSeashells&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with a map:&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;processors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;credit-card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;processCreditCard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;paypal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;processPaypal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;bank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;processBank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;processBitcoin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;seashells&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;processSeashells&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;processTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;processPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;processors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentType&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Functionalize
&lt;/h3&gt;

&lt;p&gt;This one is pretty near and dear to me. One of the first things I learned was to break my functions down as small as they can be, so that we can reuse that chunk of code later. This comes with the added benefit that now we've given that chunk of functionality a name. So when we read through the code, we can get a better sense of what's going on. It also lets us leverage one of the main features provided to us in JS, that let's us pass functions around to alter the functionality of other functions. &lt;/p&gt;

&lt;p&gt;One of the best examples, is the array function &lt;code&gt;map&lt;/code&gt;. We call this function off of an array and pass it a function which will transform each item in the array returning a whole new array.&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;itemPrices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;25.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;48.00&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;priceWithHalfOffDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&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;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;discountedPrices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;itemPrices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;priceWithHalfOffDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;So now &lt;code&gt;discountedPrices&lt;/code&gt; equals &lt;code&gt;[12.50, 5.00, 24.00]&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Anytime we need to transform each item in an array and get that transformed array back, we can use map with whatever transforming function we need. We now have an immense set of functionality with just one function, because we can give it something to change what it does. &lt;/p&gt;

&lt;p&gt;This is the very tip of the iceberg to a style of programming called functional programming which you can learn about from Mattias at Fun Fun Function from his &lt;a href="https://www.youtube.com/watch?v=BMUiFMZr7vk"&gt;functional programming playlist&lt;/a&gt; or you can learn from this fun little online book called the &lt;a href="https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/"&gt;Professor Frisby's Mostly Adequate Guide to Functional Programming&lt;/a&gt;. I've found that this style of programming has vastly improved my code quality and resiliency and makes a lot of problems much easier to think about. However it can be very confusing when you first learn it because it is a bit of a brain change for most people.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Repeat Yourself (Too Much)
&lt;/h3&gt;

&lt;p&gt;Related to the previous section, if we have two blocks of code that are very similar, it can be beneficial to combine them into a function and let the parameters dictate the differences. Sometimes this can get us into trouble if we're trying to force things that are too different together. It might force us to make a function that has way too many branching paths or long lists of parameters. I find that is less often the case though. We actually more often have a ton of things that are very similar and once we start de-duplicating one part of the code it can lead to a waterfall of changes that makes the code much cleaner and easier to read. A good rule of thumb is that if this helps the code handle things more consistently and improves the readability then it's a good time to remove the redundancy. This can be a double-edged sword, but mostly beneficial when not overused.&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="nx"&gt;processOrderWithShipments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&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;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;shipments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;assignItemsToShipments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&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;paymentProcessor&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;PaymentProcessor&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Order is invalid&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;paymentProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sendOrderConfirmationEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;receipt&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;shipments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;assignItemsToShipments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;alertFulfillment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shipments&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="nx"&gt;processRecurringDigitalGoodsOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timePeriod&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&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;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;paymentProcessor&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;PaymentProcessor&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Order is invalid&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;paymentProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sendOrderConfirmationEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;setupSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timePeriod&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sendGoods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goods&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;vs&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="nx"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentProcessor&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;PaymentProcessor&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Order is invalid&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;paymentProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sendOrderConfirmationEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;receipt&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="nx"&gt;processOrderWithShipments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&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;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;shipments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;assignItemsToShipments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;alertFulfillment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shipments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;😭😭😭😭&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="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="nx"&gt;processRecurringDigitalGoodsOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timePeriod&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;orderData&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;timePeriod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&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;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;setupSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timePeriod&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;sendGoods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goods&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;😭😭😭😭&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting Rid of a Few Ifs
&lt;/h3&gt;

&lt;p&gt;Often in our code we want to provide some default values or not call a function if something's &lt;code&gt;null&lt;/code&gt;. We can get around using if statements by using boolean checks. For example if we want to default a value based on a parameter that may or may not be null we can do something like this: &lt;code&gt;const items = newItems || []&lt;/code&gt;. Because of the way JS works, boolean checks like this return the value of the expression so &lt;code&gt;items&lt;/code&gt; will be assigned &lt;code&gt;[]&lt;/code&gt; if newItems is null or undefined. This is a tip I picked up from Addy Osmani though I can't seem to find the article he wrote about it. Sometimes this can result in code that's less readable and in those cases you should use an if statement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separate API Calls into Their Own Module
&lt;/h3&gt;

&lt;p&gt;If you have multiple calls to a shared endpoint or API, it can often be helpful to encapsulate all those AJAX calls into a module where each call is a function. Now, setup and the handling of the response can be the same across the application. Anytime something changes about that API all the changes can be made in one place and we don't have all that clogging up our specific component's logic.&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;class&lt;/span&gt; &lt;span class="nx"&gt;todoAPI&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;getTodos&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;editTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoAPI&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;todoAPI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later on when you need to get the todos:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;todoAPI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./todoAPI&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;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;todoAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTodos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us the ability to pass around the API to whatever module or component needs it, and it's not stuck in some specific component. Yet another way to increase re-usability and reduce duplication.&lt;/p&gt;

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

&lt;p&gt;The web evolves constantly and so do my practices and philosophies around development, but the thoughts above have stuck around. These things are like old regulars that just keep coming back to the cafe even though the rest of the customers keep changing. A lot of what I've picked up above came from trial and error. I also read a ton of web dev Twitter, and am never scared to Google something to try out new methods. Like my good friend &lt;a href="https://www.bennettdungan.com/"&gt;Bennett Dungan&lt;/a&gt; said, learning to code is a marathon. It takes time to build practices and methods that make you productive. Try some of these things and &lt;a href="https://twitter.com/intent/tweet/?text=Here%27s%20a%20long%20list%20of%20simple%20front-end%20development%20practices%20that%20will%20help%20you%20be%20more%20productive%20in%20your%20day-to-day.%20by%20@hmillerdev&amp;amp;url=https://hmiller.dev/posts/front-end-practices-that-changed-my-life/"&gt;let me know what you think on Twitter.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;– Hunter ✌&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;em&gt;Originally posted on &lt;a href="https://hmiller.dev/posts/front-end-practices-that-changed-my-life/"&gt;hmiller.dev&lt;/a&gt;. Cover photo by &lt;a href="https://unsplash.com/@punttim?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Tim Gouw&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The Psychology of Building Software During a Crisis</title>
      <dc:creator>Hunter Miller</dc:creator>
      <pubDate>Fri, 27 Mar 2020 13:07:21 +0000</pubDate>
      <link>https://forem.com/arthyn/the-psychology-of-building-software-during-a-crisis-gii</link>
      <guid>https://forem.com/arthyn/the-psychology-of-building-software-during-a-crisis-gii</guid>
      <description>&lt;p&gt;I haven't lived through too many crises. Mostly, it's been hurricanes, and I was a child during the ones that actually affected my day-to-day life. COVID-19's effect is quite unprecendented, both in my life and the lives of others. Today marks two weeks since I started self-isolation with my wife. We've done well so far, cooking a lot, spending time in our backyard with our animals and the birds, keeping up with friends and family through video chats, and trying to enjoy all our hobbies that can be done at home. We've been very fortunate especially since we both can work from home and keep a paycheck whereas others have not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business (not) as usual
&lt;/h2&gt;

&lt;p&gt;Even though we're both big introverts, we're still going a little stir crazy. Not only that, but the weight and severity of the current pandemic is affecting our moods and energy. Certain things feel more important now, much more than ever, and other things that might have felt somewhat important before, now feel meaningless.&lt;/p&gt;

&lt;p&gt;For example, minor things like keeping a particular sleep schedule, cutting grass, washing the car, etc. start feel a little meaningless. Side projects that I might have picked up to work on after work don't quite call my name like they used to. So maybe a small boon of this time is that it shows us what really matters.&lt;/p&gt;

&lt;p&gt;And yet, this hasn't quite seemed to have hit my company's psyche yet. We're still mostly business as usual (besides now all working from home and taking precautions), building the same software for the same projects that we were working on before. With mostly the same deadlines. It feels wrong or at the least off. It feels like we should be contributing to the problem at hand, the pandemic. If not that, it feels like we should be working on cleaning up and bolstering the core software. But we aren't. We're building for new features, like we always are.&lt;/p&gt;

&lt;p&gt;Before this crisis, we operated as a feature factory for the large ecommerce site we run, at one of the world's largest jewelry manufacturers. The feature factory pace/prioritization has been written about many times before. The business comes up with a new feature to offer users in an attempt to get more sales, and then we build it. Repeat. &lt;/p&gt;

&lt;p&gt;The effects of this style can be seen everywhere. Complicated UI that appeases the 1% of users who actually use it while confusing the 99% who don't need it. Tons of code that hasn't been touched in years. Over burdened teams with ever depreciating code bases and little to no time for maintenance of the core features. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's missing?
&lt;/h2&gt;

&lt;p&gt;A mindset. A mindset that keeps the essence of our business and the majority of users top of mind. We're like magpies. Every customer with a shiny new problem or every teammate with a new brilliant feature stops us in our tracks. It's easy to forget that 95% of our customers go through the same five pages of our site nearly every day. If our gemstones deptartment is looking to improve their numbers, and we start building a new experience to make it easier, maybe we'll improve the numbers by 3-10%. But gemstones might only be 5% of our total web revenue. So, globally this nets us a 0.5% increase in revenue. If we instead make a change like improving checkout flow, or globally decreasing page load by 1s, we might see a total web revenue improvement by 1% or more while also improving all of our customer's experiences.&lt;/p&gt;

&lt;p&gt;That's not as glamorous as making a new feature and not nearly as marketable, but it's more helpful overall. It also puts us in a stronger position over the long run, because our core is resilient, forged to perfection over time. If we continually choose working on what's essential, our customers won't want to leave, and they'll have more confidence we're invested in what they actually came for. Sometimes you have to build the glam to attract people or innovate to find unreached markets. And I think that's perfectly fine some of the time, but you need the right mix.&lt;/p&gt;

&lt;p&gt;Getting back to crisis time, what can we even be certain of right now? This could all last much longer than we thought. A new program or feature we wanted to release might get lost in the malaise of the time, a waste. People aren't seeking novelty right now. They want security and certainty. Which is why it feels wrong. What can we build to shore up weaknesses during times like this? If we have to shut down for weeks, what can we focus on that saves us money or cleans up something really messy? Our customers won't be expecting new and fresh.&lt;/p&gt;

&lt;p&gt;Everyone's huddling in place or courageously fighting. By trying to run business as usual, I feel out of place, almost guilty. And definitely mentally and emotionally low on energy. When I normally would be working on side projects, I find myself just wanting to relax and spend time with friends and family. The universe is shoving the essential in my face. I've been wanting to consistently write for a long time, and this might be the only way to feel like I'm contributing to the larger problems at hand.&lt;/p&gt;

&lt;p&gt;If you just feel like chatting with someone, you can email me at &lt;a href="//mailto:hunter@hmiller.dev"&gt;hunter@hmiller.dev&lt;/a&gt; or schedule something on my &lt;a href="https://calendly.com/hunter-miller"&gt;calendly&lt;/a&gt; and we can video chat. Stay safe out there and keep connected with those you love.&lt;/p&gt;

&lt;p&gt;– Hunter ✌&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://hmiller.dev/posts/the-psychology-of-building-software-during-a-crisis/"&gt;hmiller.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@___rob__?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Robert Metz&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>Senior Developers, Let Us Learn Too</title>
      <dc:creator>Hunter Miller</dc:creator>
      <pubDate>Fri, 23 Aug 2019 04:56:50 +0000</pubDate>
      <link>https://forem.com/arthyn/senior-developers-let-us-learn-too-kdp</link>
      <guid>https://forem.com/arthyn/senior-developers-let-us-learn-too-kdp</guid>
      <description>&lt;p&gt;If you have a team of developers there will always be a mix of experiences and ages. Something I've noticed especially from senior and older developers is a tendency to be negative, doubtful, cynical, and quick to shoot down ideas that don't jive with what they know. This creates a culture without sharing because some ideas are worth more than others. This culture leads newer devs to censor themselves, and if I'm less likely to share what I think, then I'll be even moreso afraid to question what seniors say.&lt;/p&gt;

&lt;p&gt;I've had to develop a strong will and confidence to be able to question seniors and have my ideas heard. When making decisions about a new project, senior devs often have flimsy reasons, deep assumptions or very little passion to support their decisions. Sometimes I can sway them over a prolonged discussion because I'm often more passionate about a solution than they are, but frequently decisions get made quickly without the group because they decide to go ahead of the team.&lt;/p&gt;

&lt;p&gt;Senior devs that go off to "hero" a project are toxic. Just because you can fully implement a project top to bottom doesn't mean you should. Sometimes it's not even their choice to do so, but they often have the choice to include others on the project. If they don't and start making all the decisions, it feels like they are taking all the fun. Development thrives on shared knowledge, exposure to others' ideas/cross-pollination, criticism of code style and architecture. Too much code that has not been designed for readability and understanding especially without including others becomes a black hole. Their code is optimized for their own understanding. This creates artificial bottlenecks in the codebase. It becomes the sole responsibility of the person who wrote it, which leads to siloing, more context switching and overall a larger burden on the team. You may even make memes about the obtuse, complex, and messy code that no one wants to touch or untangle. &lt;/p&gt;

&lt;p&gt;If you read Twitter at all, this is the "10x engineer" everyone was memeing about. When devs like this have strong opinions and loud voices, they will dominate a team. Too often these people are propped up by middle/upper management because they see them as high producers. Which leads to even more influence in their favor. It can be stifling. Seniors tackling the majority of the difficult work prevents the mids and juniors from reaching their full potential and perpetuates their status. And when others go to tackle hard problems they get stuck easier because they haven't had enough practice. It becomes a self-fulfilling prophecy. &lt;/p&gt;

&lt;p&gt;What does it take to reverse the situation? Like in most crafts, devs need room to make mistakes and fuck up. We need time to learn. We don't come out of the womb knowing all the intricate knowledge that we are expected to know, especially intimate business knowledge. Plus, no one knows everything. We need seniors with a beginner's mind, open to learn something even from the noobiest junior. Because as we've seen, the world of development changes quickly and there's always something new to learn. Encouraging others to own projects, removing your ego from solutions, asking hard questions that help others to arrive at the correct architecture/solution, guiding architecture but not dictating it, pairing, helpful code reviews. When you find a senior who takes support of the teams seriously, it's a breath of fresh air and helps the team move faster as a whole.&lt;/p&gt;

&lt;p&gt;It can be tough balancing this with business needs, especially if it's a particularly toxic business culture too. Really it all boils down to time and patience. Good senior devs will take time with others and really help to make sure they understand. Like any good leadership they should be willing to get their hands dirty, pave the way, but ultimiately trust that the rest of the team can carry out the majority of the work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://hmiller.dev"&gt;hmiller.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>Achieve Greatness by Striving for Quality</title>
      <dc:creator>Hunter Miller</dc:creator>
      <pubDate>Sat, 03 Nov 2018 06:19:32 +0000</pubDate>
      <link>https://forem.com/arthyn/achieve-greatness-by-striving-for-quality-2a8e</link>
      <guid>https://forem.com/arthyn/achieve-greatness-by-striving-for-quality-2a8e</guid>
      <description>&lt;p&gt;Building effective and resilient software is hard. Building software that is a joy to use is &lt;strong&gt;even harder&lt;/strong&gt;. Software developers and their teams manage a number of goals and often struggle with meeting them, whether it's business goals, making deadline/budget, finding the right talent, avoiding technical debt, etc. &lt;/p&gt;

&lt;p&gt;All of those goals are important, but none of them trump &lt;strong&gt;creating usable software&lt;/strong&gt;. Being usable is simply the lowest bar. Any lower and the product will simply fail. Does your app annoy people? Do users have to trudge through mud to do even the simplest of tasks? Questions like this can lead us to great reward, if we would only spend the time it takes to resolve the problems uncovered.&lt;/p&gt;

&lt;p&gt;Developers seem to have a blind-spot and a particular endurance for clunky experiences. We understand what it took to make. Even a few mis-steps can lead us down a path where our app becomes frustrating to even look at. And while we can have sympathy towards others who build software, &lt;strong&gt;we cannot expect sympathy from our users&lt;/strong&gt;. They deserve better and shouldn't be burdened with our struggle. We've got to be better than that. Especially for developers just getting into the field, we have to give them principles to uphold and an image to strive for. We have to show them what it takes and what it really means to do development well. &lt;/p&gt;

&lt;p&gt;True quality can only be achieved by deep understanding and collaboration with our colleagues outside of development, but we need to control how we work and be firm with our principles. &lt;strong&gt;This is what it takes to create truly gratifying software.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Technically UX
&lt;/h2&gt;

&lt;p&gt;To help developers strive towards this goal, I'm starting a weekly newsletter, &lt;a href="https://technicallyux.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Technically UX&lt;/strong&gt;&lt;/a&gt;. We will be discussing what it takes to build better, usable software and introduce a new topic called technical UX. Technical UX is a whole class of problems that fall under developers' responsibility that range from foundational issues like poorly performing architecture, all the way up to final polish issues like optimizing animations. It's part of what separates the good developers from the great and often part of the reason why we fail at making usable experiences.&lt;/p&gt;

&lt;p&gt;If you want to learn more, check out the &lt;a href="https://technicallyux.com/posts/intro-to-technical-ux:-part-1-performance/" rel="noopener noreferrer"&gt;first newsletter that just launched on performance&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>ux</category>
      <category>webdevs</category>
      <category>introduction</category>
    </item>
  </channel>
</rss>
