<?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: Nathan Fritz</title>
    <description>The latest articles on Forem by Nathan Fritz (@fritzy).</description>
    <link>https://forem.com/fritzy</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%2F143919%2Ffce12b14-cffb-4289-8bd1-66bcec38502f.jpg</url>
      <title>Forem: Nathan Fritz</title>
      <link>https://forem.com/fritzy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fritzy"/>
    <language>en</language>
    <item>
      <title>The Future of Virtual Assistants</title>
      <dc:creator>Nathan Fritz</dc:creator>
      <pubDate>Tue, 01 Jun 2021 16:53:41 +0000</pubDate>
      <link>https://forem.com/fritzy/the-future-of-virtual-assistants-2ie9</link>
      <guid>https://forem.com/fritzy/the-future-of-virtual-assistants-2ie9</guid>
      <description>&lt;p&gt;&lt;em&gt;I did a series of talks on the future getting weird several years ago. This is a self-indulgent post where I once again explore my futurism hobby.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Virtual assistants like Siri, Hey Google, and Alexa are going to get much more useful in the coming years. With the rise of &lt;a href="https://en.wikipedia.org/wiki/Machine_learning"&gt;machine learning&lt;/a&gt;, including technologies like &lt;a href="https://en.wikipedia.org/wiki/GPT-3"&gt;GPT-3&lt;/a&gt;, these assistants will get a lot more conversational, but it goes beyond that. These services will get &lt;em&gt;personal&lt;/em&gt;, and become infinitely more useful as they become our agents on applications and websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personalized
&lt;/h2&gt;

&lt;p&gt;Assistants will collect data from our conversations to combine with data from other sources in order to create a more personalized experience. Making suggestions, for example. They might even reach out to you during the day.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hey, Nathan?"&lt;br&gt;
"Yeah, Siri?"&lt;br&gt;
"You're trying to build a pushup habit – this might be a good time."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You could also respond by shushing it, or arguing that you just wanted to do pushups that &lt;em&gt;one time&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Modern thinking has it that &lt;a href="https://jamesclear.com/habit-triggers"&gt;building habits requires a trigger&lt;/a&gt;, and your assistant could provide that. Along those lines, it could track your calories, guide your meditations, make suggestions for upcoming anniversaries and birthdays, and more.&lt;/p&gt;

&lt;p&gt;Some of these things might sound like notifications, but it's a little different. The assistant will be making guesses as to when you're not busy based on movement, heart rate, and other clues; it'll start to learn when you don't mind being interrupted. It'll be much more polite about it than any notification could be, not that you couldn't ask it to stop.&lt;/p&gt;

&lt;p&gt;Other ways that an assistant will adapt to you is with subtle clues about your tone of voice, and other behaviors. In order to build a rapport with you, it'll mimic your inflections and speech patterns. Research has shown that we &lt;a href="https://en.wikipedia.org/wiki/Mirroring"&gt;mirror body language and speech interactions&lt;/a&gt; in order to build mutual respect.&lt;/p&gt;

&lt;p&gt;An agent will start to anticipate your usage patterns to make interactions more convenient for you. It'll notice when you've missed something, and help you fill in the gap. Beyond just anticipating your Starbucks order (more on that later), an assistant will realize that you're rushing to work, and might send a message ahead of you to let your employees know that you're going to be a few minutes late for the first meeting of the day. The agent is watching out for you, and will try to make your day go more smoothly.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Explosion of Applications and Use Cases
&lt;/h2&gt;

&lt;p&gt;The actions an agent will be able to take is going to explode. Right now, if McDonald's wanted Alexa to be able to make an order, they'd have to register an extension with Amazon and include all of the anticipated words and commands along with their responses, or a service callback to make a dynamic response. Each user will then have to add the McDonald's service to their Alexa and cross-authenticate with their McDonald's user account. Additionally, each user will have to learn and memorize the type of things they can say to use the McDonald's service in Alexa. All of this complexity keeps the number of services fairly low, and user participation even lower.&lt;/p&gt;

