<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yuta Miyama</title>
    <description>The latest articles on DEV Community by Yuta Miyama (@kenzan100).</description>
    <link>https://dev.to/kenzan100</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%2F439334%2F91f978ec-771c-453a-a651-334070aa9ec5.jpeg</url>
      <title>DEV Community: Yuta Miyama</title>
      <link>https://dev.to/kenzan100</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kenzan100"/>
    <language>en</language>
    <item>
      <title>One week SRE transition crash course</title>
      <dc:creator>Yuta Miyama</dc:creator>
      <pubDate>Mon, 21 Mar 2022 07:05:52 +0000</pubDate>
      <link>https://dev.to/kenzan100/one-week-sre-transition-crash-course-4hd5</link>
      <guid>https://dev.to/kenzan100/one-week-sre-transition-crash-course-4hd5</guid>
      <description>&lt;p&gt;&lt;strong&gt;This is my story.&lt;/strong&gt; I’ve been developing various web applications for the past 5 years. Size and domain vary, but most of the time, my primary responsibility is to “ship features”.&lt;/p&gt;

&lt;p&gt;Just at the beginning of this month, I transitioned into SRE (Site Reliability Engineer) role. The terminology and its practice were popularized by Google - &lt;a href="https://sre.google/"&gt;https://sre.google/&lt;/a&gt; I won’t try to explain what’s already best explained by them.&lt;/p&gt;

&lt;p&gt;This blog is to share how my first week went.&lt;/p&gt;

&lt;p&gt;I thought I could give u*&lt;em&gt;nique insights into how a seasoned software developer can quickly ramp up himself when changing the course of his career&lt;/em&gt;*.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8iLEwUj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8l42vl93aj753a3qd5q4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8iLEwUj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8l42vl93aj753a3qd5q4.png" alt="Image description" width="880" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Can this happen in ONE WEEK?&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How product developers can lose sight of a system’s runtime
&lt;/h1&gt;

&lt;p&gt;First of all, a bit of justification on why this transition is not a trivial one.&lt;/p&gt;

&lt;p&gt;Having been a web application engineer for some time, &lt;strong&gt;my focus has been mostly around the codebase&lt;/strong&gt;; the static snapshot of the system without deep-dive into the runtime.&lt;/p&gt;

&lt;p&gt;I’m not saying I didn’t pay attention to where the code is deployed, how to monitor them, etc. My point is that &lt;strong&gt;my “most important priority” has been to come up with a scalable “domain model” that’s separated from the underlying system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iSmlak6M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvvb2z3hpsccwe8k1kh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iSmlak6M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvvb2z3hpsccwe8k1kh7.png" alt="Image description" width="880" height="393"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Divide enables focus, takes away the holistic understanding.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This tendency is exacerbated by having worked for a bigger company.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I code, will be deployed to some virtual machine owned by Tier 1 Cloud providers. They have their own abstractions on these machines. This is not inherent to the big companies, but due to the sheer scale of the system, new failure patterns emerge from the distributed architecture.&lt;/p&gt;

&lt;p&gt;This is one of the reasons why I need to give myself a ramp-up time, to familiarize myself with the runtime.&lt;/p&gt;

&lt;h1&gt;
  
  
  Feature shipping mentality
&lt;/h1&gt;

&lt;p&gt;There’s another, much more significant reason why this transition is hard.&lt;/p&gt;

&lt;p&gt;In a company with more than thousands of employees, often times &lt;strong&gt;the department to own the “feature shipping speed” is different from the department which owns the Core SLOs (Service Level Objectives) of the underlying component&lt;/strong&gt;. I won’t debate if that’s a good thing or not. This separation certainly enables the concentration and focus of each developer.&lt;/p&gt;

&lt;p&gt;However, this has a hidden cost. If you develop too much of a “feature shipping mentality”, you might be cutting a scope that’ll actually save your day when the release happens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X3yDX40Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npb4nhpa1iaq7d6go9ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X3yDX40Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npb4nhpa1iaq7d6go9ao.png" alt="Image description" width="880" height="379"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don’t just ship code. Duh.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Three steps to start your SRE journey
&lt;/h1&gt;

&lt;p&gt;Enough about the background. Below are the three steps I discovered, to maximize the “throughput” of my learning. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Pick up the terminology
&lt;/h2&gt;

&lt;p&gt;At this stage, focus on the two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What and how many layers of abstractions are there to deal with?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What are the rough dependencies (topology) of each runtime, at various layers of abstractions?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bCDOCM3p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pglxcjozmifqkynajsr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCDOCM3p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pglxcjozmifqkynajsr.png" alt="Image description" width="880" height="365"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;One thing I find amusing is that libraries meant for infrastructure (non-end-user facing in general) sometimes have wild names I have no idea what it’s doing.&lt;/p&gt;

&lt;p&gt;It’s not straightforward to unpack these random terminologies. In order not to get lost in its randomness, pay attention to the explanation by its layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Put yourself in the shoes of the incident responder.
&lt;/h2&gt;

&lt;p&gt;Once your SRE life begins, you'll be paged for a wide variety of things; its breadth and depth vary significantly.&lt;/p&gt;

&lt;p&gt;It's almost certain that nobody can prepare for all the possible causes. Then, the question becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the “incident lifecycle” you can generalize? (Detection, Early impact assessment, offending component identification, …) use your own words so that the learnings stick to your brain.&lt;/li&gt;
&lt;li&gt;In each stage of the incident unfolding, what’s the focus you have to have? Depending on the size/domain of your role, you might be wearing different hats during the lifecycle of an incident.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mmYBjSCY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9so306030t749tdg0ouh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mmYBjSCY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9so306030t749tdg0ouh.png" alt="Image description" width="880" height="356"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  3. Know ways to keep filling the gaps
&lt;/h2&gt;

&lt;p&gt;Finally, as it was the same for application development, nothing is set in stone. Industry’s practice,  tooling, and even preferred incident response communication strategy might change.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lean on others. Ask them what they find most useful when they started this journey.&lt;/li&gt;
&lt;li&gt;Look for the industry's go-to books. Buy some to get you started, and buy some more for the reference you can use long-term.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;In this article, I made an attempt to explain how one can transition himself to the SRE role. It turned out to be much more generic than I imagined. Though, I believe this is a good piece of advice 😇 Hope you find it useful too.&lt;/p&gt;

