<?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: brandon flowers</title>
    <description>The latest articles on Forem by brandon flowers (@headwinds).</description>
    <link>https://forem.com/headwinds</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%2F9292%2F68402.jpeg</url>
      <title>Forem: brandon flowers</title>
      <link>https://forem.com/headwinds</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/headwinds"/>
    <language>en</language>
    <item>
      <title>Cave Troll: Cracking React, XState &amp; PusherJS Communication</title>
      <dc:creator>brandon flowers</dc:creator>
      <pubDate>Tue, 24 May 2022 15:56:09 +0000</pubDate>
      <link>https://forem.com/headwinds/heartbeat-cracking-react-xstate-pusherjs-communication-3bac</link>
      <guid>https://forem.com/headwinds/heartbeat-cracking-react-xstate-pusherjs-communication-3bac</guid>
      <description>&lt;p&gt;As we develop an app, we enjoy a sense of flow, connecting functions following our mental models of how we believe the code should all fit together. It can be frustrating to get bogged down by functions that don't behave as we expect them to; especially when we adopt some new library that has promised us to save us time and tears.&lt;/p&gt;

&lt;p&gt;I've been experimenting with the mechanics that drive modern 2D multiplayer experiences that feature machine learning taking inspiration from &lt;a href="https://wildermyth.com/" rel="noopener noreferrer"&gt;Wildermyth&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm building with React, PusherJS, XState, RabbitMQ, and a recommendation engine built in Python. The goal is have them all work in harmony to provide a non-blocking experience where long jobs like reinforcement learning tasks are processed in the background and the user can perform other activities and receive feedback on their progress.&lt;/p&gt;

&lt;p&gt;In this post, I'm only going to going share how React can subscribe to PusherJS events via XState, and update the UI once the work has completed. I've been a big fan of XState's visualization tool using it Storybook for the past year and recently started using the new Stately tools for VS Code as well as kicking the tires of their hosted editor.&lt;/p&gt;

&lt;p&gt;I won't go into the backend of this project, but it's important to say a few things so that you can understand why I wanted to use PusherJS. So I will mention that the setup is a pipeline with 4 flask apps: API, producer, consumer, and a recommendation model. I wanted a pipeline flow so that I can add and remove libraries to experiment and transform the data. Depending on what I want to play with, I can try different models and other tasks like text processing.&lt;/p&gt;

&lt;p&gt;With this backend in place, I have developed the frontend app to make Restful requests and subscribe to PusherJS which will eventually receive an update.&lt;/p&gt;

&lt;p&gt;Since I'm building a 2D game, the app will make requests to generate maps and predict optimized walking paths but the UI will not be blocked because the final response will be picked up from a PusherJS subscription.&lt;/p&gt;

&lt;p&gt;Now how do we get PusherJS to update our XState machine within React? But first, why XState as my state management weapon of choice?&lt;/p&gt;

&lt;p&gt;Similar to what attracted me to functional programming, I liked that &lt;a href="https://xstate.js.org/docs/guides/introduction-to-state-machines-and-statecharts/" rel="noopener noreferrer"&gt;XState is deterministic&lt;/a&gt; which basically means that I should know where I am, where I came from, and where I'm going in the code base at all times. It also comes with a &lt;a href="https://stately.ai/viz" rel="noopener noreferrer"&gt;visual editor&lt;/a&gt;, and finally provides clear examples of how to reduce complexity and &lt;a href="https://xstate.js.org/docs/tutorials/reddit.html#splitting-machines" rel="noopener noreferrer"&gt;split up machines&lt;/a&gt; making it more readable and testable parts; props to &lt;a href="https://twitter.com/steveruizok/status/1509221944759046152" rel="noopener noreferrer"&gt;Steve Ruizok&lt;/a&gt; and his multiplayer XState experiments.    &lt;/p&gt;

&lt;p&gt;I wasn't satisfied with my first attempts to make this happen. I tried several approaches to position the machine inside and outside the React functional component. I could trigger the task and have my pipeline return the result to a bound instance of PusherJS within React.&lt;/p&gt;