&lt;p&gt;But this will change in the coming years. Phone applications and websites will be able to include standardized interfaces specifically for virtual assistants. These &lt;a href="https://en.wikipedia.org/wiki/API"&gt;APIs&lt;/a&gt; will describe what kinds of things the agent can do with the service, suggested phrases and promotions, information dependency based workflows, and examples. This won't be nearly as strict as a traditional low-level API, because the agent will use language processing and other machine language techniques to interpret the application; it'll be somewhere in between a user interface and a computer interface. The assistant will combine its newfound knowledge of the service with what it knows about the user, and create a custom experience on the fly with the user.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Driving.&lt;/em&gt; "Hey Google, I'd like order a Big Mac from McDonald's up ahead."&lt;br&gt;
&lt;em&gt;Looks up the McDonald's agent API.&lt;/em&gt; "Sure, do you want that in a meal or just the sandwich?"&lt;br&gt;
"Just the sandwich."&lt;br&gt;
"They have seasonal vanilla custard filled Holiday Pies right now. You've been good and haven't had a dessert in a few days. Would you like one?"&lt;br&gt;
"Oh they have those again? Nice, I'd like one."&lt;br&gt;
"Your total is $9.14. Would you like me to finalize the order?"&lt;br&gt;
"Oh, can you add an ice water?"&lt;br&gt;
"Yes. The total cost is unchanged. Would you like me to order a Big Mac, Holiday Pie, and ice water for $9.14?"&lt;br&gt;
"Yes, that sounds good."&lt;br&gt;
"I submitted your McDonald's order on your VISA card ending in 1234. Please pull into order space #4."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since companies no longer have to painfully create and register &lt;a href="https://developer.amazon.com/en-US/docs/alexa/ask-overviews/what-is-the-alexa-skills-kit.html"&gt;agent skills&lt;/a&gt;, there will be a lot more services available to the agent. With the service-registration and user-friction gone, and fully customized experiences using natural language, there will be an explosion of consumer use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent-to-Agent
&lt;/h2&gt;