&lt;p&gt;This article is written with Suiko, a note app that grows with your thoughts.&lt;/p&gt;

&lt;p&gt;This article was first drafted using a note app called “Suiko”. If you’re interested in how to craft your writings, please join the app beta testing form below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kenzan100.substack.com/p/ive-created-an-app-optimized-for"&gt;https://kenzan100.substack.com/p/ive-created-an-app-optimized-for&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sre</category>
      <category>devops</category>
    </item>
    <item>
      <title>I’ve created an app optimized for drafting articles. On your smartphone.</title>
      <dc:creator>Yuta Miyama</dc:creator>
      <pubDate>Sat, 19 Feb 2022 11:51:03 +0000</pubDate>
      <link>https://dev.to/kenzan100/ive-created-an-app-optimized-for-drafting-articles-on-your-smartphone-2g9f</link>
      <guid>https://dev.to/kenzan100/ive-created-an-app-optimized-for-drafting-articles-on-your-smartphone-2g9f</guid>
      <description>&lt;p&gt;(Originally written in &lt;a href="https://kenzan100.substack.com/"&gt;https://kenzan100.substack.com/&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hello! Let me share an app I’ve created, for drafting articles with ease.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m calling for alpha testers, who’d like to give this app a try. If you’re interested, please contact me via &lt;a href="https://forms.gle/aPh51kDohsS3H9dw7"&gt;this Google Form&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  First. On the difficulty of writing long, quality sentences.
&lt;/h2&gt;

&lt;p&gt;Usually, I have many fragmented thoughts in my head; some are potentially good, some are probably bad that doesn’t lead anywhere :)&lt;/p&gt;

&lt;p&gt;The problem, is I don’t know which one is which.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2v194BI6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/416q0ykhz4t29c5hfj6e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2v194BI6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/416q0ykhz4t29c5hfj6e.png" alt="Image description" width="880" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For me, the only way to tell between these two, is to “put it out there” for others to read. Only when I write them with the audience in mind, I can test the texts to its potential.&lt;/p&gt;

&lt;p&gt;Now, the question becomes how to cross that chasm. I need some amount of momentum and continuity to keep crossing the chasm. Make it “good enough” for others to at least make sense of what I’m trying to say.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dEPTcTpD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oem01kyv6fp0gf0plch3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dEPTcTpD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oem01kyv6fp0gf0plch3.png" alt="Image description" width="880" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s a sharp “cliff” between the random thoughts that only exist in my head, and the carefully crafted sentences that convey the points of these ideas.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why it is difficult to form an article
&lt;/h1&gt;

&lt;p&gt;When I think about this, I think about a journey any thought takes. From a rough, raw idea that’s in your brain, into a sequence of sentences that forms a logic:&lt;/p&gt;

&lt;p&gt;Let’s dissect this into the three stages of content transformation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DbcACGUd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlqvyu4k3x7itwcdim6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DbcACGUd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlqvyu4k3x7itwcdim6n.png" alt="Image description" width="844" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First, the thoughts are born in your mind, and they resemble a structure of a graph network. Thoughts, ideas, and concepts have some “links” in between, but their significance might not be apparent at this stage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, with the right “saturation” of these graph nodes and links, some of them will start to form into a set of “outlines”. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, some parts of the outlines will be extracted into a series of sentences tailored for the audience; the version you think is good enough to put it out there.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unsurprisingly, there’re already apps that fit each stage of this journey: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Roam Research, Obsidian&lt;/li&gt;
&lt;li&gt;Dynalist, Workflowly&lt;/li&gt;
&lt;li&gt;Words-like software&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There’re even some apps that cover the multiple (or all) stages of this journey: Notion, Markdown editors, or even a suite of Google Documents/Spreadsheets might do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Many failed attempts to complete the journey of words transformation
&lt;/h2&gt;

&lt;p&gt;I have a track record of trying out as many note-taking apps I could do. When I look at my past creation in each one of these apps, I see many failed attempts of forming a consistent habit.&lt;/p&gt;

&lt;p&gt;Most of the time, I leave these tools with some unfinished thoughts, unable to push them to cross the line of publishing them. Why did these texts not make it out there?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vz8vef2n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydl8fuiw2moex4m7kph7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vz8vef2n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydl8fuiw2moex4m7kph7.png" alt="Image description" width="880" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many failed attempts that I don’t feel like adding more&lt;/p&gt;

&lt;p&gt;I see two reasons (out of potentially many) here.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Most of the tools are promising too much, becoming too powerful, too complicated.&lt;/li&gt;
&lt;li&gt;Consequently, they’ll force you the mindset of “organizing the past texts” before you can start writing new ones.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even as simple as Apple native note app, I would feel compelled to look at what I’ve written in the past, when starting the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I want something, that doesn’t force me into thinking “I have to organize these texts”.&lt;/strong&gt; I do want to find them “eventually” when the time is right. But that shouldn’t be the first action I need to take in the platform.&lt;/p&gt;

&lt;p&gt;In Japanese, this reminds me of a concept called “発酵” (fermentation process). You could translate it as “sleep on the ideas”. You want to forget them, let them stay where they are, how they are. Unless you actively seek for them to come back to it.&lt;/p&gt;

&lt;p&gt;I’m making a tool exactly for that. &lt;strong&gt;A simple, intuitive tool to make you do the following two things very well.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A blank inbox to start writing random texts. It’s your dumping ground of anything that comes across your brain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Carefully crafted set of UX to edit, organize, and grow them sometime later.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the tool can do these two things extremely well, I believe that’s all what I need to cross that chasm. I can finally start publishing my thoughts into the wild. And maybe more importantly, I can finally be ease with my writing, fully knowing that some will never see the light. and That’s OK.&lt;/p&gt;

&lt;h2&gt;
  
  
  I’ve turned this process into an app (iOS, Android, and the Web app)
&lt;/h2&gt;

&lt;p&gt;First, every screen starts with a blank slate of a text box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2_SARVsu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t3k4d3w84xnak83nmn8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2_SARVsu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t3k4d3w84xnak83nmn8w.png" alt="Image description" width="800" height="254"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;First Screen of the App&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The basic idea here is that your past sentences should never be the distraction of the texts you’re about to produce. Taking advantage of this “blank slate everytime”, you’re safe to start dumping what’s fresh in your mind.&lt;/p&gt;