&lt;p&gt;The PusherJS subscription would then send an XState event with the result as a payload and my context should be updated but unfortunately it failed to update, and thus my view wouldn't react to the change.&lt;/p&gt;

&lt;p&gt;So I turned to google to see if anyone else was having this issue, and discovered a few interesting posts including these two: &lt;a href="https://github.com/statelyai/xstate/issues/549" rel="noopener noreferrer"&gt;How should a machine interact with websocket?&lt;/a&gt; and &lt;a href="https://www.kevinhxu.com/xstate-websocket-machine/" rel="noopener noreferrer"&gt;XState Websocket Machine&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It's a bit disappointing to see that Github thread locked but it basically inspired this article so please use the comments below if you have any questions; not to say I'll have all the answers; but we can certainly struggle together.&lt;/p&gt;

&lt;p&gt;I'll share the section of my state machine that I borrowed from glenndixon's post and show how I worked through this communication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const caveTrollMachine = createMachine(
  {
    context: initialContext,
    invoke: {
      id: 'socket',
      src: (context, event) =&amp;gt; (callback, onEvent) =&amp;gt; {
        const { channel } = context;

        setTimeout(function () {
          console.log('got here after 1 sec ');
          callback({ type: 'FETCH_USER_MAP' });
        }, 1000);

        const onGetMapSuccessHandler = data =&amp;gt; {

          const {
            result: { map },
          } = data;

          callback({ type: 'PUSHER_FOUND_MAP_SUCCESS', generatedMap: map });
        };

        PusherService.bindToPusher(channel, c.GET_MAP_SUCCESS, onGetMapSuccessHandler);
      },
    },
    id: 'caveTroll',
    initial: 'idle',
    states: {
      idle: {
        on: {
          FETCH_USER_MAP: {
            target: 'loadingUserMap',
          },
          SAY_HI: {
            target: 'sayingHi',
          },
        },
      },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also installed the XState Chrome extension so that I could use the machine visualization via Chrome dev tools but found it not as effective as the hosted Stately visualizer. In fact, the many times the chrome extension would fail to render and all I saw was &lt;code&gt;"Resetting..."&lt;/code&gt; in the window. &lt;/p&gt;

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

&lt;p&gt;Once I could watch the machine, I could finally see the actual state, and was able to add the missing on listener to that state so that it would hear when PusherJS had updated with the result of my request.&lt;/p&gt;

&lt;p&gt;I left my &lt;code&gt;SAY_HI&lt;/code&gt; event in that screenshot to show how I start by building simple experiments. It's always nice to follow &lt;code&gt;hello world&lt;/code&gt; first approach to programming where I simply want to get some text to appear and then add more complexity once I understand how it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on: {
  FETCH_MAP_SUCCESS: {
   target: 'idle',
   actions: assign({ 
      tileModels: onTileModelsUpdateHandler, 
      generatedMap: onGeneratedMapHandler, 
      isMapGenerated: true }),
   },
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything was working in my state chart as expected except my &lt;code&gt;onTileModelsUpdateHandler&lt;/code&gt;. For some reason, it appeared that when this function fired, it did update the models with the proper x,y coordinates from the DOM but then suddenly the entire array would be empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  useEffect(() =&amp;gt; {
    if (tileModels.length &amp;gt; 0) {
      const el = document.getElementById(`tile8`);
      if (el &amp;amp;&amp;amp; tileModels?.length &amp;gt; 0) {
        const updatedTileModels = tileModels.map(model =&amp;gt; {
          const newEl = document.getElementById(`tile${model.id}`);
          const boundingRect = newEl.getBoundingClientRect();
          return { ...model, x: boundingRect.x, y: boundingRect.y };
        });
        send({ type: 'UPDATE_TILE_MODELS', updatedTileModels });
      }
    }
  }, [tileModels]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I ever get stuck on a coding problem, the first thing I do is start to remove the complexity, and break it down into a more simple task . I'll never forget when I was pair-programming with another developer and she asked, "What's the delta?".&lt;/p&gt;

&lt;p&gt;So I started to refactor, rewrite, and remove some of the deltas aka the differences and complexity. Instead of drawing a grid, I simplified it to one row. I changed my design from a field to single tunnel, a cave.&lt;/p&gt;

&lt;p&gt;With the cave model, I didn't need the grid function, and once I replaced it with a function that drew a row everything started to work again!&lt;/p&gt;

&lt;p&gt;By eliminating the grid, I was able to identify it and not the XState machine as the source of my vanishing model problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const createGrid = () =&amp;gt; {
    const grid = [];
    // credit https://stackoverflow.com/questions/22464605/convert-a-1d-array-to-2d-array
    // but be careful here since splice is destructive - make sure you don't destroy the original array!!!
    // important lesson for xstate that you don't mutate the original array!!!
    const cloneModels = [...models];
    // vs using just models
    while (cloneModels.length) grid.push(cloneModels.splice(0, totalInRow));
    return grid;
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't realize that I was mutating the original array through the destructive act of using splice. Of course this is one of the dangers of &lt;code&gt;copypasta&lt;/code&gt; from Stackoverflow, and I did review the source before implementing it, and it appeared harmless. I've since added &lt;a href="https://immutable-js.com/" rel="noopener noreferrer"&gt;ImmutableJS&lt;/a&gt; into the mix which I know is a bit controversial because it's not maintained but that doesn't mean it doesn't work. I have another large library of game asset datasets built on top of it and have never had issue with it. &lt;/p&gt;

&lt;p&gt;After cloning the array, I was then able to bring back the grid, and once again everything worked as expected. I had assumed the context within the machine was immutable. I want to explore using XState's guards in the future to see if I could have received some feedback and data protection which could have helped point to my grid function instead of having to tear up my machine work digging for the cause. &lt;/p&gt;

&lt;p&gt;By refactoring the machine, it did help me understand much more about how it works and definitely improved my work flow and ability to detect and squash bugs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3os7dou31g18r4ep59m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3os7dou31g18r4ep59m.png" alt="Frodo and the cave troll" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A Guide for Guides: Building a Fun Java App with Tomcat &amp; Maven with the Community Edition of IntelliJ</title>
      <dc:creator>brandon flowers</dc:creator>
      <pubDate>Thu, 25 Nov 2021 21:25:20 +0000</pubDate>
      <link>https://forem.com/headwinds/a-guide-for-guides-building-a-fun-java-app-with-tomcat-maven-with-the-community-edition-of-intellij-28cb</link>
      <guid>https://forem.com/headwinds/a-guide-for-guides-building-a-fun-java-app-with-tomcat-maven-with-the-community-edition-of-intellij-28cb</guid>
      <description>&lt;p&gt;Often, when reading tech articles, we long for cliff notes and tips in the margins. This is where comments and discussion threads can be especially helpful.&lt;/p&gt;

&lt;p&gt;I've embarked on a 100 days of code challenge to become more proficient in Java, and am now 30 days. So today, my IntelliJ Ultimate license expired and I'm faced with two options: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask my manager for a license&lt;/li&gt;
&lt;li&gt;Continue with the free community edition &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since I'm considered mainly a frontend dev on my team, asking for a license is a bit of stretch but my manager has seen enough of my full-stack experiments with Node or Python to know that I do have the potential contribute end to end features in Java too. &lt;/p&gt;

&lt;p&gt;I'm especially interested in building internal tools and dashboards to improve the visibility into our system. For instance, to allow our Trading team to make informed decisions about when they can launch email campaigns based on the status of multiple complex, orchestrated cron jobs that need to complete successfully before it's safe to proceed, targeting over a million customers with our latest deals.   &lt;/p&gt;

&lt;p&gt;So I have asked, and while I wait for the green light (usually a couple days within any large enterprise) I have some time to explore the free community edition and see what I can build in the meantime with what I have. &lt;/p&gt;

&lt;p&gt;During this 100 day learning project, I've been bouncing between two toy apps that help me learn. One app is command line chat bot app and the other is maven-based stats app that requires Tomcat so that can run a web server to display web pages. &lt;/p&gt;

&lt;p&gt;This stream of consciousness post will eventually get to the steps it took me to render some html via Java. But it's less about rendering, and really only a final check before deploying to GCP. For the past few years, I've been increasingly interested in the shape of data over attempting to visualize it. I'm more interested in the complexity of how distributed systems communicate; how is the data exchanged and safe guarded so that the system can always recover and there is a sense of consistent flow where thresholds are rarely reached.   &lt;/p&gt;

&lt;p&gt;When I tried to run this web app with the community edition, I was immediately struck by the lack of run button that was present  in the Ultimate edition. I could not figure out how to add the Tomcat server which was easy to do in the licensed version. I tried both Smart Tomcat and Tomcat Runner plugins without success on the mac.&lt;/p&gt;

&lt;p&gt;After a googling adventure where I stumbled upon this article &lt;a href="https://www.theserverside.com/video/Step-by-step-Maven-Tomcat-WAR-file-deploy-example"&gt;Step by step Maven Tomcat WAR file deploy example&lt;/a&gt; by Cameron Mackenzie which lead me to his github for the &lt;a href="https://github.com/cameronmcnz/rock-paper-scissors"&gt;Rock Paper Scissors github repo&lt;/a&gt; which seemed like a fun sample project to get up and running.&lt;/p&gt;

&lt;p&gt;Now this is the part where I step in as a guide as say that while I recommend reading his article first, you may not need to follow his step by step instructions. In fact, I tried and faltered. Instead, I did the following. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;brew install tomcat &lt;/li&gt;
&lt;li&gt;cd /usr/local/Cellar/tomcat/10.0.13/bin/&lt;/li&gt;
&lt;li&gt;catalina start&lt;/li&gt;
&lt;li&gt;go to your browser and see localhost:8080 &lt;/li&gt;
&lt;li&gt;refer to Cameron's step about grabbing the roshambo.war file from the specific branch&lt;/li&gt;
&lt;li&gt;paste that war into /usr/local/Cellar/tomcat/10.0.13/libexec/webapps&lt;/li&gt;
&lt;li&gt;notice that when you paste in the war, it creates a folder and expands its contents&lt;/li&gt;
&lt;li&gt;go back the browser and view localhost:8080/roshambo&lt;/li&gt;
&lt;li&gt;rename roshambo folder to rps and try to view it again&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll also &lt;a href="https://www.youtube.com/watch?v=8xjWToEoNck"&gt;credit this youtube&lt;/a&gt; which tipped me off on how to copy the war into Tomcat.  &lt;/p&gt;

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

&lt;p&gt;And voila! I have a working rock paper scissors app in my browser which is gives me enough confidence to return my app and continue experimenting.   &lt;/p&gt;

&lt;p&gt;Now, the final part that I wanted today was the ability for Maven to build the war file and move it Tomcat. And thanks to this &lt;a href="https://stackoverflow.com/questions/369639/how-to-copy-war-to-tomcats-webapps-directory-using-maven"&gt;stackoverflow thread&lt;/a&gt; I was able to tweak the ship for my mac:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;plugin&amp;gt;
  &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.2.0&amp;lt;/version&amp;gt;
  &amp;lt;configuration
&amp;lt;outputDirectory&amp;gt;/usr/local/Cellar/tomcat/10.0.13/libexec/webapps/&amp;lt;/outputDirectory&amp;gt;
  &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simply calling &lt;code&gt;mvn package&lt;/code&gt; performs the desired results. I decided to change a few values and learn a bit about the system.   &lt;/p&gt;

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

&lt;p&gt;Again, all I want to use Tomcat as final check for little UI that I have, and mainly use IntelliJ for the big services backing it. I've worked alongside many devs who would be entirely comfortable with no UI whatsoever but I prefer at least some parse, minimal controls that empower non-technical people to make mighty leaps of faith. &lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Dig Through Python And Create Game Art with Playscii</title>
      <dc:creator>brandon flowers</dc:creator>
      <pubDate>Thu, 10 Jun 2021 16:37:00 +0000</pubDate>
      <link>https://forem.com/headwinds/dig-through-python-and-create-game-art-with-playscii-5dlp</link>
      <guid>https://forem.com/headwinds/dig-through-python-and-create-game-art-with-playscii-5dlp</guid>
      <description>&lt;p&gt;One of the best ways to learn any language is to dig through the source code of a full application. It may be daunting at first, but if you have a sense of where the application begins, you should be able to find the main application file. From there, you can start to explore various paths and learn how it operates. &lt;/p&gt;

&lt;p&gt;I have been following the &lt;a href="http://vectorpoem.com/"&gt;playscii&lt;/a&gt; project (and several artists using it) on Twitter and wanted to try the tool myself. &lt;/p&gt;

&lt;p&gt;I purchased it for the paltry default sum of $2, and was pleasantly surprised to see that it includes the source code along with the compiled app.  &lt;/p&gt;

&lt;p&gt;Playscii can be used to create art that is ideal for tile-based games.&lt;/p&gt;

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

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



&lt;/p&gt;

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

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



&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;First, I tried to launch the application but my Mac refused to open this app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“Playscii” cannot be opened because the developer cannot be verified.

macOS cannot verify that this app is free from malware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok the app wasn't going to work, but what about the source code?! As an ever-learning python dev, the source code is much more valuable than any compiled tool.  &lt;/p&gt;

&lt;p&gt;My first attempt to install the source code failed unfortunately but I wasn't deterred yet. I have had other pythons app fail the first time and knew I might be able to get past this hurdle with a little determination.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 install -r requirements.txt 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It did not finish building the wheel. I waited a half hour and then abandoned this approach. Next, I turned to googling and discovered what appears to be the &lt;a href="https://heptapod.host/jp-lebreton/playscii"&gt;original repo&lt;/a&gt; along with another dev's update to it. So thanks to &lt;a href="https://github.com/michael-lazar/playscii"&gt;Michael Lazar's build&lt;/a&gt; I was to able to use his updated requirements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;appdirs==1.4.0
gprof2dot==2015.12.1
numpy==1.20.1
Pillow==8.1.2
PyOpenGL==3.1.5
PySDL2==0.9.7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time all the requirements installed without issue on my Mac (Catalina with Python 3.9). Then I tried to run the app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 playscii.py 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This didn't work, and my next hoop was related to the &lt;code&gt;sdlmixer&lt;/code&gt; library. I can give live without audio support, and simply decided to see if I could comment out that out and try again.  &lt;/p&gt;

&lt;p&gt;I only had to do a few tweaks with the main playscii file to disable the audio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# from audio import AudioLord
# from sdl2 import video, sdlmixer
from sdl2 import video
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be careful to disable the audio but not the ui here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# self.ui,self.al = None, None
# self.al = None
self.ui = None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And presto! ✨&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;As you can see from own tweet, having a little bit of friction in your game that an eager dev can overcome on their own actually encourages them to promote to your work. &lt;/p&gt;

&lt;p&gt;Ideally though, everything should just work though. But you wouldn't be able to focus on the core value if you had to manage every build across multiple platforms as an indie developers; that's why other indie developers are here to help! &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Composing React Hooks</title>
      <dc:creator>brandon flowers</dc:creator>
      <pubDate>Sun, 02 May 2021 14:59:22 +0000</pubDate>
      <link>https://forem.com/headwinds/composing-react-hooks-47b1</link>
      <guid>https://forem.com/headwinds/composing-react-hooks-47b1</guid>
      <description>&lt;p&gt;As a leader, working with several bootcamp developers entering their second or third years as a professional javascript developers, we have a certain responsibility to guide them and introduce computer science concepts that they may have missed in their compressed education. &lt;/p&gt;

&lt;p&gt;There is a natural interest to refine their craft by diving into Functional Programming. After a solid year or two of Javascript programming, they would have mastered enough of the fundamentals to be open to learning more.  &lt;/p&gt;

&lt;p&gt;They may get turned on to FP after reading a blog post or through co-workers. The first steps in learning FP would be to read a book and soak up a few videos on the basic principles. Once you have the concepts, then you can begin experimenting with them. &lt;/p&gt;

&lt;p&gt;To the gain of the benefits of FP, you do not need a library right away. Many FP practices, like writing more testable, &lt;code&gt;pure functions&lt;/code&gt; that when given an input always return the same output, can be applied in your daily coding without importing an another library. &lt;/p&gt;

&lt;p&gt;Adding a library like &lt;code&gt;react-hook-compose&lt;/code&gt; or &lt;code&gt;ramda&lt;/code&gt; will give you extra functionality when you are ready for it. They do require extra brain power so I would not recommend approaching them until after you have absorbed at least the basics of FP. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is composition?
&lt;/h2&gt;

&lt;p&gt;Have you ever realized that after writing within the same React file, your code has swelled to hundreds of lines and its becoming unwieldy to manage? This becomes even more pronounced when you try to share this code with a fellow developer who shrieks at the size of your commit with appropriate emoji. &lt;/p&gt;

&lt;p&gt;We want to refactor large files into smaller smaller so that they are easier to review and test.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Ramda
&lt;/h2&gt;

&lt;p&gt;I had invested several years in learning the ImmutableJS library and feel that I know it well enough that I wanted to experiment with a new FP library. In my mind, ImmutableJS and Ramda are comparable libraries. There is some drama about ImmutableJS being unmaintained but I have never had an issue with it and sometimes a library can reach a certain maturity without needing more work. &lt;/p&gt;

&lt;p&gt;My first impression of Ramda is that the documentation already feels more like Clojure which I've studied in the past. It mentions terms like or unary or &lt;a href="https://medium.com/@igorwojda/function-arity-4be140702f1d"&gt;arity&lt;/a&gt; which are probably new language to javascript developers unless you have already learned other FP focussed languages like Haskell, Clojure, or Elm. Like Clojure, Ramda offers the javascript a new world of functionality, providing more tools to safely transform data without worrying about mutation.     &lt;/p&gt;

&lt;p&gt;The Ramda library provides a &lt;a href="https://ramdajs.com/docs/#compose"&gt;compose function&lt;/a&gt; which allows you to take smaller files and bring them together through incremental steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Poster = ({ id, coverUrl, title }) =&amp;gt; {
  return (
    &amp;lt;ListItem key={id}&amp;gt;
      &amp;lt;Image url={coverUrl} a11y={title} width="100" /&amp;gt;
    &amp;lt;/ListItem&amp;gt;
  );
};

const makePosters = map(Poster);
const getPoster = pick(["id", "coverUrl", "title"]);
const getPosters = map(getPoster);
const TitleList = compose(makePosters, getPosters);

const Posters = ({ tvSeriesDataset }) =&amp;gt; (
  &amp;lt;Column&amp;gt;
    &amp;lt;SubHeadline size="large"&amp;gt;TV Series&amp;lt;/SubHeadline&amp;gt;
    &amp;lt;List customClass="list"&amp;gt;{TitleList(tvSeriesDataset)}&amp;lt;/List&amp;gt;
  &amp;lt;/Column&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've prepared a &lt;a href="https://codesandbox.io/s/ramda-react-hooks-ikoni"&gt;Ramda codesandbox exploring how to compose&lt;/a&gt; several react functions. For instance, we can write a list component in one file and a list item component in another file. As the author, this can become subjective when is a file too small? In my case, I decided to write them as separate functions to be exported and re-used by other components, but I left them in one file because the line count was already under 100.   &lt;/p&gt;

&lt;p&gt;Along with compose, this codesandbox also features various ways to transform the data at each step of the composition. I started this experiment by simply googling "codesandbox ramda" and leveraged some code from other authors giving them credit within the readme.  &lt;/p&gt;

&lt;h2&gt;
  
  
  react-hooks-compose
&lt;/h2&gt;

&lt;p&gt;This library is almost self explanatory. It does what you would expect it to do. Similar to compose in Redux, you can take a presentational component and apply several hooks to it. &lt;/p&gt;

&lt;p&gt;What is the motivation to use compose? Through compose, we can write hooks external to our presentation and re-use them within other components. In this experiment, I take 3 hooks: useState, useQuery, and useMutation and combine them with a presentation component. Each part is a separate file.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;composeHooks&lt;/code&gt; can add hooks to our presentational component following this pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ViewComponentWithHooks = composeHooks(({ myQuery, myMutation}) =&amp;gt; ({
  useCaptureInput: () =&amp;gt; useCaptureInput(),
  useQuery: () =&amp;gt; useQuery(myQuery),
  useMutation: () =&amp;gt; useMutation(myMutation)
}))(ViewComponent);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I had some fun creating this &lt;a href="https://codesandbox.io/s/apollo-react-compose-hooks-teg9o"&gt;react-hooks-compose codesandbox&lt;/a&gt; which displays some of my favourite recent TV series. Most of these series were recommended by friends. &lt;/p&gt;

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

&lt;p&gt;Over the last year, I have watched a team of mainly bootcamp developers grow to a point where I feel like they have become peers and can sagely criticize the DRYness of my own programming. We are in the process of introducing FP at &lt;a href="https://www.loblawdigital.co/careers"&gt;Loblaws Digital&lt;/a&gt;, beginning with the fundamentals and, through these experiments, I'm attempting to convince them (and myself) that should introduce Ramda into our codebase.  &lt;/p&gt;

&lt;p&gt;It's not enough for me to mention ImmutableJS or Ramda in a meeting, I want my team to follow my example and experiment with them. I hope they see this post as motivation to create their own codesandbox so that I in turn can learn from them.   &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>functional</category>
      <category>react</category>
      <category>hooks</category>
    </item>
    <item>
      <title>If you've never looked at Clojure before...</title>
      <dc:creator>brandon flowers</dc:creator>
      <pubDate>Tue, 14 Aug 2018 14:30:58 +0000</pubDate>
      <link>https://forem.com/headwinds/if-youve-never-looked-at-clojure-before-5158</link>
      <guid>https://forem.com/headwinds/if-youve-never-looked-at-clojure-before-5158</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvegtv2obw4v6wab0d5r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvegtv2obw4v6wab0d5r.jpg" alt="women of nasa lego" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've never looked at Clojure before, this brief article may be your first taste and I hope you savour the experience. Clojure is an alternative to Java. It features interop with Java meaning you can access core Java functions within Clojure. It is a server side language and thus you would also need either Javascript or ClojureScript to write web-based client code. &lt;/p&gt;

&lt;p&gt;I'm working on a &lt;a href="https://github.com/headwinds/clojure-shed" rel="noopener noreferrer"&gt;series of Clojure &amp;amp; ClojureScript lessons&lt;/a&gt; to help me learn the language, and I've completed the &lt;a href="https://glacial-badlands-20785.herokuapp.com/" rel="noopener noreferrer"&gt;first lesson&lt;/a&gt; introducing map, filter &amp;amp; reduce which I'd like to share with you. &lt;/p&gt;

&lt;p&gt;Why should you learn Clojure? If you are a fan of Functional Programming design patterns, you will appreciate the immutable nature of Clojure functions and its FP approach to server side development producing highly testable code. Like Python, Clojure also &lt;a href="https://www.braveclojure.com/getting-started/" rel="noopener noreferrer"&gt;features a REPL&lt;/a&gt; where you can experiment and test functions of your program vastly speeding up development.&lt;/p&gt;

&lt;p&gt;After a few weeks of writing Clojure and receiving valuable feedback from the much more seasoned Clojure devs at &lt;a href="https://www.todaqfinance.com/" rel="noopener noreferrer"&gt;TODAQ&lt;/a&gt;, I've managed to get several pull requests merged into our master branch and I've mainly learned to simplify my Clojure functions by pulling out complex sections and breaking them up into smaller, more manageable functions, increasing code readability. Once you begin to refactor deeply nested functions, all those braces begin to make sense and you can achieve some nice terse, code clarity.  &lt;/p&gt;

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