&lt;p&gt;Your agent instance will be able to interact with the agents of others, at least within a given platform (I'll talk more about open and federated standards another time). This will be useful for scheduling appointments, buying gifts, and checking in others that trust you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Does my partner have any late meetings tomorrow?"&lt;br&gt;
&lt;em&gt;Agent looks up their calendar directly, or asks their agent through a special API.&lt;/em&gt;&lt;br&gt;
"Their last work meeting is at 2:30pm."&lt;br&gt;
"What should I get them for their birthday?"&lt;br&gt;
"They recently added a book to their wishlist – Brandon Sanderson's &lt;em&gt;Rhythm of War&lt;/em&gt;, the latest in the &lt;em&gt;Stormlight Archive&lt;/em&gt;."&lt;br&gt;
"Oh yeah, she loves those books. Can you call the local books store and have them hold a copy for me? Also, order a flower arrangement from the flower shop around the corner."&lt;br&gt;
"I'll do that. Do you want me to confirm the arrangement and price before I order the flowers?"&lt;br&gt;
"No, you know what they like."&lt;br&gt;
"Okay. I'll have the book store hold the book at the front counter for you, and I'll order those flowers. I'll let you know when I'm done."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At any point, your agent could contact other agents or even people on the phone to ask the necessary questions. The other agents will know your relationship with their users, and will only allow your agent to have appropriate and approved types of data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This example might seem a little weird – having what is essentially a program pick out flowers for your partner. I also found it deeply weird in &lt;a href="https://fourhourworkweek.com/"&gt;4 Hour Workweek&lt;/a&gt; when Tim Ferris asked his internet assistant to write a heartfelt apology email to his wife. To each their own.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future is Weird
&lt;/h2&gt;

&lt;p&gt;Virtual Assistants are frustratingly rudimentary right now, but over the next decade, they'll get a lot more useful. These agents won't be &lt;a href="https://en.wikipedia.org/wiki/Artificial_general_intelligence"&gt;generalized artificial intelligence&lt;/a&gt;, we're simply not that close to developing one yet, but from a user's perspective, the lines will be blurred.&lt;/p&gt;

&lt;p&gt;I want to be clear that I'm not advocating for these features nor this future. I just think this is where things are headed based on the potentials at play, trends in natural language processing, privacy in the US, and the rise of cloud machine learning. I'll get into my opinions on the morality of these trends in a future post.&lt;/p&gt;

&lt;p&gt;Regardless of the morality of it, virtual agents &lt;em&gt;will&lt;/em&gt; make our lives easier, so it'll be an easy sell.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stay tuned for Part II, where we explore the repercussions of these technology trends.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>futurism</category>
      <category>future</category>
    </item>
    <item>
      <title>Keep Your OS Clean with $HOME/.local </title>
      <dc:creator>Nathan Fritz</dc:creator>
      <pubDate>Sun, 07 Feb 2021 07:30:31 +0000</pubDate>
      <link>https://forem.com/fritzy/keep-your-nix-install-clean-with-home-local-c04</link>
      <guid>https://forem.com/fritzy/keep-your-nix-install-clean-with-home-local-c04</guid>
      <description>&lt;p&gt;In a *nix environment (Linux, MacOS, WSL), software without packages can sometimes install to global spaces by default. This is often undesirable, due to running unverified scripts as root, conflicts with other packages, and potentially breaking the software during an OS upgrade. Instead, these custom installs should be placed in your home directory. In my case, &lt;code&gt;$HOME&lt;/code&gt; is &lt;code&gt;/home/fritzy&lt;/code&gt; or &lt;code&gt;/Users/fritzy&lt;/code&gt; on MacOS.&lt;/p&gt;

&lt;p&gt;But where &lt;em&gt;in&lt;/em&gt; your $HOME? As the title implies, &lt;code&gt;$HOME/.local&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This directory is a GNOME convention that other software has adopted as well. Similar to &lt;code&gt;/usr/local&lt;/code&gt;, it is designated for custom or non-package installed software. The &lt;code&gt;.&lt;/code&gt; at the beginning of the directory name has the added benefit of hiding the directory, preventing cluttering an often-used space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up $HOME/.local
&lt;/h2&gt;

&lt;p&gt;If it doesn't exist, go ahead and create it, along with a &lt;code&gt;bin&lt;/code&gt; directory as your user. No special permissions are needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, make sure that &lt;code&gt;$HOME/.local/bin&lt;/code&gt; is in your $PATH, preferably with a higher priority than &lt;code&gt;/usr/bin&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;For Linux Bash users do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/local.bin:&lt;span class="se"&gt;\$&lt;/span&gt;PATH &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom Installers
&lt;/h2&gt;

&lt;p&gt;Now we can install some software. I wanted to install &lt;a href="https://starship.rs/"&gt;Starship&lt;/a&gt;, a cross-shell prompt in my WSL2 Ubuntu. The only documented way to install this is to install by directly executing a download -- questionable from a security perspective.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://starship.rs/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, I downloaded and inspected the script. I discovered a few things. By default, it would install to &lt;code&gt;/usr/bin&lt;/code&gt;, a global space requiring root access. But there was good news; I found a command-line option to set the install directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl  https://starship.rs/install.sh &lt;span class="nt"&gt;--output&lt;/span&gt; install.sh &lt;span class="c"&gt;# download&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x install.sh &lt;span class="c"&gt;# make it executable&lt;/span&gt;
./install.sh &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.local/bin &lt;span class="c"&gt;# the -b option is what discovered&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; ./install.sh &lt;span class="c"&gt;# don't need this anymore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then followed the instructions for setting up Starship for Bash.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'eval "$(starship init bash)"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom Compiled Installs (Node.js)
&lt;/h2&gt;

&lt;p&gt;If you build custom software, you'll want to find the "prefix" option, and set it to &lt;code&gt;$HOME/.local&lt;/code&gt;. When following build instructions, you should ignore anything that tells you to use &lt;code&gt;sudo&lt;/code&gt; when installing; you won't need it with a prefix in your home directory, and doing so may cause problems later.&lt;/p&gt;

&lt;p&gt;Let's clone &lt;a href="https://nodejs.org"&gt;Node.js&lt;/a&gt;, compile it, and install it to our &lt;code&gt;.local&lt;/code&gt; prefix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking Out
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/build &lt;span class="c"&gt;# I use a build directory for custom compiling&lt;/span&gt;
git clone git@github.com:nodejs/node.git
&lt;span class="nb"&gt;cd &lt;/span&gt;node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating Tags
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="c"&gt;# update fetched branches and tags&lt;/span&gt;
git tag &lt;span class="c"&gt;# lists tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As an aside, if you want to sort tags with semver logic, you can update your git config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; tag.sort version:refname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Checkout a Tag As a Branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout tags/v15.8.0 -b build-v15.8.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure and Compile
&lt;/h3&gt;

&lt;p&gt;Now we can compile it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./configure &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.local
make &lt;span class="nt"&gt;-j12&lt;/span&gt; &lt;span class="c"&gt;# number of hardware thread on my cpu&lt;/span&gt;
make &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="c"&gt;# sets everything up in your prefix directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first &lt;code&gt;make&lt;/code&gt; line will take a bit, but hey, you look really busy and smart when you're compiling code.&lt;/p&gt;

&lt;p&gt;Now when you run &lt;code&gt;node -V&lt;/code&gt;, it'll show your newly install Node.js version. You also now have the added benefit of being able to install 'global' npm packages without sudo. You'll notice that you now have &lt;code&gt;include&lt;/code&gt; &lt;code&gt;lib&lt;/code&gt; and &lt;code&gt;share&lt;/code&gt; directories in your &lt;code&gt;$HOME/.local&lt;/code&gt;, just like you would with a &lt;code&gt;/usr/local&lt;/code&gt; prefix.&lt;/p&gt;

&lt;p&gt;You can get similar benefits of using &lt;a href="https://github.com/nvm-sh/nvm"&gt;nvm&lt;/a&gt; without having to compile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep It Clean
&lt;/h2&gt;

&lt;p&gt;Installing unpackaged software in your &lt;code&gt;$HOME/.local&lt;/code&gt; directory is more secure, more stable across OS upgrades, and prevents unnecessary &lt;code&gt;root&lt;/code&gt; usage going forward. It can take a bit of investigation with some software, but is worth having a cleaner install in the end. Ideally, the vast majority of your software simply uses OS supported packages, but now you have a plan for when it doesn't.&lt;/p&gt;

&lt;p&gt;For you MacOS users, OS upgrades would regularly break Brew for me, but you can even &lt;a href="https://andrewjorgensen.com/post/install-homebrew-to-your-home-directory/"&gt;install Brew into your home directory&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Please comment below, or send me your thoughts &lt;a href="https://twitter.com/fritzy"&gt;on Twitter @fritzy&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>macos</category>
      <category>node</category>
    </item>
    <item>
      <title>One Web Architect's Core Beliefs</title>
      <dc:creator>Nathan Fritz</dc:creator>
      <pubDate>Mon, 25 Jan 2021 17:04:24 +0000</pubDate>
      <link>https://forem.com/fritzy/one-web-architect-s-core-beliefs-335f</link>
      <guid>https://forem.com/fritzy/one-web-architect-s-core-beliefs-335f</guid>
      <description>&lt;p&gt;Our core beliefs are the principles that we've learned through experience or subscribed to from others in order to quickly make decisions and value judgements. They occasionally need to be re-evaluated, but without them, we'd spend all of our time analyzing instead of acting.&lt;/p&gt;

&lt;p&gt;Over time, as a software developer, you'll adopt and develop &lt;em&gt;software development&lt;/em&gt; core beliefs. It's important to be conscious of them, so that you can contextualize their application, debate your peers, and know when to re-evaluate.&lt;/p&gt;

&lt;p&gt;Here are some of the web architecture core beliefs that I've developed and adopted in my 20 years as a software developer. Each of these could be a blog post, and probably already are. My former colleagues may be able to remember specific incidents and hard lessons learned that cemented some of these beliefs. 😬&lt;/p&gt;

&lt;p&gt;Core beliefs, be they about software or life, are personal; I'm not asking you to agree with or adopt any of these, but if something rings true, certainly feel free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inactive Software Is Dead Software
&lt;/h2&gt;

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

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



&lt;/p&gt;

&lt;p&gt;In the web world, software ages very quickly. Dependencies are out of date in months, and with a culture of small packages, your software may have a lot of dependencies.&lt;/p&gt;

&lt;p&gt;Every time you set a piece of software down, it's going out of date. Bit rot is real. The platform that you built it for moves on, your embedded dependencies have software vulnerabilities published, your services change APIs, etc. It'll take some effort to bring your software back up to date the next time you need to work on it.&lt;/p&gt;

&lt;p&gt;When choosing dependencies, it's usually a bad idea in the web world to use anything that hasn't been updated in the last 6 months. You've been warned.&lt;/p&gt;

&lt;p&gt;Are there exceptions? Sure. What if your software uses a stable platform, has no or few dependencies, and is super small. Again, context is king.&lt;/p&gt;

&lt;h2&gt;
  
  
  The KISS Principle (Keep It Simple Stupid)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/KISS_principle" rel="noopener noreferrer"&gt;The Kiss Principle is 80 years old&lt;/a&gt; at this point. It states that complicated systems are much more prone to failure.&lt;/p&gt;

&lt;p&gt;There's &lt;a href="https://en.wikipedia.org/wiki/List_of_software_development_philosophies#Rules_of_thumb,_laws_and_principles" rel="noopener noreferrer"&gt;a lot of these software principals&lt;/a&gt;. You may want to adopt some of them if they ring true to you.&lt;/p&gt;

&lt;p&gt;I also like Gall's Law.&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;The thing is, we're engineers, and we over-do it sometimes. Over-engineering is always a temptation for software developers that love their craft. It's probably the most common software development sin. There's a time and a place, which we'll get to in a bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client State is a Cache
&lt;/h2&gt;

&lt;p&gt;Client-side web applications have to hold some data, and the client is almost never the source of truth. That means that any data you maintain in a client is part of a cache and should be treated that way.&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;You have to be very deliberate with cached data. Here are some guidelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only cache data that you're very likely to use.&lt;/li&gt;
&lt;li&gt;Don't cache data that the user doesn't have permissions to see.&lt;/li&gt;
&lt;li&gt;Avoid making decisions based on cached data.&lt;/li&gt;
&lt;li&gt;Invalidate cached data when the source of truth updates.&lt;/li&gt;
&lt;li&gt;Don't update the cache from user actions without marking it as pending.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dealing properly with client state data is a very large topic, but thinking of it as a cache first can help you make the right choices for how to use and maintain that data.&lt;/p&gt;

&lt;h2&gt;
  
  
  100% Test Coverage Is Achievable and Desirable
&lt;/h2&gt;

&lt;p&gt;When writing a library or API, 100% test coverage should be a priority. Yes, it's doable. In the worst case, it's time-neutral, and the benefits are great and sometimes non-obvious.&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;I'm not an expert when it comes to testing on the client-side of a web application, but I have seen significant coverage of the data-management and component side done to great effect.&lt;/p&gt;

&lt;p&gt;Tests not only validate that your code is following the intended purpose, but it also documents that intended purpose in great detail. It gives future contributors a starting point when looking at a piece of functionality -- they can use your tests to suss out how to generate the required inputs, where in the code functionality lives, and exactly what your expectations for the code were. Good test coverage reduces the cognitive overhead of someone else working on your code.&lt;/p&gt;

&lt;p&gt;Tests give you a solid foundation when refactoring -- if your coverage is good enough, you'll know where you need to keep working and when you're done refactoring. Tests give you the confidence to make big changes.&lt;/p&gt;

&lt;p&gt;Code coverage will also help prevent &lt;a href="https://en.wikipedia.org/wiki/Spaghetti_code" rel="noopener noreferrer"&gt;spaghetti code&lt;/a&gt;. As Isaac points out, code that is hard to test is a &lt;a href="https://en.wikipedia.org/wiki/Code_smell" rel="noopener noreferrer"&gt;code smell&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business Logic Needs to be Isolated
&lt;/h2&gt;

&lt;p&gt;All of your business logic for a web app should be in the server. UX logic can live on the client, and data management logic can live in the database, but you're asking for trouble to do any business logic anywhere except your server process. Ideally, it should be in it's own layer within that process.&lt;/p&gt;

&lt;p&gt;When you spread business logic out, it makes it hard to find and maintain, and you greatly increase the complexity of your app. You're opening yourself up for security vulnerabilities (the very nature of a web client having authorization logic is a vulnerability in itself).&lt;/p&gt;

&lt;p&gt;So what is business logic? Any action that results in a function that changes/accesses data directly related to the purpose of the application.&lt;/p&gt;

&lt;p&gt;It's okay to use a stored procedure for actions that are not specific to the application, like maintenance, migrations, sharding, etc. It's okay to have client logic for displaying views and generating API calls. If you're checking to see whether a user can make an API call before making the API call, that may be a sign that something is amiss.&lt;/p&gt;

&lt;p&gt;Keeping all of the business logic on one server layer makes it more testable, makes it easier to swap out database and API layers, and reduces the number of things a developer has to think about while making changes or debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Expose More Surface Area Than You Use
&lt;/h2&gt;

&lt;p&gt;Any code that you're not using in your project is technical debt, and any API that you haven't tested is a vulnerability. It's a trope at this point for developers to brag about how many lines of code they've deleted rather than the number that they've written with a wink. It goes along with the KISS principal. Don't be overly clever in order to reduce your line-count, but generally less is more.&lt;/p&gt;

&lt;p&gt;One of the reasons why I generally don't think GraphQL is a great solution is because you're deploying more capability than you're using. You're giving clients and users a full query language, of which they'll only use a small portion, in most cases, and when it doesn't work or surfaces a denial-of-service vulnerability because they can write a query that performs poorly, that's a bug you're going to have to fix.&lt;/p&gt;

&lt;p&gt;There are valid use cases for exposing a query interface like GraphQL, and there are ways of limiting its surface-area, and ways of getting complete test coverage, but all of those things involve considered effort. Here is an &lt;a href="https://www.apollographql.com/blog/securing-your-graphql-api-from-malicious-queries-16130a324a6b/" rel="noopener noreferrer"&gt;Apollo GraphQL Guide&lt;/a&gt; for dealing with some of these problems.&lt;/p&gt;

&lt;p&gt;Every line of code and every piece of functionality you provide is an opportunity for bugs and increases maintenance. If you and your users aren't going to use it, don't include it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Innovate When Developing an MVP
&lt;/h2&gt;

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

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



&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/fritzy/status/1345958359342612482" rel="noopener noreferrer"&gt;This twitter thread&lt;/a&gt; pretty much covers my view here. It's a bit of a hot take, but it goes along with some of my other core beliefs and the KISS principal.&lt;/p&gt;

&lt;p&gt;Basically, the time for innovation is not during the initial version of a project. You should do your experimentation separately, either as isolated prototypes and experiments, or incrementally after you prove to the business that the MVP has value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clever is the Enemy of Good
&lt;/h2&gt;

&lt;p&gt;You should write code for people first, not computers. It's important that team members and your future self be able to easily see what your code is meant to do. Follow language idioms, don't take shortcuts just to shave off a few lines, and don't try to combine your logic to fulfill many purposes in one clever bit of code.&lt;/p&gt;

&lt;p&gt;Instead, clearly handle your logic in an idiomatic way that walks through the problem step-by-step. Simplicity is handling the core logic and edge-cases with clear code. Don't go out of your way to save keystrokes as typing is not the time consuming part of writing software; thinking is. You can always go back and make things more terse if you've thought of a better way to be clear and handle more edge cases later.&lt;/p&gt;

&lt;p&gt;Your goal is to make your code appear pedestrian, despite solving the problems brilliantly. This may take some iteration and a lot of thinking. You'll know you're doing well if both senior and junior developers understand your code and pull requests at a glance. Make sure to give similar feedback when doing pull requests for other developers.&lt;/p&gt;

&lt;p&gt;For example, creating a clever mix-in function for a language that only supports direct inheritance will make the code hard to follow, and make the software more difficult to debug. Keep things simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uncompromised Multi-Master Replication is a Myth
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Warning: This section is about the CAP Theorem, so feel free to skip it. Do not operate heavy machinery while taking CAP Theorem.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Multi-master replication will always have compromises. The &lt;a href="https://en.wikipedia.org/wiki/CAP_theorem" rel="noopener noreferrer"&gt;CAP theorem&lt;/a&gt; states that between &lt;strong&gt;C&lt;/strong&gt;.onsistency, &lt;strong&gt;A&lt;/strong&gt;.vailability, and &lt;strong&gt;P&lt;/strong&gt;.artition-tolerance, you can never maintain all three at once.&lt;/p&gt;

&lt;p&gt;Well-implemented distributed databases document their claims and don't claim to violate the CAP theorem. These claims are typically AP (available and partition-tolerant) or CP (consistent and partition-tolerant). On a practical level, all distributed databases aim to be partition-tolerant, safely recovering from node and network failures.&lt;/p&gt;

&lt;p&gt;A partition is when one or more nodes are either down or can't communicate with all other nodes. These partitions can happen in unexpected ways, where the boundaries of communication is different for any given node.&lt;/p&gt;

&lt;p&gt;An AP database keeps data available during network partitions, but can produce conflicts and inconsistencies such as foreign references or incomplete transactions. A CP system does not produce conflicts (usually, check your guarantees) and keeps data consistent, but some reads or writes can be blocked during a network partition. RDBMS databases, like SQL, are typically CP, while document stores are more often AP.&lt;/p&gt;

&lt;p&gt;Conflict resolution is a business logic problem, and needs to be solved specifically in the context of the data being stored. If two writers are editing the same article during a network partition, a last-write-wins strategy could delete one of the editor's changes. In that particular case, you may want to resolve the conflicts manually with document-merge strategy. An AP database often resolves conflicts with a last-write-win strategy by default, so be mindful.&lt;/p&gt;

&lt;p&gt;MongoDB famously had ridiculous performance and replication claims when it first launched in 2009. &lt;a href="https://en.wikipedia.org/wiki/MongoDB#Technical_criticisms" rel="noopener noreferrer"&gt;It took quite a few years to clean up&lt;/a&gt;. I learned a lot in those days from &lt;a href="https://aphyr.com/posts/284-jepsen-mongodb" rel="noopener noreferrer"&gt;Aphyr's posts, exploring database clustering claims with his testing tool, Jespen&lt;/a&gt;. Beware of marketing-driven engineering products!&lt;/p&gt;

&lt;p&gt;In short, when selecting a distributed database product, make sure you understand their claims. There's no magic bullet when it comes to horizontal scaling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make a Plan for Scaling
&lt;/h2&gt;

&lt;p&gt;You can scale pretty high with a single application server and a single database server, but you should also have a plan for scaling up later. Implementing a scaling solution during development of an MVP introduces unnecessary complexity (violating several of my previous core beliefs) and is an example of &lt;a href="https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize" rel="noopener noreferrer"&gt;premature optimization&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on your business needs, you could scale horizontally, making it so that you could have any number of application servers and database servers (See the Multi-Master core belief above -- this can be complicated to get right). Horizontally scaling makes sense if you need to support many writes per second, and your users and data aren't logically siloed.&lt;/p&gt;

&lt;p&gt;You could also scale through siloed sharding. If your product primarily manages logically grouped users (a common case for sharding) each group can have a dedicated set of application servers and databases. Interactions between user groups is limited. This is one of the easier ways to scale.&lt;/p&gt;

&lt;p&gt;If your user numbers are capped, like in an IT intranet application, simply writing an efficient application is enough to scale to 10s of thousands of active users. You should still design your application in such a way that it doesn't matter how many instances you run at once for reasons of uptime and staged releases.&lt;/p&gt;

&lt;p&gt;Keep in mind, running multiple instances of your API against a single database server (or single master server with many read-servers) will only scale to a point. Eventually you'll exceed  your ability to write data to the database and will need to shard your users/data or use a distributed database.&lt;/p&gt;

&lt;p&gt;Knowing how you're going to scale up ahead of time will help you make implementation decisions during the MVP stage of your application. Remember, having to scale up is a good problem to have, and you'll have more resources to implement your plan later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Experience Matters (DX)
&lt;/h2&gt;

&lt;p&gt;At one of my first full-time programming jobs 20 years ago, I spoke with a senior developer about a problem I was having configuring the project for a niche QA use-case. They pointed me to a CLI program they wrote to manage that configuration. He was the only one using this tool so far, so I was shocked to see how &lt;em&gt;nice&lt;/em&gt; it was. He'd take the time to have self-documenting command-line arguments and a clear README that went over its purpose and usage.&lt;/p&gt;

&lt;p&gt;Why had he bothered to take the time to make this script so easy to use when he was the only user? Because developer experience matters, even just for himself, and he suspected others might find it useful eventually. At the time, I would have just slapped together a script, made all of the options constants that I would have to manually edit each time, and moved on.&lt;/p&gt;

&lt;p&gt;It left an impression, and I began taking more care in the experience of the software I was writing, because it usually payed dividends in time. I was never embarrassed to share my little tools and libraries with others.&lt;/p&gt;

&lt;p&gt;Years later, when I started regularly writing open source code, I took the time to see what successful open source projects included in their README. It's made a huge difference for my career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Core Beliefs
&lt;/h2&gt;

&lt;p&gt;When I started this blog post, &lt;a href="https://twitter.com/fritzy/status/1352494892069515266" rel="noopener noreferrer"&gt;I asked people what their core software beliefs were&lt;/a&gt;. I got some pretty good answers. Feel free to send me any additional thoughts or feedback below or at &lt;a href="https://twitter.com/fritzy" rel="noopener noreferrer"&gt;@fritzy&lt;/a&gt;. For more, follow me here, on Twitter, and on &lt;a href="https://github.com/fritzy" rel="noopener noreferrer"&gt;github.com/fritzy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I set out to explore and share some of my web architecture beliefs. Some of them are objective fact (like multi-master databases), some of them are value statements (DX matters), but they're all things that I keep in mind in order to quickly architect quality software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related
&lt;/h3&gt;

&lt;p&gt;A &lt;a href="https://chriskiehl.com/article/thoughts-after-6-years" rel="noopener noreferrer"&gt;similar article&lt;/a&gt; was published during the writing of this. There's a lot there that I agree with, but certainly not all of it. I don't endorse their views, but it's the kind of exercise that I'm encouraging with this article.&lt;/p&gt;

</description>
      <category>web</category>
      <category>architecture</category>
      <category>database</category>
      <category>api</category>
    </item>
    <item>
      <title>Introducing Ape ECS (js!)</title>
      <dc:creator>Nathan Fritz</dc:creator>
      <pubDate>Sun, 27 Sep 2020 03:36:11 +0000</pubDate>
      <link>https://forem.com/fritzy/introducing-ape-ecs-js-250o</link>
      <guid>https://forem.com/fritzy/introducing-ape-ecs-js-250o</guid>
      <description>&lt;p&gt;Whenever someone announces an ECS library, or really anything to do with ECS, the post must describe what ECS is. These posts always get it wrong because it's impossible to explain without mixing in bits of implementation. Even the &lt;a href="https://en.wikipedia.org/wiki/Entity_component_system"&gt;Wikipedia article&lt;/a&gt; falls into this trap. I will not break with tradition.&lt;/p&gt;

&lt;p&gt;First of all, you can find Ape ECS at &lt;a href="https://github.com/fritzy/ape-ecs"&gt;https://github.com/fritzy/ape-ecs&lt;/a&gt; and you can install it into your project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;ape-ecs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Okay, but what is ECS?
&lt;/h3&gt;

&lt;p&gt;ECS stands for Entity-Component-System, which name the parts of the paradigm. It's used in game and simulation development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Entities&lt;/strong&gt; are uniquely identified and are defined by which Components or Component instances are associated with them (ugh, we're already getting into implementation).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Components&lt;/strong&gt; are uniquely identified instances of data-types with association to an Entity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Systems&lt;/strong&gt; do work on Components.&lt;/p&gt;