&lt;p&gt;After that, you’re taken into an editing screen, that you can extend the text with “pluses” and “reorder handles”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ogWe-nXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wlbuz5inii7s64ieq87g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ogWe-nXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wlbuz5inii7s64ieq87g.png" alt="Image description" width="880" height="562"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Editing Screen with “+” and “reorder handles”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The process of turning the random thoughts to the outlining, requires a carefully selected set of tools to assist you in the journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the part I’m actively developing right now.  This is where you come in! Each month, I add many features, talk to the alpha testers, then discard some.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I’m aiming, is to create a &lt;strong&gt;“sharp knife for texts editing”&lt;/strong&gt;; it should have a few set of Editing UX that’s just enough to form the structure of your article. Fast and intuitive.&lt;/p&gt;

&lt;p&gt;Eventually, some texts will find its aim;  a meaningful structure that delivers the points it wants to make.&lt;/p&gt;

&lt;h1&gt;
  
  
  Publish it to anywhere you’d like
&lt;/h1&gt;

&lt;p&gt;From there, it’s totally up to you. I only publish maybe one out of ten articles (posts) I create in this app.&lt;/p&gt;

&lt;p&gt;That’s perfectly ok for me. Every word I’ve dumped in this playground must have had its purpose at the time of writing. Maybe it will in the future, too.&lt;/p&gt;

&lt;p&gt;Some of them, will make it to some blogging platforms I use; Medium, Dev.to, or maybe your own hosted blog sites.&lt;/p&gt;

&lt;p&gt;The app is totally unopinionated on how you’ll use the drafts in the end&lt;/p&gt;

&lt;h1&gt;
  
  
  Would you like to give this app a try?
&lt;/h1&gt;

&lt;p&gt;I’m currently in the process of recruiting early testers, to give me feedback on the direction of the app. If you’d like to try this out, please fill out the following simple form to say hi!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forms.gle/aPh51kDohsS3H9dw7"&gt;Google Form for Early Testers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve had some success inviting alpha testers from Japanese audience. Now, I’d like to receive more feedback worldwide.&lt;/p&gt;

&lt;p&gt;No matter what, let’s keep writing! Your words are worth sharing. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kenzan100"&gt;Say Hi on Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Writing!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Line by line explanation of Ruby 3 Ractor - worker pool implementation</title>
      <dc:creator>Yuta Miyama</dc:creator>
      <pubDate>Mon, 31 May 2021 18:02:17 +0000</pubDate>
      <link>https://dev.to/kenzan100/let-s-read-worker-pool-implementation-using-ruby-3-ractor-feature-103g</link>
      <guid>https://dev.to/kenzan100/let-s-read-worker-pool-implementation-using-ruby-3-ractor-feature-103g</guid>
      <description>&lt;p&gt;Ruby 3 has an exciting update about its concurrency support: Ractors.&lt;/p&gt;

&lt;p&gt;First, please read &lt;a href="https://github.com/ruby/ruby/blob/master/doc/ractor.md"&gt;https://github.com/ruby/ruby/blob/master/doc/ractor.md&lt;/a&gt; for "What it is" and "What it can do".&lt;/p&gt;

&lt;p&gt;If you're trying to achieve some sort of concurrent programming and ❤️ Ruby language, you should definitely give it a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worker pool's implementation in Ractor
&lt;/h2&gt;

&lt;p&gt;Below's the copy of the code explained in Ractor's official documentation. It's slightly modified to provide more granular explanation on its behaviour.&lt;/p&gt;

&lt;p&gt;I've also annotated the code heavily, so that you can read the intent of each line with me.&lt;/p&gt;

&lt;p&gt;Let's decipher this line by line, so that you can properly assess what you can do with Ractor.&lt;/p&gt;

&lt;p&gt;For the basic API of Ractor, please refer to &lt;a href="https://ruby-doc.org/core-3.0.0/Ractor.html"&gt;https://ruby-doc.org/core-3.0.0/Ractor.html&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Code with line-by-line explanation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This example computes if the given numbers is a prime number or not, using 10 parallel workers. &lt;/span&gt;

&lt;span class="c1"&gt;# to make `num.prime?` possible.&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'prime'&lt;/span&gt;

&lt;span class="c1"&gt;# this ractor will keep listening to the sent messages, and yield them to whomever want to take the value.&lt;/span&gt;
&lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;yield&lt;/span&gt; &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Let's check the prime numbers from 1 upto 1000&lt;/span&gt;
&lt;span class="no"&gt;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="c1"&gt;# we'll use 10 workers to do this work.&lt;/span&gt;
&lt;span class="no"&gt;RN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="c1"&gt;# worker ractors initialization.&lt;/span&gt;
&lt;span class="c1"&gt;# each worker ractor takes pipe as its sharable object (Ractor has some synchronization mechanism according to [this doc](https://github.com/ruby/ruby/blob/master/doc/ractor.md#shareable-objects)) &lt;/span&gt;
&lt;span class="c1"&gt;# then, each worker Ractor reads the input through the pipe (multiplexing) to utilize 10 workers&lt;/span&gt;
&lt;span class="n"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="no"&gt;RN&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;# Ractor#take is a blocking call, and waits till pipe yields something&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;
      &lt;span class="c1"&gt;# Worker, then in turn, computes something (expensive :) and yields to whomever willing to listen to this ractor&lt;/span&gt;
      &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"worker #&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prime?&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# sending 1000 numbers to the pipe, worker ractors are ready to consume by now.&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="no"&gt;N&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# main process (main process itself is a running Ractor) calls&lt;/span&gt;
&lt;span class="c1"&gt;# Ractor#select, which can listen to a list of ractors&lt;/span&gt;
&lt;span class="c1"&gt;# because it's called (1..N) times, it'll hit all of the computed values by the time pp prints them.&lt;/span&gt;
&lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="no"&gt;N&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;_r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;wid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;I hope this illustration together with &lt;a href="https://github.com/ruby/ruby/blob/master/doc/ractor.md"&gt;https://github.com/ruby/ruby/blob/master/doc/ractor.md&lt;/a&gt; has given you a better understanding of what you can do with Ractor.&lt;/p&gt;

&lt;p&gt;In my opinion, Ruby finally providing basic primitives for doing actor based concurrency is very exciting.&lt;/p&gt;

&lt;p&gt;You won't have to focus too much on the performance gain, or even the current status of all the APIs (they explicitly state its an experimental feature, as of Ruby 3.0.1).&lt;/p&gt;

&lt;p&gt;still, I'm confident that we can already start learning how to write distributed systems all within the favourite language of our choice :)&lt;/p&gt;

&lt;p&gt;I hope you'll dig a bit deeper by yourself, as well! Happy coding 🙌&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>distributedsystems</category>
      <category>ractor</category>
    </item>
    <item>
      <title>Make an original io game in 5 days</title>
      <dc:creator>Yuta Miyama</dc:creator>
      <pubDate>Fri, 01 Jan 2021 18:02:33 +0000</pubDate>
      <link>https://dev.to/kenzan100/make-an-original-io-game-in-5-days-3c0g</link>
      <guid>https://dev.to/kenzan100/make-an-original-io-game-in-5-days-3c0g</guid>
      <description>&lt;p&gt;I've used my holiday break to make an original .io game from scratch. It took me 5 days.&lt;/p&gt;

&lt;p&gt;Here, I'll share how you can do the same.&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2F1p2huzdzodnq7l1wp12bx0xhp9nw" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2F1p2huzdzodnq7l1wp12bx0xhp9nw" alt="game screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Why?
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Cuz it's my passion.
&lt;/h2&gt;

&lt;p&gt;Before I ventured into a software development career, I used to make a physical card game that &lt;a href="https://www.japanfs.org/en/news/archives/news_id029442.html" rel="noopener noreferrer"&gt;teaches kids about environmental issues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I poured my soul into that game, and I've wanted to make more games ever since.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cuz online game dev has so much learning potential.
&lt;/h2&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fqvo8hirxcr7a192thz1kyk6iv7bd" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fqvo8hirxcr7a192thz1kyk6iv7bd" alt="MDN game dev"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a look at the above image (from &lt;a href="https://developer.mozilla.org/en-US/docs/Games" rel="noopener noreferrer"&gt;MDN game dev&lt;/a&gt; web page).&lt;/p&gt;

&lt;p&gt;As you can see, it has &lt;strong&gt;so many surface areas that you can dig into&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Being a good software developer is all about being a constant learner. This excites me.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's in it for you?
&lt;/h1&gt;

&lt;p&gt;Have you imagined yourself as a game developer &lt;em&gt;someday&lt;/em&gt; ? You know how to program something, but you aren't really sure how to start as a game developer?&lt;/p&gt;

&lt;p&gt;This tutorial serves as yet another article to give you that push to finally start making your own game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Target Audience
&lt;/h2&gt;

&lt;p&gt;I'm assuming that you have a little bit of programming experience already. When I describe the steps in specific terms, I expect you to be able to "Google it" for supplementary knowledge.&lt;/p&gt;

&lt;p&gt;But don't worry.&lt;br&gt;
I've also provided &lt;strong&gt;the commit by commit instruction&lt;/strong&gt; in each step. When you're lost in the instruction, look at the code diff to make sure you're on track.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;The game I made&lt;/li&gt;
&lt;li&gt;Part1: Make a local development environment (Day1)&lt;/li&gt;
&lt;li&gt;Part2: Design the game elements (Day2, Day3)&lt;/li&gt;
&lt;li&gt;Part3: Adjust the elements to a "playable" state(Day4, Day5)&lt;/li&gt;
&lt;li&gt;Takeaways&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  The game I made
&lt;/h1&gt;

&lt;p&gt;It's like a 2D tank game, where you'll navigate your character to beat an opponent's character. But there's one twist.&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fmd8ru9zsokoe635f6dk8kjfnvbo9" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fmd8ru9zsokoe635f6dk8kjfnvbo9" alt="game-screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll have to play &lt;a href="https://en.wikipedia.org/wiki/Rock_paper_scissors" rel="noopener noreferrer"&gt;"Rock Paper Scissors"&lt;/a&gt; when you collide with opponents. So you'll need to be creative on how to adjust each character's "shape" before they collide.&lt;/p&gt;

&lt;p&gt;You can play the game via &lt;a href="https://morning-castle-26048.herokuapp.com/" rel="noopener noreferrer"&gt;this link&lt;/a&gt;. It might take a few seconds before it boots.&lt;/p&gt;




&lt;h1&gt;
  
  
  Part1: Make a local development environment (Day1)
&lt;/h1&gt;

&lt;p&gt;First of all, let's focus on making a foundation for a local development environment.&lt;/p&gt;

&lt;p&gt;(Make sure you have a Node.js on your machine. I'm using MacBook + Homebrew)&lt;/p&gt;

&lt;h2&gt;
  
  
  Part1-1: Build HTML/JS via Webpack
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Grab your favorite package manager. NPM should be fine, but I like &lt;a href="https://yarnpkg.com/getting-started/install" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt; more.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://webpack.js.org/guides/getting-started/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt; for your project directory. Again, you can pick alternatives if you know what you're doing :)&lt;/li&gt;
&lt;li&gt;Create a JS/HTML template to conform to the Webpack build cycle.&lt;/li&gt;
&lt;li&gt;Try running your build, e.g. &lt;code&gt;yarn webpack --watch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Access the file to see your progress. e.g. &lt;code&gt;open dist/index.html&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/d13f560fb18b79f3fa6d38ee147f8b14005caeef" rel="noopener noreferrer"&gt;This commit&lt;/a&gt; represents the progress so far.&lt;/p&gt;

&lt;p&gt;You should be able to see some messages on console + HTML.&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2F0ptuxpavp4sahl5cfhy6k33m3bj4" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2F0ptuxpavp4sahl5cfhy6k33m3bj4" alt="1-1 progress"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part1-2: Draw something on canvas
&lt;/h2&gt;

&lt;p&gt;Next, let's make sure you'll be able to draw/manipulate objects using the HTML canvas element. I've used &lt;a href="https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript" rel="noopener noreferrer"&gt;this tutorial&lt;/a&gt; to get familiar with the basics.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Draw a circle on the canvas.&lt;/li&gt;
&lt;li&gt;Add an event listener to the keydown event.&lt;/li&gt;
&lt;li&gt;Write a JS &lt;a href="https://gameprogrammingpatterns.com/game-loop.html" rel="noopener noreferrer"&gt;"game loop"&lt;/a&gt; function so that the drawing happens continuously as you move the circle.&lt;/li&gt;
&lt;li&gt;Assign dynamic coordinates(x, y) to the "draw circle" function so that that cursor keys can move the circle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/5baa3f896bb61799e205136bcc1fdb35bc20dbb4" rel="noopener noreferrer"&gt;This commit&lt;/a&gt; represents this part of progress.&lt;/p&gt;

&lt;p&gt;Yay! your circle should be moving as you press your cursor keys :)&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fjxaeqzglztvmj8cfx2vtj6tggryc" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fjxaeqzglztvmj8cfx2vtj6tggryc" alt="circle-moving"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part1-3: Prepare web server
&lt;/h2&gt;