&lt;p&gt;The idea is that you keep your logic separate from your data, unlike Object-Oriented Programming where you encapsulate your data with your logic. But how? Well, we'd have to get into implementation details.&lt;/p&gt;

&lt;p&gt;Generally you have a System which could be a function or a class (in Ape ECS you can override the built in System class or just use a function) that has a single job that it does like Gravity.&lt;/p&gt;

&lt;p&gt;Most implementations have a way of querying Entities and Components beyond just getting all of the entities or getting all of a Component of a given type. Minimally you can do a Join or Union to get all of the Entities that have at least a set of Component types. Some ECS implementations have more advanced queries, &lt;a href="https://github.com/fritzy/ape-ecs/blob/master/docs/Query.md"&gt;like Ape ECS Queries&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Gravity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ApeECS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;System&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentTick&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;frameInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GameLoop&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;getOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FrameInfo&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;entities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Position&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;Vector&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;execute&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;const&lt;/span&gt; &lt;span class="nx"&gt;entity&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;entities&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;vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vector&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;frameInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deltaTime&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;9.807&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&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;The magic of ECS is that our Gravity system works on anything that has a Vector and Position. We could make it as specific as we want, but what's more important is the things we don't care about. Gravity would work on any Entity that has those Components, whether it has a Sprite, AI, Weapon, Effect, whatever. We don't have to depend on a hierarchy of classes to determine whether Gravity works on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use ECS though?
&lt;/h3&gt;