&lt;p&gt;Finally, let's spin up a web server. This step prepares you for the next step, where you'll be moving your game state to the server-side.&lt;/p&gt;

&lt;p&gt;Server-side dictating the game logic is crucial to provide a consistent online game experience.&lt;/p&gt;

&lt;p&gt;To connect server-side logic with the user's input + rendering, we'll use a technology called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" rel="noopener noreferrer"&gt;WebSocket&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WebSocket enables efficient bi-directional messages between clients and servers.&lt;/p&gt;

&lt;p&gt;Let's first set up "connections." Actual event implementations are explained in later steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install and spin up &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express web server&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install and setup WebSocket connections between the server and the client, using a library called &lt;a href="https://socket.io/get-started/chat/" rel="noopener noreferrer"&gt;Socket.io&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This part of the commit looks like &lt;a href="https://github.com/kenzan100/action-janken/commit/6695757a10f96c91025eb9e31eedde7ce724572c" rel="noopener noreferrer"&gt;this&lt;/a&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  Part2: Design the game elements (Day2, Day3)
&lt;/h1&gt;

&lt;p&gt;So far, we've created the following components to as scaffolding to build games on.&lt;/p&gt;

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

1. HTML/JS + Webpack to build(package) them.
2. Canvas + EventListeners to render/interact with visual elements.
3. Express web server + WebSocket to establish bi-directional connections.


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

&lt;/div&gt;




&lt;h1&gt;
  
  
  Recapping what we're building
&lt;/h1&gt;

&lt;p&gt;It's useful to have a summary of what kind of game you're making at this stage. Below's my version:&lt;/p&gt;

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

Game Idea memo

&amp;lt;Game Objects&amp;gt;
- Player object: to move around in 2d canvas.
- "Rock Paper Scissors" Coins: to place in 2d canvas.


&amp;lt;Game Logic&amp;gt;
1. When the Player collides with Coins, the Player will change its shape to one of "Rock" / "Paper" / "Scissor."
2. The shape change is based on the maximum number of coins you've collected at a given moment.
3. When Players collide with each other, the actual "Rock Paper Scissor" game takes place. It uses the current shape of each player object.
4. Winner stays in the game. The loser is kicked out of the game. The last person to remain in the game wins all.


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

&lt;/div&gt;

&lt;p&gt;Let's build out the proof-of-concept, according to the game memo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part2-1: Translate the game logic to data models
&lt;/h2&gt;

&lt;p&gt;One useful step is to translate the game logic described above to actual data models our server should use.&lt;/p&gt;

&lt;p&gt;Don't try to be perfect. Pay attention to &lt;strong&gt;"what's the foundational properties each role has to have?"&lt;/strong&gt;. We can add more properties later as the game gets sophisticated.&lt;/p&gt;

&lt;p&gt;I started my data model as the following:&lt;/p&gt;

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

{
  players: [
    { id: yuta, x: 0, y: 0 }, ...
  ],
  coins: [
    { kind: Rock, x: 10, y: 10 }, ...    
  ]
}


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

&lt;/div&gt;

&lt;p&gt;Pretty straightforward. The game has two arrays, with each object holds its x y coordinate. The coin has &lt;code&gt;kind&lt;/code&gt; property to represent Rock/Paper/Scissor to have a different effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separate game logic from rendering logic
&lt;/h3&gt;

&lt;p&gt;To provide consistent/fair UX among players, we should express game logic on the server-side. The client-side (JS run in browsers) will only be responsible for two things: rendering the game state and sending user inputs to the server.&lt;/p&gt;

&lt;p&gt;We can imagine this separation as a continuous cycle of &lt;code&gt;inputs -&amp;gt; state change -&amp;gt; rendering -&amp;gt; next inputs&lt;/code&gt;.&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fh7c7uq4oqgioe63k8f8whyceeh31" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fh7c7uq4oqgioe63k8f8whyceeh31" alt="input-&amp;gt;state-&amp;gt;render-&amp;gt;next-input"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part2-2: Connect server-side logic to client-side rendering
&lt;/h2&gt;

&lt;p&gt;First, let's tackle the part where the server sends data models to the client-side. For the above, it'll simulate the state transition -&amp;gt; rendering part.&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;Convert the data model to JS Objects. Put that in server-side JS.&lt;/li&gt;
&lt;li&gt;Prepare server-side &lt;a href="https://gameprogrammingpatterns.com/game-loop.html" rel="noopener noreferrer"&gt;game-loop&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Have WebSocket send the data model as &lt;code&gt;gameUpdates&lt;/code&gt; to clients.&lt;/li&gt;
&lt;li&gt;Have clients output received data models.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/477f5005379350ed93767df3be2595b0e50b1849" rel="noopener noreferrer"&gt;This commit&lt;/a&gt; describes this part.&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fuy8ty8kfrlw9hke1yksr0nzbfbne" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fuy8ty8kfrlw9hke1yksr0nzbfbne" alt="server -&amp;gt; client rendering"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should be able to see the circles at the coordinates/size defined on the server-side. 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  Part2-3: Connect client-side inputs to server-side logic
&lt;/h2&gt;