&lt;p&gt;If your game is complicated, dynamic, or meant to be a simulation, a lot can be gained from separating your logic and your data. For one, you have dynamic composition of your entities.&lt;/p&gt;

&lt;p&gt;Want the player to go from running around as a human to controlling a mech? Easy, just add your PlayerControlled component to the mech entity. Want to mutate your character to have an extra arm? Just add an extra Arm component and the equipping System will deal with it just like the other two arms.&lt;/p&gt;

&lt;p&gt;Systems interact with each other more when they're decoupled. A bunch of them might act on or inspect the same Components, essentially piping inputs and outputs to each other. This leads to high levels of data-integration, which leads to &lt;a href="https://en.wikipedia.org/wiki/Emergent_gameplay"&gt;Emergent Behavior&lt;/a&gt;. In the example of the Gravity system, it would interact indirectly with a Movement system that used Vectors to update their corresponding Position. There's a story about many systems interacting with each other in Dwarf Fortress to kill cats that is a &lt;a href="https://www.youtube.com/watch?v=6yWf6BHqiWM"&gt;classic example&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;There are other benefits as well -- it tends to be more performant to run one function (System) which loops through many entities than it is to loop through many entities and run a series of methods on each. It's also easy to serialize your data and save your state when your data is separate. The Blizzard Overwatch architect talked about how it made it easier to make a &lt;a href="https://www.youtube.com/watch?v=W3aieHjyNvw"&gt;competitive network game using ECS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Okay, but Why Ape ECS?
&lt;/h3&gt;