&lt;p&gt;Next, let's express the other half of interaction: client inputs -&amp;gt; server state transition.&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;Bridge the user input eventListener to the WebSocket event.&lt;/li&gt;
&lt;li&gt;Have the server-side update its data model by the inputs received from the client-side.&lt;/li&gt;
&lt;li&gt;Change the static data model to the dynamic one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/7f5bc8afbcf4562f175de1935459a38485161213" rel="noopener noreferrer"&gt;The commit&lt;/a&gt; and the successful output is as follows:&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fzq8yplavegfv1nwzwgtlbf0qqf9g" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fzq8yplavegfv1nwzwgtlbf0qqf9g" alt="circle moving"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Keep it up!
&lt;/h2&gt;

&lt;p&gt;Congrats on making it this far! You already have 80% of the foundational code to make a 2D online game.&lt;/p&gt;




&lt;h1&gt;
  
  
  Part3: Adjust the elements to a "playable" state(Day4, Day5)
&lt;/h1&gt;

&lt;p&gt;Now that we have most of the elements ready, how do we turn this into a "playable" game?&lt;/p&gt;

&lt;p&gt;Let's come back to the game idea memo:&lt;/p&gt;

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

Game Idea memo

&amp;lt;Game Objects&amp;gt;
- Player object: to move around in 2d canvas.
- "Rock Paper Scissors" Coins: to place in 2d canvas.


&amp;lt;Game Logic&amp;gt;
1. When the Player collides with Coins, the Player will change its shape to one of "Rock" / "Paper" / "Scissor."
2. The shape change is based on the maximum number of coins you've collected at a given moment.
3. When Players collide with each other, the actual "Rock Paper Scissor" game takes place. It uses the current shape of each player object.
4. Winner stays in the game. The loser is kicked out of the game. The last person to remain in the game wins all.


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Part3-1: Translate game logic to a player's story
&lt;/h2&gt;

&lt;p&gt;It's important to tell a "game dynamics" from a user's point of view. From the moment a player joins a game, how does it progress? How does it end? Do they want to come back after one game ends?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;Player Story&amp;gt;
1. At the beginning, players start with the "Rock" state. At this point, colliding with each other means "tie": nothing happens.
2. As you move the object, you'll start placing some Rock Paper Scissors coins.
3. You'll watch out what state opponents are in. Depending on that, you'll either try to change your state to a winning one or change the opponent's state to a losing one.
4. When it's ready, tackle and collide with an opponent.
5. If won, you'll readjust your state so that you can keep winning with others.


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

&lt;/div&gt;

&lt;p&gt;Let's use this sample player story as a guide to build the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part3-2: Enable player-to-coin interaction
&lt;/h2&gt;