&lt;p&gt;It's performant, it's flexible, and it has some neat features.&lt;/p&gt;

&lt;p&gt;Here is what makes it stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced Queries for entities.&lt;/li&gt;
&lt;li&gt;Persisted Queries (indexes) are updated as Entity composition changes.&lt;/li&gt;
&lt;li&gt;Component reference properties to Entities (EntityRef, EntitySet, EntityObject)

&lt;ul&gt;
&lt;li&gt;When a referenced entity is destroyed, the property is updated to null.&lt;/li&gt;
&lt;li&gt;Subscribe-able events for adding and removing references.&lt;/li&gt;
&lt;li&gt;Reverse query from entity to entity-components that reference it.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Not all systems need to run every frame.&lt;/li&gt;
&lt;li&gt;Export/import support for saving/restoring state with component-level serialization configuration.&lt;/li&gt;
&lt;li&gt;100% Test Coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I spent a lot of my hobby time in the last year, and especially quarantine, exploring prototypes to solving this problem to find the right implementation and features set.&lt;/p&gt;

&lt;p&gt;There are a bunch of other ECS implementations out there for JavaScript, but most of them are &lt;a href="http://vasir.net/blog/game-development/how-to-build-entity-component-system-in-javascript"&gt;fairly naive or merely instructive&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You could also use &lt;a href="https://ecsy.io/"&gt;Mozilla's ECSY&lt;/a&gt;, which isn't a bad way to go. Some of the devs have pledged to keep working on it despite &lt;a href="https://arstechnica.com/information-technology/2020/08/firefox-maker-mozilla-lays-off-250-workers-says-covid-19-lowered-revenue/"&gt;being layed-off&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ape ECS 1.0
&lt;/h3&gt;