&lt;p&gt;Let's address the part where each player's state changes by the coins collected so far.&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;state&lt;/code&gt; property to each player's data model. &lt;code&gt;Rock:0, Paper:0, Scissor:0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the server-side game loop, make &lt;strong&gt;collision-detection&lt;/strong&gt; happen between players and coins.&lt;/li&gt;
&lt;li&gt;Change the state of the player object, depending on the sum of collected coins.&lt;/li&gt;
&lt;li&gt;Have client-side JS express the state change (for now, I'll just change the colors).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/56a9760a06f2046f1d8e96e15445c3f1cb44a23d" rel="noopener noreferrer"&gt;The commit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will look like this:&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fzqbbigq3vb44qbjstvs44ouq602k" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fzqbbigq3vb44qbjstvs44ouq602k" alt="player-coin interaction"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might wonder why coins won't appear on the screen. This is because the coin you've just placed collides with the player "right away".&lt;/p&gt;

&lt;p&gt;There are several ways to fix this, but I'll do it in the next steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collision Detection? What?
&lt;/h3&gt;

&lt;p&gt;It might sound intimidating at first, but good articles/libraries are already out there to support you on this topic.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection" rel="noopener noreferrer"&gt;this article&lt;/a&gt; for a good introduction to the subject.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part3-3: Enable player-to-player interaction
&lt;/h2&gt;

&lt;p&gt;By reusing the player-to-coin interaction above, we can build a player-to-player interaction.&lt;/p&gt;

&lt;p&gt;One key difference here is that the player-to-player interaction will produce a "Rock Paper Scissor" event to determine the winner of that collision.&lt;/p&gt;

&lt;p&gt;Here, I'll introduce another data model called &lt;code&gt;match&lt;/code&gt; to express this state.&lt;/p&gt;

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

match = { loser: webSocketID, winner: webSocketID }


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

&lt;/div&gt;

&lt;p&gt;This will enable rendering the win/lose result to the client-side.&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;Prepare a &lt;code&gt;match&lt;/code&gt; data model to express a win/lose state.&lt;/li&gt;
&lt;li&gt;Implement player-to-player collision detection (reusing the method implemented in the previous part).&lt;/li&gt;
&lt;li&gt;Implement the rule of &lt;a href="https://en.wikipedia.org/wiki/Rock_paper_scissors" rel="noopener noreferrer"&gt;Rock Paper Scissors&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Fill in the &lt;code&gt;match&lt;/code&gt; data model with the result and send it to the client-side.&lt;/li&gt;
&lt;li&gt;Output the match result on the client-side (for now, it'll output to the console).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/2da40384d2019e8fbb4d4af34333d583a4472c75" rel="noopener noreferrer"&gt;The commit is here&lt;/a&gt;&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fwv6kzizxgpp5czq1o7o2p0j0cx1u" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fwv6kzizxgpp5czq1o7o2p0j0cx1u" alt="player-to-player interaction"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part3-4: Replace rendering objects with actual game images
&lt;/h2&gt;

&lt;p&gt;You're almost there! Let's replace the placeholder circles with Rock Paper Scissor images to communicate the game concept.&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;Prepare images for player objects, as well as coin objects.&lt;/li&gt;
&lt;li&gt;Replace the circles with the images.&lt;/li&gt;
&lt;li&gt;Ajudst the x y coordinate of images so that center of the image will point to the coordinate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;3rd step requires the knowledge of &lt;code&gt;setTransform&lt;/code&gt; from Canvas API. There're many good articles out there to do this. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations" rel="noopener noreferrer"&gt;MDN API doc&lt;/a&gt; is always a good start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sidenote: Delay the player-to-coin collision detection
&lt;/h3&gt;

&lt;p&gt;Above, I've described player-to-coin collision happens right away, hiding the coin object from appearing on the screen.&lt;/p&gt;

&lt;p&gt;I can think of several ways to solve this (A. Change the coin concept to "bullet," shooting them from your player's object. B. Place the coins a little bit in front of you, ...).&lt;/p&gt;

&lt;p&gt;In this post, I've chosen the option to "delay" the collision detection so that you can use coins both for you and for other players.&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fobojjtz9otka36bh8oz2iitbin4z" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fobojjtz9otka36bh8oz2iitbin4z" alt="delay collision"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've added the &lt;code&gt;placedAt&lt;/code&gt; property to do this. &lt;code&gt;placedAt&lt;/code&gt; will express the elapsed time since coin placement. This enables the small gap before the coin starts interacting with player objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/323667f06c4a9906fc5d72edef5571aa00db9b79" rel="noopener noreferrer"&gt;The commit&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part3-5: Complete one game cycle
&lt;/h2&gt;

&lt;p&gt;As the last step, let's supplement the player story with basic instructions.&lt;/p&gt;

&lt;p&gt;Think from the user's perspective. Users would know nothing about how your game works when they first see it.&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;Prepare a win/lose result text as HTML.&lt;/li&gt;
&lt;li&gt;Show the result text when the match is decided between two players.&lt;/li&gt;
&lt;li&gt;Implement "clean up" logic for the lost player. (Disconnect WebSocket connection, Stop rendering, Delete the server-side objects).&lt;/li&gt;
&lt;li&gt;Prepare Game Rule section as another HTML content.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/kenzan100/action-janken/commit/7ec35b696dbb59d197ed0967db27afafdb049502" rel="noopener noreferrer"&gt;The commit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below's the screenshot of result display (top: winner side. bottom: loser side).&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fmyd5zfeixyq4nvx74697j0l5g0vk" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fmyd5zfeixyq4nvx74697j0l5g0vk" alt="winning side instruction"&gt;&lt;/a&gt;&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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fad62cd9ro0m0wj3khalo7ix7m3he" 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%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fad62cd9ro0m0wj3khalo7ix7m3he" alt="losing side instruction"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose where to deploy your game
&lt;/h3&gt;

&lt;p&gt;If your objective is to prototype a casual game, I'd recommend &lt;a href="https://devcenter.heroku.com/articles/nodejs-support" rel="noopener noreferrer"&gt;Heroku Node.js deployment&lt;/a&gt;. It is easy to use, and the free tier should be enough to showcase your work.&lt;/p&gt;




&lt;h1&gt;
  
  
  The result
&lt;/h1&gt;

&lt;p&gt;Congratulations! &lt;/p&gt;

&lt;p&gt;You've now completed the first full cycle of the game-making process.&lt;/p&gt;

&lt;p&gt;Let's recap how far we've come by looking at the &lt;a href="https://github.com/kenzan100/action-janken" rel="noopener noreferrer"&gt;repository&lt;/a&gt; and &lt;a href="https://github.com/kenzan100/action-janken/commits/main" rel="noopener noreferrer"&gt;its commit history&lt;/a&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Takeaways
&lt;/h1&gt;

&lt;p&gt;Making a game itself is only half the outcome. Here're a few tips I've learned along the way:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Revisit the process as composable steps for the next game
&lt;/h2&gt;

&lt;p&gt;Organize your commit and game elements so that you can reuse the patterns in the next game.&lt;/p&gt;

&lt;p&gt;In this post, we've learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canvas 2D rendering + key-based controls&lt;/li&gt;
&lt;li&gt;Games that involve Collision Detection&lt;/li&gt;
&lt;li&gt;Casual multiplayer online games (.io games)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually, you'll build your own pattern of techniques + elements, making the process tailored for your creativity.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Look for relevant articles + people who are doing the same thing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/ja/docs/Web" rel="noopener noreferrer"&gt;MDN&lt;/a&gt; is always a high-quality resource for web-based technologies.&lt;/p&gt;

&lt;p&gt;It's critical to find likely-minded people who are already doing the output of their work.&lt;/p&gt;

&lt;p&gt;Victor Zhou's blog on &lt;a href="https://victorzhou.com/blog/build-an-io-game-part-1/" rel="noopener noreferrer"&gt;How to build a .io game from scratch&lt;/a&gt; helped me tremendously on this.&lt;/p&gt;

&lt;p&gt;Be careful not to be swamped by the sheer amount of articles you'll find on the Internet. Not everything is high-quality. &lt;/p&gt;

&lt;p&gt;A good measurement on when to stop searching is, "have I collected enough keywords/terminologies to unblock myself?".&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Do a lot of deliberate practice
&lt;/h2&gt;

&lt;p&gt;This is true to any kind of learning. The Game-making process is no exception, as it is a lifelong journey to create a game that's fun and satisfying.&lt;/p&gt;

&lt;p&gt;Focus on the learning topic &lt;strong&gt;one at a time&lt;/strong&gt;. There're many relevant technologies (Audio, WebRTC, Network programming, ...) and game genres(RPG, action, puzzle, ...) you could try. Trying to learn many things at once will degrade the learning.&lt;/p&gt;

&lt;p&gt;Don't focus too much on "How to make people play my game?". &lt;strong&gt;Focus on "How can I share the learning within the game-making process?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The latter will get you to a network of like-minded people, which is sometimes more important than the game itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Feedback is welcome!
&lt;/h2&gt;

&lt;p&gt;I'll now focus on making the next game. Please give me comments/feedback on what you've thought of the article.&lt;/p&gt;

&lt;p&gt;My Twiter account is &lt;a href="https://twitter.com/kenzan100" rel="noopener noreferrer"&gt;kenzan100&lt;/a&gt;. Please follow me if you've liked my content.&lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Did you know Ruby has resolv-replace?</title>
      <dc:creator>Yuta Miyama</dc:creator>
      <pubDate>Sun, 13 Dec 2020 22:22:21 +0000</pubDate>
      <link>https://dev.to/kenzan100/ruby-has-resolv-replace-10l0</link>
      <guid>https://dev.to/kenzan100/ruby-has-resolv-replace-10l0</guid>
      <description>&lt;p&gt;In Ruby, there's a library called &lt;a href="https://ruby-doc.org/stdlib-2.7.0/libdoc/resolv-replace/rdoc/index.html"&gt;&lt;code&gt;resolv-replace&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a drop-in replacement (moneky patch) of libc DNS resolver Ruby's using under the hood. It'll use a pure Ruby implementation called &lt;a href="https://docs.ruby-lang.org/en/2.7.0/Resolv.html"&gt;&lt;code&gt;Resolv&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The doc states the merit of &lt;code&gt;Resolv&lt;/code&gt; as &lt;em&gt;"Resolv can handle multiple DNS requests concurrently without blocking the entire Ruby interpreter"&lt;/em&gt;. So ppl probably reach out to this when they want to improve the performance.&lt;/p&gt;

&lt;p&gt;You can read how &lt;code&gt;resolv-replace&lt;/code&gt; is patching a set of Ruby's stdlibc network calls at &lt;a href="https://ruby-doc.org/stdlib-2.7.0/libdoc/resolv-replace/rdoc/index.html"&gt;https://ruby-doc.org/stdlib-2.7.0/libdoc/resolv-replace/rdoc/index.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you'd like more control on the DNS layer due to how your app's constructed, I'd recommend checking out this library.&lt;/p&gt;




&lt;p&gt;&lt;span&gt;Cover Photo by &lt;a href="https://unsplash.com/@jjying?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;JJ Ying&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/network?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Create a private RSS feed without paying a penny.</title>
      <dc:creator>Yuta Miyama</dc:creator>
      <pubDate>Sun, 13 Sep 2020 15:19:39 +0000</pubDate>
      <link>https://dev.to/kenzan100/create-a-private-rss-feed-without-paying-a-penny-447p</link>
      <guid>https://dev.to/kenzan100/create-a-private-rss-feed-without-paying-a-penny-447p</guid>
      <description>&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@anniespratt?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Annie Spratt&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/penny?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Prerequisite
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.dropbox.com/basic"&gt;Dropbox Basic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pages.github.com/"&gt;Github Pages&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Steps
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Upload your mp3/mp4 contents to Dropbox. Get a raw link by following &lt;a href="https://zapier.com/learn/how-to/generate-direct-dropbox-link/"&gt;this step&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Locally, follow &lt;a href="https://www.thepolyglotdeveloper.com/2016/02/create-podcast-xml-feed-publishing-itunes/"&gt;this article&lt;/a&gt; to create an RSS file.&lt;/li&gt;
&lt;li&gt;Commit your RSS file to your Github repo. Publish it as a Github page.&lt;/li&gt;
&lt;li&gt;Make sure your RSS file path is valid with &lt;a href="https://castfeedvalidator.com/"&gt;https://castfeedvalidator.com/&lt;/a&gt;. Some of the test results say warnings. As long as this is a private feed, you can ignore them.&lt;/li&gt;
&lt;li&gt;Share the RSS file path to your community! Popular podcast apps (including Apple Podcast) have a way to import RSS URLs directly. Enjoy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To be minimum, below worked. (The URL is no longer valid, as I was too embarrassed to keep it public).&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;rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:rawvoice="http://www.rawvoice.com/rawvoiceRssModule/" version="2.0"&amp;gt;
    &amp;lt;channel&amp;gt;
        &amp;lt;title&amp;gt;Podcast Title Here&amp;lt;/title&amp;gt;
        &amp;lt;link&amp;gt;https://www.example.com&amp;lt;/link&amp;gt;
        &amp;lt;image&amp;gt;
            &amp;lt;url&amp;gt;http://www.example.com/image3000x3000.png&amp;lt;/url&amp;gt;
            &amp;lt;title&amp;gt;Podcast Title Here&amp;lt;/title&amp;gt;
            &amp;lt;link&amp;gt;https://www.example.com&amp;lt;/link&amp;gt;
        &amp;lt;/image&amp;gt;
        &amp;lt;description&amp;gt;
            The full length description for your podcast
        &amp;lt;/description&amp;gt;
        &amp;lt;language&amp;gt;en-us&amp;lt;/language&amp;gt;
        &amp;lt;copyright&amp;gt;Yuta copyright 2016&amp;lt;/copyright&amp;gt;
        &amp;lt;item&amp;gt;
          &amp;lt;title&amp;gt;Episode Name 2&amp;lt;/title&amp;gt;
          &amp;lt;link&amp;gt;https://dl.dropbox.com/s/dff56030336b/YourVideoAudioFile.mp4&amp;lt;/link&amp;gt;
          &amp;lt;pubDate&amp;gt;Sat, 02 Jan 2020 16:00:00 PDT&amp;lt;/pubDate&amp;gt;
          &amp;lt;description&amp;gt;The full length episode 2 description&amp;lt;/description&amp;gt;
          &amp;lt;enclosure url="https://dl.dropbox.com/s/dff56030336b/YourVideoAudioFile.mp4" length="36715125" type="audio/mpeg"/&amp;gt;
          &amp;lt;guid&amp;gt;https://dl.dropbox.com/s/dff56030336b/YourVideoAudioFile.mp4&amp;lt;/guid&amp;gt;
        &amp;lt;/item&amp;gt;
    &amp;lt;/channel&amp;gt;
&amp;lt;/rss&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Misc TIL
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I didn't know that &lt;a href="https://discussions.apple.com/thread/7120235"&gt;&lt;code&gt;.mov&lt;/code&gt; and &lt;code&gt;.mp4&lt;/code&gt; are compatible with great extent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;I'm not sure how protective this feed URL will become, only by specifying &lt;a href="https://github.com/RetSamys/private-RSS-feed/blob/master/robots.txt"&gt;robots.txt&lt;/a&gt;. Let me know your thoughts.&lt;/li&gt;
&lt;li&gt;If you're more serious about your audience, consider &lt;a href="https://www.glow.fm/guides-tutorials/whatareprivatefeed"&gt;paid&lt;/a&gt; / &lt;a href="https://support.patreon.com/hc/en-us/articles/115000877506-Add-my-private-RSS-feed-to-the-Apple-Podcast-app"&gt;services&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Finally, &lt;a href="https://www.reddit.com/r/podcasting/comments/5s8u3m/podcast_rss_feed_spec_or_something/ddela5g/"&gt;another link&lt;/a&gt; I stumbled upon along the way. Thank you Internet!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rss</category>
      <category>github</category>
      <category>dropbox</category>
    </item>
  </channel>
</rss>