&lt;p&gt;Today, I'm launching Ape ECS 1.0. The documentation (especially the API documentation) is comprehensive. It boasts 100% test coverage. I've run it through it's paces for usage and performance. Ape ECS is ready for you to use!&lt;/p&gt;

&lt;p&gt;I'm super happy to get this released, especially given how difficult this year has been. I'm excited to finally talk about it more broadly and call it 1.0!&lt;/p&gt;

&lt;p&gt;I look forward to hearing your questions, suggestions, and contributions. Open issues and pull requests &lt;a href="https://github.com/fritzy/ape-ecs"&gt;on Github&lt;/a&gt;. Feel free to poke me on &lt;a href="https://twitter.com/fritzy"&gt;Twitter @fritzy&lt;/a&gt; or Discord (Fritzy#5972). Please make suggestions for the documentation as well!&lt;/p&gt;

&lt;p&gt;Update 09/27: We had our first post-1.0 &lt;a href="https://github.com/fritzy/ape-ecs/pull/24"&gt;pull-request!&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next for Ape ECS?
&lt;/h3&gt;

&lt;p&gt;Software is never done! I will continue to work on Ape ECS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://github.com/fritzy/missileorders"&gt;example game Missile Orders&lt;/a&gt; is not finished yet, nor does it properly show off the benefits of ECS yet.&lt;/li&gt;
&lt;li&gt;I want to expand the benchmarks to cover queries, and use that as a basis for more optimizations.&lt;/li&gt;
&lt;li&gt;I plan on adding Commands, expand Events, and implement rollbacks and fast-forwards in order to support lag-resistant and corrective network support.&lt;/li&gt;
&lt;li&gt;The documentation needs corrections, more patterns, and examples.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to work on these things, please reach out!&lt;/p&gt;

&lt;h3&gt;
  
  
  Special Thanks
&lt;/h3&gt;

&lt;p&gt;Thanks to &lt;a href="https://twitter.com/benathon"&gt;Ben Morse&lt;/a&gt; for early implementation feedback, documentation suggestions, and the TypeScript definitions!&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://twitter.com/DrawnByJaime"&gt;Jaime Robles&lt;/a&gt; for the banner image!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ecs</category>
      <category>gamedev</category>
      <category>simulation</category>
    </item>
  </channel>
</rss>
