<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Project Kenneth]]></title><description><![CDATA[Hi there! I'm Kenneth. I build apps then I write about the experience. All articles are my own personal thoughts and opinions.]]></description><link>https://blog.projectkenneth.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 09:43:08 GMT</lastBuildDate><atom:link href="https://blog.projectkenneth.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Dynamic Component Rendering in React]]></title><description><![CDATA[When defining application components, a good strategy is to split by functionality.
In a blogging application, we'll have a component to represent the WYSIWYG editor then, another to hold the publish settings. In this particular example, the publish ...]]></description><link>https://blog.projectkenneth.com/dynamic-component-rendering-in-react</link><guid isPermaLink="true">https://blog.projectkenneth.com/dynamic-component-rendering-in-react</guid><category><![CDATA[React]]></category><category><![CDATA[components]]></category><category><![CDATA[design principles]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Tue, 26 Oct 2021 18:35:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635273259235/rYu5P6TL7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When defining application components, a good strategy is to split by functionality.</p>
<p>In a blogging application, we'll have a component to represent the WYSIWYG editor then, another to hold the publish settings. In this particular example, the publish settings component is pretty static. Meaning, it will always have the same fields and behavior.</p>
<p>But, what if the publish settings contents vary dynamically? A good example of this can be found in Photoshop. In this case, depending on the tool selected, the Property Panel will be rendered differently.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635271845629/pXhLs5wpy.gif" alt="componentdynamic_ps.gif" /></p>
<p>This is where dynamic component rendering comes in. When a tool is selected, Photoshop will intelligently determine what will be rendered on the property pane.</p>
<p>In this post, let's explore how to implement dynamic component rendering in React.</p>
<p>Let's go!</p>
<h2 id="the-design">The Design</h2>
<p>In this section, we'll talk about what makes up a dynamic component rendering implementation.</p>
<p>There are 3 items we need to prepare:</p>
<ol>
<li><strong>Configuration</strong> - In its most basic form, the configuration is simply a mapping between a condition and a component.</li>
<li><strong>Dynamic Components</strong> - Of course, we'd need to have the components that will actually be dynamically rendered.</li>
<li><strong>Dynamic Render Function</strong> - This is the function that will actually perform the decision of which component to render.</li>
</ol>
<p>Next, we'll look at dynamic component rendering in action.</p>
<h2 id="the-implementation">The Implementation</h2>
<p>For our example, we'll look at a Property Editor component whose contents can be dynamically changed based on user selection.</p>
<p>We'll configure each of the 3 items mentioned in the previous section. Let's start.</p>
<h3 id="configuration">Configuration</h3>
<p>For the configuration, we'll implement a basic mapping between a key and a functional component to represent that key:</p>
<pre><code><span class="hljs-keyword">const</span> Config = {
  assign: AssignPropertyEditor,
  <span class="hljs-built_in">log</span>: LogPropertyEditor
}
</code></pre><p>Based on this configuration, our dynamic component renderer will have 2 different components to choose from.</p>
<h3 id="dynamic-components">Dynamic Components</h3>
<p>For the dynamic components, we implement them as if they're normal components.</p>
<p>The <code>AssignPropertyEditor</code> component looks like this:</p>
<pre><code><span class="hljs-keyword">const</span> AssignPropertyEditor = <span class="hljs-function">(<span class="hljs-params">{ codeData, updateData }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> type = codeData.type;
    <span class="hljs-keyword">const</span> localData = codeData.data;

    <span class="hljs-keyword">if</span> (type === <span class="hljs-string">"assign"</span>) {
        <span class="hljs-keyword">const</span> onVariableChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
            localData.variable = event.target.value;

            updateData(localData);
        };

        <span class="hljs-keyword">const</span> onValueChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
            localData.value = event.target.value;

            updateData(localData);
        };

        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Assign:<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>/&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"assign_var"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{localData.variable}</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Variable"</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{onVariableChange}</span> /&gt;</span>
                <span class="hljs-symbol">&amp;nbsp;</span>=<span class="hljs-symbol">&amp;nbsp;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"assign_val"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{localData.value}</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Value"</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{onValueChange}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
        );
    } 

    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
};
</code></pre><p>While the <code>LogPropertyEditor</code> looks like this:</p>
<pre><code><span class="hljs-keyword">const</span> LogPropertyEditor = <span class="hljs-function">(<span class="hljs-params">{ codeData, updateData }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> type = codeData.type;
    <span class="hljs-keyword">const</span> localData = codeData.data;

    <span class="hljs-keyword">if</span> (type === <span class="hljs-string">"log"</span>) {
        <span class="hljs-keyword">const</span> onMessageChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
            localData.message = event.target.value;

            updateData(localData);
        };

        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Log:<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"log_message"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{localData.message}</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Message"</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{onMessageChange}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
        );
    }

    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
};
</code></pre><p>The only pattern we need to be aware of is that both components should receive the same set of properties. Of course, they should use these properties in the same way.</p>
<p>In our example, the <code>codeData</code> will hold the data for each component. Then, the <code>updateData</code> property is a callback function which the dynamic components will execute when their respective data has changed.</p>
<h3 id="dynamic-render-function">Dynamic Render Function</h3>
<p>For better context, we'll show the render function as included in its entire component:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [activeData, setActiveData] = useState();

  <span class="hljs-keyword">const</span> onUpdateCodeData = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-comment">// react to data update from dynamic components</span>
  };

  <span class="hljs-keyword">const</span> renderPropertyEditor = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (activeData &amp;&amp; activeData.type !== <span class="hljs-literal">null</span> &amp;&amp; Config[activeData.type]) {
      <span class="hljs-keyword">const</span> PropertyEditor = Config[activeData.type];
      <span class="hljs-keyword">return</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">PropertyEditor</span> <span class="hljs-attr">codeData</span>=<span class="hljs-string">{activeData}</span> <span class="hljs-attr">updateData</span>=<span class="hljs-string">{onUpdateCodeData}</span> /&gt;</span></span>);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">em</span>&gt;</span>Select an element type to display.<span class="hljs-tag">&lt;/<span class="hljs-name">em</span>&gt;</span></span>);
    }
  };

  <span class="hljs-keyword">const</span> onDisplayAssignEditor = <span class="hljs-function">() =&gt;</span> {
    setActiveData({ <span class="hljs-attr">type</span>: <span class="hljs-string">"assign"</span>, <span class="hljs-attr">data</span>: { <span class="hljs-attr">variable</span>: <span class="hljs-string">"a"</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">"100"</span> } });
  };

  <span class="hljs-keyword">const</span> onDisplayLogEditor = <span class="hljs-function">() =&gt;</span> {
    setActiveData({ <span class="hljs-attr">type</span>: <span class="hljs-string">"log"</span>, <span class="hljs-attr">data</span>: { <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world!"</span> } });
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Toolbox<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onDisplayAssignEditor}</span>&gt;</span>Update to ASSIGN<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onDisplayLogEditor}</span>&gt;</span>Update to LOG<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Property Editor<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        {renderPropertyEditor()}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span> &gt;</span>
  );
}</span>
</code></pre><p>The dynamic render function is the <code>renderPropertyEditor</code> function. It uses the <code>activeData</code> variable to determine which component to render.</p>
<p>The key code in this function is:</p>
<pre><code><span class="hljs-keyword">const</span> PropertyEditor = Config[activeData.type];
<span class="hljs-keyword">return</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">PropertyEditor</span> <span class="hljs-attr">codeData</span>=<span class="hljs-string">{activeData}</span> <span class="hljs-attr">updateData</span>=<span class="hljs-string">{onUpdateCodeData}</span> /&gt;</span></span>);
</code></pre><p>In this section of the code, we literally treat the functional component passed in the configuration as a stand-alone component named <code>PropertyEditor</code>. Whatever component the <code>activeData.type</code> value maps to, will be the one receiving the <code>activeData</code> and <code>onUpdateCodeData</code> properties. This will also be the same component to be rendered.</p>
<h2 id="a-more-realistic-example">A More Realistic Example</h2>
<p>For a more real-world example, you can check out <a target="_blank" href="https://devpinch.online/speed-build.html">Speed Build</a>. It's a simple low-code app builder created using React and ReactFlow. Speed Build's code can be found <a target="_blank" href="https://github.com/projectkenneth/react-low-code-app-builder/">here</a>.</p>
<p>The parent component and the render function can be found at <code>src/Editor/Canvas.js</code>. Additionally, all the dynamic property components are located at the <code>src/PropertyPanel</code> directory.</p>
<p>For more similar projects that can help you learn software/web development, you can check out my <a target="_blank" href="https://devpinch.online/">DevPinch</a> initiative.</p>
<h2 id="conclusion">Conclusion</h2>
<p>So, that's it! We've implemented dynamic component rendering in react! </p>
<p>Here's a quick demo:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635271642918/FvPsTIRr6.gif" alt="componentdynamic.gif" /></p>
<p>Glad that you've reached the end of this post. Let me know what you think of this approach by sending in your comments.</p>
<p>I hoped you learned something new from me today!</p>
<hr />
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Feature Management in ReactJS]]></title><description><![CDATA[In this post, I'll show you how to implement feature management on your React applications. Feature management is the way to control which features are available based on certain scenarios.
Why Do Feature Management?
Here are some scenarios where con...]]></description><link>https://blog.projectkenneth.com/feature-management-in-reactjs</link><guid isPermaLink="true">https://blog.projectkenneth.com/feature-management-in-reactjs</guid><category><![CDATA[React]]></category><category><![CDATA[features]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Mon, 11 Oct 2021 10:00:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633946278616/eKWfd8jrb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, I'll show you how to implement feature management on your React applications. Feature management is the way to control which features are available based on certain scenarios.</p>
<h2 id="why-do-feature-management">Why Do Feature Management?</h2>
<p>Here are some scenarios where controlling feature availability is necessary:</p>
<ol>
<li><strong>The feature should only be turned on after a marketing event.</strong> With feature flags, the feature can already be sitting in production and an administrator can just simply enable it via configuration once the event is done.</li>
<li><strong>The feature should only be available to users on a specific plan.</strong></li>
</ol>
<p>All of these scenarios share the same concept. In this post, we'll focus on the 2nd one. Let's go!</p>
<h2 id="the-requirements">The Requirements</h2>
<p>Let's say we're building a blog application that offers the ff. features:</p>
<ul>
<li>Updating Title and Content</li>
<li>Publishing to multiple blog platforms</li>
<li>Scheduling the publish time</li>
</ul>
<p>Now, let's say the app offers 3 plans to users: Basic, Pro, and, Ultimate. </p>
<p>With these plans, the team has decided to have a plan comparison table that looks like this:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>Basic</td><td>Pro</td><td>Ultimate</td></tr>
</thead>
<tbody>
<tr>
<td>Update Title and Content</td><td>Yes</td><td>Yes</td><td>Yes</td></tr>
<tr>
<td>Schedule the publish time ​</td><td>No</td><td>Yes</td><td>Yes</td></tr>
<tr>
<td>Publish to multiple blog platforms</td><td>No</td><td>No</td><td>Yes</td></tr>
</tbody>
</table>
</div><p>We now have all the requirements defined. Let's start building!</p>
<h2 id="the-starting-point">The Starting Point</h2>
<p>For your reference, the initial state of the project can be found <a target="_blank" href="https://github.com/projectkenneth/react-feature-control/tree/Initial-State">here</a>. </p>
<p>For simplicity, we only have the <code>New Blog</code> page in this version.</p>
<p>The page contains the following:</p>
<ul>
<li>A Role Switcher to simulate changing of the plans</li>
<li>All the features are still available to the user</li>
</ul>
<p>Here's how it looks like at this point:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633927794332/Qy1vYMk9D.png" alt="FC-React-2.png" /></p>
<h3 id="the-role-switcher">The Role Switcher</h3>
<p>Here's a look at the <code>RoleSwitcher</code> component:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RoleSwitcher</span>(<span class="hljs-params">{ plans, activePlan, setActivePlan }</span>) </span>{
    <span class="hljs-keyword">const</span> navItemTags = <span class="hljs-function">() =&gt;</span>
        plans.map(<span class="hljs-function">(<span class="hljs-params">label, index</span>) =&gt;</span>
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"nav-item"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">nav-link</span>" + (<span class="hljs-attr">activePlan</span> === <span class="hljs-string">index</span> ? " <span class="hljs-attr">active</span>" <span class="hljs-attr">:</span> "")} <span class="hljs-attr">onClick</span>=<span class="hljs-string">{e</span> =&gt;</span> setActivePlan(index)}&gt;{label}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
        );

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"nav nav-pills"</span>&gt;</span>
            {navItemTags()}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
    );
};
</code></pre><p>The component receives 3 properties which are passed by the <code>App</code> component.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> availablePlans = Config.availablePlans;
  <span class="hljs-keyword">const</span> [activePlan, setActivePlan] = useState(<span class="hljs-number">0</span>);

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RoleSwitcher</span> 
    <span class="hljs-attr">plans</span>=<span class="hljs-string">{availablePlans}</span> <span class="hljs-attr">activePlan</span>=<span class="hljs-string">{activePlan}</span> 
    <span class="hljs-attr">setActivePlan</span>=<span class="hljs-string">{setActivePlan}</span> /&gt;</span></span>
</code></pre><p>The <code>App</code> component then refers to the <code>availablePlans</code> exposed by <code>Config.js</code></p>
<pre><code><span class="hljs-keyword">const</span> Config = {
    availablePlans: [<span class="hljs-string">'Basic'</span>, <span class="hljs-string">'Pro'</span>, <span class="hljs-string">'Ultimate'</span>]
};
</code></pre><p>The <code>RoleSwitcher</code> displays all the available plans and allows the user to set the <code>activePlan</code>. The <code>activePlan</code> variable will then be passed to the <code>Editor</code> component later on.</p>
<h2 id="the-feature-based-approach">The Feature-Based Approach</h2>
<p>Now, let's update the other features to only be shown on the appropriate plan.</p>
<p>In this approach, we let the plans identify the features that are going to be available in them.</p>
<p>Therefore, we need to make changes to the <code>Config</code> file:</p>
<pre><code><span class="hljs-string">const</span> <span class="hljs-string">Config</span> <span class="hljs-string">=</span> {
    <span class="hljs-attr">availablePlans:</span> [
        {
            <span class="hljs-attr">id:</span> <span class="hljs-number">0</span>,
            <span class="hljs-attr">name:</span> <span class="hljs-string">'Basic'</span>,
            <span class="hljs-attr">features:</span> []
        },
        {
            <span class="hljs-attr">id:</span> <span class="hljs-number">1</span>,
            <span class="hljs-attr">name:</span> <span class="hljs-string">'Pro'</span>,
            <span class="hljs-attr">features:</span> [<span class="hljs-string">'scheduledPost'</span>]
        },
        {
            <span class="hljs-attr">id:</span> <span class="hljs-number">2</span>,
            <span class="hljs-attr">name:</span> <span class="hljs-string">'Ultimate'</span>,
            <span class="hljs-attr">features:</span> [<span class="hljs-string">'scheduledPost'</span>, <span class="hljs-string">'multiplePublishers'</span>]
        }
    ]
}<span class="hljs-string">;</span>
</code></pre><p>In the above change, each plan inside the <code>availablePlans</code> array now has a list of <code>features</code> that are available in them.</p>
<p>Then, let's update the <code>RoleSwitcher</code> to support this new format:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RoleSwitcher</span>(<span class="hljs-params">{ plans, activePlan, setActivePlan }</span>) </span>{
    <span class="hljs-keyword">const</span> navItemTags = <span class="hljs-function">() =&gt;</span>
        plans.map(<span class="hljs-function">(<span class="hljs-params">plan</span>) =&gt;</span>
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"nav-item"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{plan.id}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
                    <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">nav-link</span>" + (<span class="hljs-attr">activePlan.id</span> === <span class="hljs-string">plan.id</span> ? " <span class="hljs-attr">active</span>" <span class="hljs-attr">:</span> "")} 
                    <span class="hljs-attr">onClick</span>=<span class="hljs-string">{e</span> =&gt;</span> setActivePlan(plan)}&gt;{plan.name}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
        );

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"nav nav-pills"</span>&gt;</span>
            {navItemTags()}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
    );
};
</code></pre><p>The initialization section of the <code>App</code> component also needs to be updated:</p>
<pre><code><span class="hljs-keyword">const</span> availablePlans = Config.availablePlans;
<span class="hljs-keyword">const</span> [activePlan, setActivePlan] = useState(availablePlans[<span class="hljs-number">0</span>]);
</code></pre><p>And now, for the star of this post, let's talk about the <code>FeatureBlock</code> component!</p>
<h3 id="the-feature-block-component">The Feature Block Component</h3>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FeatureBlock</span>(<span class="hljs-params">props</span>) </span>{
    <span class="hljs-keyword">const</span> isFeatureVisible = props.activePlan.features
        .find(<span class="hljs-function"><span class="hljs-params">feature</span> =&gt;</span> feature === props.featureName);

    <span class="hljs-keyword">if</span> (isFeatureVisible) {
        <span class="hljs-keyword">return</span> (
                <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
                    {props.children}
                <span class="hljs-tag">&lt;/&gt;</span></span>
            );
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
};
</code></pre><p>The <code>FeatureBlock</code> component is a wrapper component and receives the following:</p>
<ul>
<li>The <code>activePlan</code> property to determine the selected plan</li>
<li>The <code>featureName</code> property to which will be matched against the <code>features</code> list of the <code>activePlan</code> property. If a match is found, the <code>FeatureBlock</code>'s children will be rendered.</li>
<li>The component's children which are conditionally rendered based on the above 2 properties</li>
</ul>
<p>For simplicity, we'll only use the <code>FeatureBlock</code> component to wrap the publisher and scheduled inputs in the <code>Editor</code> component. This is because the title and content fields are available to all plans anyway.</p>
<p>The <code>Editor</code> component will now have this structure:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Editor</span>(<span class="hljs-params">{ activePlan }</span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"col col-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>New Post<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-comment">&lt;!--Title and content fields here--&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FeatureBlock</span> <span class="hljs-attr">activePlan</span>=<span class="hljs-string">{activePlan}</span> 
                <span class="hljs-attr">featureName</span>=<span class="hljs-string">"multiplePublishers"</span>&gt;</span>
                <span class="hljs-comment">&lt;!--The publishers selection here--&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">FeatureBlock</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FeatureBlock</span> <span class="hljs-attr">activePlan</span>=<span class="hljs-string">{activePlan}</span> 
                <span class="hljs-attr">featureName</span>=<span class="hljs-string">"scheduledPost"</span>&gt;</span>
                <span class="hljs-comment">&lt;!--The schedule input here--&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">FeatureBlock</span>&gt;</span>
            <span class="hljs-comment">&lt;!--Save and submit buttons here--&gt;</span>
    );
}</span>
</code></pre><p>After all these changes, the <code>RoleSwitcher</code> will now toggle the visibility of the publisher and schedule inputs.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633930537427/PvnYN38yE.gif" alt="FC-React-3.gif" /></p>
<p>As you can see, everything is functioning as expected. But, there's a problem with the <code>Config</code> file. </p>
<p>It's too centralized! Once the app grows, the <code>Config</code> file has the potential to be bloated. Let's solve this in the next section.</p>
<p>By the way, <a target="_blank" href="https://github.com/projectkenneth/react-feature-control/blob/Feature-Based-Check">here's the code</a> at this point.</p>
<h2 id="the-plan-based-approach">The Plan-Based Approach</h2>
<p>To solve the problem with the <code>Config</code> file, we should follow a plan-based approach.</p>
<p>In this approach, we're inverting the dependency. Instead of letting the plan define the features available, we let the features specify which plans they should be available on. This is a more modular and cleaner approach.</p>
<p>The <code>Editor</code> component will now have this structure:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Editor</span>(<span class="hljs-params">{ activePlan }</span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"col col-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>New Post<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-comment">&lt;!--Title and content fields here--&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FeatureBlock</span> <span class="hljs-attr">activePlan</span>=<span class="hljs-string">{activePlan}</span> 
                <span class="hljs-attr">planNames</span>=<span class="hljs-string">{[</span>"<span class="hljs-attr">Ultimate</span>"]}&gt;</span>
                <span class="hljs-comment">&lt;!--The publishers selection here--&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">FeatureBlock</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FeatureBlock</span> <span class="hljs-attr">activePlan</span>=<span class="hljs-string">{activePlan}</span> 
                <span class="hljs-attr">planNames</span>=<span class="hljs-string">{[</span>"<span class="hljs-attr">Pro</span>", "<span class="hljs-attr">Ultimate</span>"]}&gt;</span>
                <span class="hljs-comment">&lt;!--The schedule input here--&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">FeatureBlock</span>&gt;</span>
            <span class="hljs-comment">&lt;!--Save and submit buttons here--&gt;</span>
    );
}</span>
</code></pre><p>The <code>FeatureBlock</code> will also be updated to support this change:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FeatureBlock</span>(<span class="hljs-params">props</span>) </span>{
    <span class="hljs-keyword">const</span> isFeatureVisible = props.planNames.find(<span class="hljs-function"><span class="hljs-params">plan</span> =&gt;</span>
        plan === props.activePlan.name);

    <span class="hljs-keyword">if</span> (isFeatureVisible) {
        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
                {props.children}
            <span class="hljs-tag">&lt;/&gt;</span></span>
        );
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
};
</code></pre><p>Now that the <code>Config</code> will not be responsible for storing the plan-to-feature mappings anymore, it can already be simplified to:</p>
<pre><code><span class="hljs-string">const</span> <span class="hljs-string">Config</span> <span class="hljs-string">=</span> {
    <span class="hljs-attr">availablePlans:</span> [
        {
            <span class="hljs-attr">id:</span> <span class="hljs-number">0</span>,
            <span class="hljs-attr">name:</span> <span class="hljs-string">'Basic'</span>
        },
        {
            <span class="hljs-attr">id:</span> <span class="hljs-number">1</span>,
            <span class="hljs-attr">name:</span> <span class="hljs-string">'Pro'</span>
        },
        {
            <span class="hljs-attr">id:</span> <span class="hljs-number">2</span>,
            <span class="hljs-attr">name:</span> <span class="hljs-string">'Ultimate'</span>
        }
    ]
}<span class="hljs-string">;</span>
</code></pre><p><a target="_blank" href="https://github.com/projectkenneth/react-feature-control/blob/Plan-Based-Check">Here's the code</a> at this point.</p>
<h2 id="in-summary">In Summary</h2>
<p>We've successfully implemented Feature Management in React!</p>
<p>What I've provided is simply a skeletal reference. You can expand it further to support more advanced requirements.</p>
<p>In my case, I was thinking to implement user-specific feature availability. In this scenario, specific features can only be available to users who pass certain conditions.</p>
<p>For example, what if only want to make the scheduled publishing feature available to users from a certain location? We'll explore this in my next article which I'll upload in the next few days!</p>
<p>Glad that you've reached the end of this post. Let me know what you think of this approach by sending in your comments.</p>
<p>I hoped you learned something new from me today!</p>
<hr />
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[A Topic-centric Approach To Organizing Content using Notion]]></title><description><![CDATA[When I create content, I start off with a topic. Then, I create different content pieces revolving around that topic targeting different platforms like Hashnode, Dev.to, or Twitter.
In fact, I recently Tweeted about this, that content creation nowada...]]></description><link>https://blog.projectkenneth.com/a-topic-centric-approach-to-organizing-content-using-notion</link><guid isPermaLink="true">https://blog.projectkenneth.com/a-topic-centric-approach-to-organizing-content-using-notion</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[writing]]></category><category><![CDATA[content]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Sun, 03 Oct 2021 15:14:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273872909/fxTuSsHVj.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I create content, I start off with a topic. Then, I create different content pieces revolving around that topic targeting different platforms like <a target="_blank" href="http://hashnode.com">Hashnode</a>, <a target="_blank" href="http://Dev.to">Dev.to</a>, or <a target="_blank" href="https://twitter.com/">Twitter</a>.</p>
<p>In fact, I recently <a target="_blank" href="https://twitter.com/ProjectKenneth/status/1444278643853774850?s=20">Tweeted about this</a>, that content creation nowadays is about creating content once and distributing it everywhere.</p>
<p>When I started using <a target="_blank" href="https://www.notion.so/">Notion</a>, my first idea was to apply this approach to my workspace. Here's how I did it.</p>
<h2 id="the-databases">The Databases</h2>
<p>The first things I created in Notion are 2 databases:</p>
<ul>
<li><strong>Topics</strong></li>
<li><strong>Content</strong></li>
</ul>
<h3 id="topic-database">Topic Database</h3>
<p>This is the database that will contain all of my topics &amp; ideas. In this database, I only have one 1 template and it looks like this:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273442831/tkSF0Spk2.png" alt="1 Topic Template.PNG" /></p>
<p>The 2 major fields in this template are:</p>
<ul>
<li><strong>Tags</strong> - a multi-valued field that I can further use to classify my ideas</li>
<li><strong>Related to Content Calendar (Topic)</strong> - this is an auto-generated field because of a <code>Relation</code> field added in the templates under the <code>Content</code> database. We'll discuss this further later.</li>
</ul>
<p>This database is using a <code>Table</code> view and it looks like this:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273452650/BuGlE3WdF.png" alt="1.1 Topics - Data.PNG" /></p>
<h3 id="content-database">Content Database</h3>
<p>This database will contain all of my actual content pieces. </p>
<p>I created 2 templates under this:</p>
<ul>
<li>Tweet - for posting on, well, Twitter</li>
<li>Article - for posting on blogging platforms</li>
</ul>
<p>Both templates have this structure:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273468897/Hk4hWzC_s.png" alt="2 Content Template - Article.PNG" /></p>
<p>The major fields for these templates are:</p>
<ul>
<li><strong>Type</strong> - this is the type of content piece (Article or Tweet). Though, this is already predefined by the templates.</li>
<li><strong>Topic</strong> - this is the <code>Relation</code> field I mentioned earlier. This allows me to define which topic this piece of content is related to.</li>
<li><p><strong>Status</strong> - specifies the state of this content piece. It has the following possible values:
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273515564/WWyARrIlJ.png" alt="3 Content Template - Status Types.PNG" /></p>
</li>
<li><p><strong>Publication Date &amp; URL</strong> - to allow me to specify the publication info once the content piece is published.</p>
</li>
</ul>
<p>Lastly, the main body content of the template will be where I write the actual content.</p>
<p><strong>Assets Sub-page</strong></p>
<p>As you may have noticed, there's a default sub-page in these templates named <code>Assets</code>. This sub-page allows me to upload the assets that I'll embed in the content piece.</p>
<p>Based on its parent template, this sub-page will have a different default value under it.</p>
<ul>
<li><p>For Tweets, it'll look like this:
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273538671/4-vZ9jaaa.png" alt="7 Content Calendar - Tweet - Default Assets.PNG" /></p>
</li>
<li><p>For Articles:
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273544805/yWVwhbk94.png" alt="5 Content Calendar - Article - Default Assets.PNG" /></p>
</li>
</ul>
<p><strong>Board View</strong></p>
<p>For this template, I used a <code>Board</code> view so I can easily track the individual status of my content pieces:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633273572077/eU819QInv.png" alt="8 Content Calendar - Data.PNG" /></p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>So, this is how I manage my content in Notion! This approach really helped me become more organized.</p>
<p>Now, every time I think of an idea, I first log it in the Topics database. With Notion's mobile apps, I can even do this while on the go.</p>
<p>Then, I'll create the related content pieces depending on which platforms I'm targeting.</p>
<p>I'm also planning to create more Content templates to handle different platforms like Facebook or even YouTube.</p>
<p>Do you have any suggestions or comments on how I can improve this? I would love to hear your thoughts so leave them in the comments section below!</p>
<hr />
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Building an API using Express and MongoDB]]></title><description><![CDATA[In this post, we'll go through the process of creating an API built using Express and MongoDB.
We'll cover the ff. steps:

Setting up MongoDB
Creating an Express application
Optimizing your Express routes
Handling errors

Let's start!
Setting up Mong...]]></description><link>https://blog.projectkenneth.com/building-an-api-using-express-and-mongodb</link><guid isPermaLink="true">https://blog.projectkenneth.com/building-an-api-using-express-and-mongodb</guid><category><![CDATA[MongoDB]]></category><category><![CDATA[Express]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Fri, 01 Oct 2021 18:50:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633113937862/K07IPv8fv.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, we'll go through the process of creating an API built using Express and MongoDB.</p>
<p>We'll cover the ff. steps:</p>
<ol>
<li>Setting up MongoDB</li>
<li>Creating an Express application</li>
<li>Optimizing your Express routes</li>
<li>Handling errors</li>
</ol>
<p>Let's start!</p>
<h2 id="setting-up-mongodb">Setting up MongoDB</h2>
<p>In this section, we'll go through creating and configuring a remote MongoDB instance.</p>
<h3 id="using-a-mongodb-instance-hosted-on-the-cloud">Using a MongoDB instance hosted on the cloud</h3>
<p>Instead of installing a local MongoDB instance, we'll use Atlas which is MongoDB's official database-as-a-service.</p>
<ol>
<li>Create a MongoDB Atlas account <a target="_blank" href="https://www.mongodb.com/cloud/atlas">here</a>.</li>
<li>Create a cluster. For new accounts, you can use the <strong><em>forever free</em></strong> tier!</li>
<li>Create the super admin user.</li>
</ol>
<h3 id="managing-your-databases-using-compass">Managing your databases using Compass</h3>
<p>To better visualize our data, we'll be using the official GUI for MongoDB, Compass.</p>
<ol>
<li>Download the latest <strong>Compass</strong> version <a target="_blank" href="https://www.mongodb.com/products/compass">here</a>.</li>
<li>Install the thing!</li>
<li>Get the database connection string from <strong>Atlas</strong>.<ol>
<li>Access your <strong>Atlas dashboard</strong>. Then, on your cluster panel, click the <strong>Connect</strong> button. </li>
<li>On the <strong>Connect</strong> popup, create your super admin user.</li>
<li>Then, for the Connection Method, choose <strong>Connect using MongoDB Compass</strong>.</li>
<li>Then, choose the latest Compass version and then copy the connection string. </li>
<li>Replace the credentials in the connection string with your actual credentials.</li>
<li>Keep the connection string somewhere safe so you can use it in the next steps.</li>
</ol>
</li>
<li>Launch <strong>Compass</strong>, <strong>**key in your connection string, then, click </strong>Connect**.
 <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633112608154/fyx7zaAnj.png" alt="DB 1.2.4 Connect to Cluster.PNG" /></li>
<li>Once connected, you can now click on the <strong>Create Database</strong> button.</li>
<li>Specify the database name and the first collection's name. Then, click the <strong>Create Database</strong> button on the popup.<ol>
<li>For this example, I created a database named <code>audit-log-demo</code> and a collection named <code>user-profile</code>.
 <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633112621266/MuFE-p_O0.png" alt="DB 1.2.6 Create Database.PNG" /></li>
</ol>
</li>
<li>You should now see <code>audit-log-demo</code> as part of the database list.</li>
<li><p>Now, let's add test data to our database.</p>
<ol>
<li>Click on the <code>audit-log-demo</code> database. You will be directed to the collection list page.</li>
<li>Click on the <code>user-profile</code> collection. You will be directed to the collection management page.</li>
<li>Under the <strong>Documents</strong> tab, click on the <strong>Add Data</strong> &gt; <strong>Insert Document</strong> button.</li>
<li><p>In the <strong>Insert to Collection</strong> popup, paste the following properties just below the <strong>_id</strong> property:</p>
<pre><code class="lang-json"> <span class="hljs-string">"firstName"</span>: <span class="hljs-string">"Tony"</span>,
 <span class="hljs-string">"lastName"</span>: <span class="hljs-string">"Stark"</span>,
 <span class="hljs-string">"age"</span>: <span class="hljs-number">25</span>
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633112695590/2HCJHdIW5.png" alt="DB 1.2.8.4 Collection List.PNG" /></p>
</li>
</ol>
</li>
</ol>
<h2 id="creating-an-express-application">Creating an Express application</h2>
<p>In this section, let's go through the step-by-step process of creating an Express application and letting this application establish a connection to our new MongoDB instance.</p>
<h3 id="setting-up">Setting up</h3>
<ol>
<li>Open your favorite CLI and navigate to your desired working directory.</li>
<li>Create a new package using <code>npm init</code>. Follow the prompts and provide the necessary details.</li>
<li>Install both <code>express</code> and the <code>mongodb</code> driver by executing <code>npm install mongodb express --save</code></li>
<li>Get the database's connection string from <strong>Atlas</strong>.<ol>
<li>Access your <strong>Atlas dashboard</strong>. Then, on your cluster panel, click the <strong>Connect</strong> button. </li>
<li>Then, for the Connection Method, choose <strong>Connect your application</strong>.</li>
<li>Then, choose the appropriate NodeJS version and then copy the connection string. </li>
<li>Replace the credentials in the connection string with your actual credentials.</li>
<li>Keep the connection string somewhere safe so you can use it in the next steps.</li>
</ol>
</li>
<li>Create a new environment setting with key <code>ALD_CONN_STRING</code> and set its value to your connection string.</li>
</ol>
<h3 id="connecting-to-the-database">Connecting to the database</h3>
<ol>
<li><p>At the root of your working directory, create an <code>index.js</code> file with this content:</p>
<pre><code class="lang-jsx"> <span class="hljs-keyword">const</span> { MongoClient, ObjectId } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongodb'</span>);
 <span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);

 <span class="hljs-keyword">const</span> mongoConnString = process.env.ALD_CONN_STRING;
 <span class="hljs-keyword">const</span> mongoClient = <span class="hljs-keyword">new</span> MongoClient(mongoConnString);

 <span class="hljs-keyword">const</span> expressApp = express();
 <span class="hljs-keyword">const</span> expressPort = <span class="hljs-number">3000</span>;

 expressApp.get(<span class="hljs-string">'/profile'</span>, <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
     <span class="hljs-keyword">try</span> {
         <span class="hljs-keyword">await</span> mongoClient.connect();

         <span class="hljs-keyword">const</span> db = mongoClient.db(<span class="hljs-string">'audit-log-demo'</span>);
         <span class="hljs-keyword">const</span> col = db.collection(<span class="hljs-string">'user-profile'</span>);

         <span class="hljs-keyword">const</span> profileList = <span class="hljs-keyword">await</span> col.find({}).toArray();

         res.send({
             <span class="hljs-attr">data</span>: profileList
         });
     } <span class="hljs-keyword">catch</span> (err) {
         next(err);
     }
     <span class="hljs-keyword">finally</span> {
         <span class="hljs-keyword">await</span> mongoClient.close();
     }
 });

 expressApp.listen(expressPort, <span class="hljs-function">() =&gt;</span> {
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Example app listening at http://localhost:<span class="hljs-subst">${expressPort}</span>`</span>)
 });
</code></pre>
<p> In the above code, we used the <code>ALD_CONN_STRING</code> environment variable to retrieve the connection string. Then, we instantiated the MongoDB and Express clients. We also introduced one route (<code>/profiles</code>) which retrieves all the documents in the <code>user-profile</code> collection.</p>
</li>
<li>Run your application by executing <code>node index.js</code> on your CLI.</li>
<li><p>Then, using your favorite REST client (I'm using <a target="_blank" href="https://www.postman.com/">Postman</a>), access the <code>/profiles</code> endpoint of your API. You should get this result:</p>
<pre><code class="lang-json"> {
     <span class="hljs-attr">"data"</span>: [
         {
             <span class="hljs-attr">"_id"</span>: <span class="hljs-string">"&lt;GUID&gt;"</span>,
             <span class="hljs-attr">"firstName"</span>: <span class="hljs-string">"Tony"</span>,
             <span class="hljs-attr">"lastName"</span>: <span class="hljs-string">"Stark"</span>,
             <span class="hljs-attr">"age"</span>: <span class="hljs-number">25</span>
         }
     ]
 }
</code></pre>
</li>
</ol>
<h3 id="adding-a-new-route">Adding a new route</h3>
<p>To further expand the capabilities of the API, we add a new route to get a specific profile by ID. </p>
<p>To do this, we just need to add the following code to your <code>index.js</code> file just before the <code>listen</code> call:</p>
<pre><code class="lang-jsx">expressApp.get(<span class="hljs-string">'/profile/:id'</span>, <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> mongoClient.connect();

        <span class="hljs-keyword">const</span> db = mongoClient.db(<span class="hljs-string">'audit-log-demo'</span>);
        <span class="hljs-keyword">const</span> col = db.collection(<span class="hljs-string">'user-profile'</span>);

        <span class="hljs-keyword">const</span> profile = <span class="hljs-keyword">await</span> col.findOne({ <span class="hljs-attr">_id</span>: ObjectId(req.params.id) });

        res.send({
            <span class="hljs-attr">data</span>: profile
        });
    } <span class="hljs-keyword">catch</span> (err) {
        next(err);
    }
    <span class="hljs-keyword">finally</span> {
        <span class="hljs-keyword">await</span> mongoClient.close();
    }
});
</code></pre>
<h3 id="checkpoint">Checkpoint</h3>
<p>You can check out the <code>index.js</code> code at this point by clicking <a target="_blank" href="https://github.com/projectkenneth/express-mongodb-demo/tree/Initial-State">here</a>.</p>
<h2 id="optimizing-your-express-routes">Optimizing your Express routes</h2>
<p>At this stage, the 2 routes we created are as follows:</p>
<pre><code class="lang-jsx">expressApp.get(<span class="hljs-string">'/profiles'</span>, <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> mongoClient.connect();

        <span class="hljs-keyword">const</span> db = mongoClient.db(<span class="hljs-string">'audit-log-demo'</span>);
        <span class="hljs-keyword">const</span> col = db.collection(<span class="hljs-string">'user-profile'</span>);

        <span class="hljs-keyword">const</span> profileList = <span class="hljs-keyword">await</span> col.find({}).toArray();

        res.send({
            <span class="hljs-attr">data</span>: profileList
        });
    } <span class="hljs-keyword">catch</span> (err) {
        next(err);
    }
    <span class="hljs-keyword">finally</span> {
        <span class="hljs-keyword">await</span> mongoClient.close();
    }
});

expressApp.get(<span class="hljs-string">'/profile/:id'</span>, <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> mongoClient.connect();

        <span class="hljs-keyword">const</span> db = mongoClient.db(<span class="hljs-string">'audit-log-demo'</span>);
        <span class="hljs-keyword">const</span> col = db.collection(<span class="hljs-string">'user-profile'</span>);

        <span class="hljs-keyword">const</span> profile = <span class="hljs-keyword">await</span> col.findOne({ <span class="hljs-attr">_id</span>: ObjectId(req.params.id) });

        res.send({
            <span class="hljs-attr">data</span>: profile
        });
    } <span class="hljs-keyword">catch</span> (err) {
        next(err);
    }
    <span class="hljs-keyword">finally</span> {
        <span class="hljs-keyword">await</span> mongoClient.close();
    }
});
</code></pre>
<p>The above code works, but, there's one major point of improvement in them.</p>
<p>In both routes, the parts that connect to the database and retrieve a reference to the collection are repeated. We should always follow the DRY (Don't Repeat Yourself) principle!</p>
<p>So how should we go about this? We introduce middleware to the code!</p>
<h3 id="whats-a-middleware">What's a middleware?</h3>
<p>In Express, a middleware is a function that can be executed before or after the actual request handlers.</p>
<p>For our example, we need to define 2 middleware functions:</p>
<ol>
<li>A middleware that establishes the connection to the database and will then pass this connection instance to the request handlers.</li>
<li>A middleware that closes the connection to the database. This middleware function will be executed after the request handlers.</li>
</ol>
<h3 id="lets-add-in-the-middleware-functions">Let's add in the middleware functions</h3>
<p>Here's the code for the 2 middleware functions:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dbConnBeforeware</span>(<span class="hljs-params">req, res, next</span>) </span>{
    <span class="hljs-keyword">const</span> mongoConnString = process.env.ALD_CONN_STRING;
    <span class="hljs-keyword">const</span> mongoClient = <span class="hljs-keyword">new</span> MongoClient(mongoConnString);

    <span class="hljs-keyword">await</span> mongoClient.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Database connection established!"</span>);

    req.dbClient = mongoClient;
    req.dbDatabaseRef = mongoClient.db(<span class="hljs-string">'audit-log-demo'</span>);

    next();
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dbConnAfterware</span>(<span class="hljs-params">req, res, next</span>) </span>{
    <span class="hljs-keyword">await</span> req.dbClient.close();

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Database connection closed!"</span>);

    next();
}
</code></pre>
<p>To use them, we need to adjust the way the routes are defined to:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getAllProfilesHandler</span>(<span class="hljs-params">req, res, next</span>) </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> col = req.dbDatabaseRef.collection(<span class="hljs-string">'user-profile'</span>);

        <span class="hljs-keyword">const</span> profileList = <span class="hljs-keyword">await</span> col.find({}).toArray();

        res.send({
            <span class="hljs-attr">data</span>: profileList
        });

        next();
    } <span class="hljs-keyword">catch</span> (err) {
        next(err);
    }
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getProfileByIdHandler</span>(<span class="hljs-params">req, res, next</span>) </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> col = req.dbDatabaseRef.collection(<span class="hljs-string">'user-profile'</span>);

        <span class="hljs-keyword">const</span> profile = <span class="hljs-keyword">await</span> col.findOne({ <span class="hljs-attr">_id</span>: ObjectId(req.params.id) });

        res.send({
            <span class="hljs-attr">data</span>: profile
        });

        next();
    } <span class="hljs-keyword">catch</span> (err) {
        next(err);
    }
}

<span class="hljs-comment">// For readability, we also created 2 new separate functions for the actual request handlers</span>
expressApp.get(<span class="hljs-string">'/profiles'</span>, dbConnBeforeware, getAllProfilesHandler, dbConnAfterware);
expressApp.get(<span class="hljs-string">'/profile/:id'</span>, dbConnBeforeware, getProfileByIdHandler, dbConnAfterware);
</code></pre>
<h3 id="checkpoint">Checkpoint</h3>
<p>You can check out the <code>index.js</code> code at this point by clicking <a target="_blank" href="https://github.com/projectkenneth/express-mongodb-demo/blob/Introducing-Middlewares/index.js">here</a>.</p>
<h2 id="handling-errors">Handling errors</h2>
<p>Another point of improvement with the current code is error handling. </p>
<p>If something goes wrong in the request handlers, the default Express error handler will be triggered. But, this default error handler does not close the database connection established.</p>
<p>To fix this, we introduce our very own error handler by adding this code after the route definition section:</p>
<pre><code class="lang-jsx">expressApp.use(<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, req, res, next</span>) </span>{
    <span class="hljs-keyword">if</span> (req.dbClient) {
        <span class="hljs-keyword">await</span> req.dbClient.close();
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Database connection closed!"</span>);
    }

    <span class="hljs-built_in">console</span>.error(err.stack);
    res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">'Something broke!'</span>);
});
</code></pre>
<p>In this custom error handler, we close the connection if any, and then log the error to the console. Lastly, we inform the API consumer that something went wrong.</p>
<p>Now, when an error occurs, you should get this response (Postman screenshot):
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633114057323/xDP3CVjiJ9.png" alt="Error Handling Response.PNG" /></p>
<h3 id="checkpoint">Checkpoint</h3>
<p>You can check out the <code>index.js</code> code at this point by clicking <a target="_blank" href="https://github.com/projectkenneth/express-mongodb-demo/blob/Introduce-Error-Handling/index.js">here</a>.</p>
<p>At this point, I added a forced error to the <code>getProfileByIdHandler</code> handler to simulate an error happening.</p>
<p>To view the version of the code without any of the forced errors, click <a target="_blank" href="https://github.com/projectkenneth/express-mongodb-demo/blob/master/index.js">here</a>.</p>
<h2 id="in-summary">In Summary</h2>
<p>We've successfully created an API built on Express and MongoDB!</p>
<p>Additionally, we've also gone through 2 rounds of code optimizations:</p>
<ol>
<li><strong>Middleware usage</strong> - for reducing code redundancy</li>
<li><strong>Custom error handling</strong> - for ensuring the database connection is closed even when issues occur</li>
</ol>
<p>I think there are still a couple of improvements on this:</p>
<ol>
<li>Once your API grows, you should split the route definitions into multiple code files.</li>
<li>The <code>dbConnBeforeware</code> can also be made configurable so you can use it for other routes that handle data from another collection.</li>
</ol>
<p>What other improvements do you have in mind? And what do you think of this approach? Let me know your thoughts in the comments</p>
<p>Glad that you've reached the end of this post. I hoped you learned something new from me today.</p>
<hr />
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Modular Routing in React]]></title><description><![CDATA[In a React + React Router environment, routing configuration is a one-to-one mapping between a route and that route's display elements.
Here's a basic example:
<Route exact path='/' component={Home} />
<Route exact path='/drafts' component={DraftList...]]></description><link>https://blog.projectkenneth.com/modular-routing-in-react</link><guid isPermaLink="true">https://blog.projectkenneth.com/modular-routing-in-react</guid><category><![CDATA[React]]></category><category><![CDATA[react router]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Mon, 27 Sep 2021 09:54:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632736248068/W-WxtEGSQ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In a React + React Router environment, routing configuration is a one-to-one mapping between a route and that route's display elements.</p>
<p>Here's a basic example:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Home}</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftListing}</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts/:draftId'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftUpdate}</span> /&gt;</span>
</code></pre><p>The above approach is suitable for simple applications, but, for complex ones, it's not really ideal.</p>
<p>Complex applications are usually composed of several modules. Each module is then composed of several components. If this is the application's structure, it is just reasonable for the routing model to follow the same structure, right?</p>
<p>Well, that's just what we're going to do! In this post, let's look at implementing modular routing in React.</p>
<p>We're doing this in 3 steps:</p>
<ol>
<li>Setup a theoretical application and identify its modules and components</li>
<li>Implement a regular routing model for the said application</li>
<li>Transform the regular routing model into a modular one</li>
</ol>
<p>Let's start!</p>
<h2 id="the-application-the-modules-and-the-components">The Application, the Modules, and the Components</h2>
<p>Let's say we're building a blog-writing application and we have decided to implement the ff. modules:</p>
<ul>
<li>Post Management</li>
<li>Draft Management</li>
</ul>
<p>Given the above modules, we'll probably design the routing map like this:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Module</td><td>Route</td></tr>
</thead>
<tbody>
<tr>
<td>Post Management</td><td>/posts</td></tr>
<tr>
<td>Draft Management</td><td>/drafts</td></tr>
</tbody>
</table>
</div><p>Looking at the above routings, it seems like we're only going to have 3 components directly representing each of our main modules. But, we all know that these modules are still going to be composed of one or more components. </p>
<p>In fact, we can even argue that these modules are "smaller applications" themselves. For instance, <em>Post Management</em> should also have a route navigating to the <em>Update Post</em> component. <em>Draft Management</em> should have this behavior as well (navigate to the <em>Update Draft</em> component).</p>
<p>So, what do we do now? We "push up" the concept of modules and identify the actual components of the application.</p>
<p>Here's the new routing map but with an added <em>Component</em> column.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Module</td><td>Component</td><td>Route</td></tr>
</thead>
<tbody>
<tr>
<td>Post Management</td><td>Post Listing</td><td>/posts</td></tr>
<tr>
<td></td><td>Update Post</td><td>/posts/:postId</td></tr>
<tr>
<td>Draft Management</td><td>Draft Listing</td><td>/drafts</td></tr>
<tr>
<td></td><td>Update Draft</td><td>/drafts/:draftId</td></tr>
</tbody>
</table>
</div><h2 id="the-regular-routing-approach">The Regular Routing Approach</h2>
<p>Now, we have identified the modules and components for our application. Let's go ahead and implement them!</p>
<h3 id="create-a-new-react-app-first">Create A New React App First</h3>
<p>Of course, the first step is to create a brand new React application.</p>
<pre><code>npx create-react-app reactjs-<span class="hljs-class"><span class="hljs-keyword">module</span>-<span class="hljs-title">based</span>-<span class="hljs-title">routing</span></span>
cd reactjs-<span class="hljs-class"><span class="hljs-keyword">module</span>-<span class="hljs-title">based</span>-<span class="hljs-title">routing</span></span>
</code></pre><p>Then, we'll install the <a target="_blank" href="https://reactrouter.com/web/guides/quick-start">React Router for Web Applications library</a> since we're building a web application.</p>
<pre><code>npm <span class="hljs-keyword">install</span> <span class="hljs-comment">--save react-router-dom</span>
</code></pre><p>For simplicity, we remove all of the other files under the <code>/src</code> directory. </p>
<p>Then, we create a new <code>index.js</code> file:</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;

<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
);
</code></pre><p>And a new <code>App.js</code> as well:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><p>Check out the code at this point <a target="_blank" href="https://github.com/projectkenneth/reactjs-module-based-routing/tree/Initial-State">here</a>.</p>
<h3 id="create-the-components">Create The Components</h3>
<p>For better maintainability, the components should be grouped by their module. So, we'll have one directory per module and each of these directories will only contain the components relevant to their respective module.</p>
<p>Just to recap, we'll need to create the components:</p>
<ul>
<li>Draft Listing</li>
<li>Draft Update</li>
<li>Post Listing</li>
<li>Post Update</li>
</ul>
<p>Lastly, we'll need to create a Home component as well just so we can render a homepage.</p>
<p>For the Draft and Post Update components, we will use the <code>useParams</code> function from <code>react-router-dom</code> to get the draft or post ID passed in the URL.</p>
<p>Here's how the Draft Update component looks like:</p>
<pre><code><span class="hljs-keyword">import</span> { useParams } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DraftUpdate</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> { draftId } = useParams();

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is Draft Update: {draftId}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DraftUpdate;
</code></pre><p>For the Draft and Post Listing components, we will use the Link component from <code>react-router-dom</code> to render links to fake drafts or posts.</p>
<p>Here's how the Draft Listing component looks like:</p>
<pre><code><span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DraftListing</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is Draft Listing<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/drafts/1'</span>&gt;</span>Draft 1<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/drafts/2'</span>&gt;</span>Draft 2<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DraftListing;
</code></pre><p>You can check out how the code looks like at this point <a target="_blank" href="https://github.com/projectkenneth/reactjs-module-based-routing/tree/Added-components">here</a>.</p>
<h3 id="create-the-initial-routing">Create The Initial Routing</h3>
<p>Now, onto the actual routing. We'll need to add the ff. code to the <code>App</code> component:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/'</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/drafts'</span>&gt;</span>Drafts<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/posts'</span>&gt;</span>Posts<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Home}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftListing}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/posts'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{PostListing}</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span>
</code></pre><p>In the updated <code>App</code> code, we now have a navigation section, and the routes to the Homepage, Draft Listing, and Post Listing have been defined.</p>
<p>Now, how should we add the routes to the draft and post update components?</p>
<p>We can do this by updating the <code>Switch</code> section of the <code>App</code> component code:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Home}</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftListing}</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts/:draftId'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftUpdate}</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/posts'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{PostListing}</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/posts/:postId'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{PostUpdate}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>
</code></pre><p>Technically, the above approach will already work. But, there's actually a couple of issues here:</p>
<ul>
<li>The references to the route names are scattered across the files which makes the project hard to maintain. For example, the path <code>drafts</code> can be found in both the <code>App</code> and <code>DraftListing</code> components. If we want to change this path, we'd have to update both files.</li>
<li>The routing for the Draft Management and Post Management module are mixed up together in one file. Essentially defeating the purpose of defining modules in the first place.</li>
</ul>
<p>Before moving to the next section, you can check out what the code looks like at this point <a target="_blank" href="https://github.com/projectkenneth/reactjs-module-based-routing/blob/Initial-Routing-Configuration">here</a>.</p>
<h2 id="transforming-to-modular-routing">Transforming to Modular Routing</h2>
<p>To address the issues I mentioned, we have to consider one very important thing:</p>
<blockquote>
<p>Modules should be stand-alone.</p>
</blockquote>
<p>Modules should be treated as smaller applications inside a larger one. They have to be in charge of everything related to them and that includes routing. This means that we should detach a module's routing configuration from the <code>App</code> component and place the configuration inside its respective module.</p>
<p>To do this, we need to introduce <em>Module Routers</em>.</p>
<h3 id="module-routers">Module Routers</h3>
<p>A module router, as its name suggests, handles all the routing for a module. For this example, <code>Module Routers</code> are special components.</p>
<p>Before creating the module router we first need to update the current routing configuration.</p>
<p>In the <code>App</code> component, instead of directly specifying the routes to the Draft Management components, we now do this:</p>
<pre><code>// From these
<span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftListing}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts/:draftId'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftUpdate}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>

// To these
<span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">'/drafts'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftRouter}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>
</code></pre><p>So, what we're doing here is:</p>
<blockquote>
<p>All routing that starts with the path <code>/drafts</code> will be handled by the <code>DraftRouter</code></p>
</blockquote>
<p>We then create the actual <code>DraftRouter</code> component. It looks like this:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DraftRouter</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> { path } = useRouteMatch();

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>You are in draft management<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">{path}</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">DraftListing</span> <span class="hljs-attr">modulePath</span>=<span class="hljs-string">{path}</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">path</span>}/<span class="hljs-attr">:draftId</span>`} <span class="hljs-attr">component</span>=<span class="hljs-string">{DraftUpdate}</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}
</code></pre><p>Here's what's happening inside the <code>DraftRouter</code>:</p>
<ul>
<li>We use the <code>useRouteMatch</code> function to get the current route path. This way, we don't have to hardcode the phrase <code>drafts</code> and it will only be defined in the <code>App</code> component.</li>
<li>We then defined a couple of sub-routes. If we received only the <code>/drafts</code> path, we'll render the <code>DraftListing</code> component. If we received the draft ID path, we render the <code>DraftUpdate</code> component.</li>
</ul>
<p>Additionally, you may have noticed the <code>modulePath</code> property of the <code>DraftListing</code> component. This is because, at this point, we've updated the <code>DraftListing</code> component to this:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DraftListing</span>(<span class="hljs-params">props</span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is Draft Listing<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">props.modulePath</span>}/<span class="hljs-attr">1</span>`}&gt;</span>Draft 1<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">props.modulePath</span>}/<span class="hljs-attr">2</span>`}&gt;</span>Draft 2<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}
</code></pre><p>As you can see, we used the <code>modulePath</code> property to dynamically inject the <code>/drafts</code> path. There's no need to hardcode that path in this component as well.</p>
<p>I've also updated the Post Management module to follow this approach. </p>
<p>To check out the final state of the code, click <a target="_blank" href="https://github.com/projectkenneth/reactjs-module-based-routing/tree/Hello-Module-Routers/">here</a>.</p>
<h2 id="summary">Summary</h2>
<p>So, that's it! We've successfully implemented modular routing in React.</p>
<p>At this stage, our <code>src</code> directory looks like this:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632731800452/wAWv1K2D2.png" alt="image.png" /></p>
<p>With this approach, we can now enjoy the ff. benefits:</p>
<ul>
<li>If we need to change a module's root path, we just need to change it in one place, in the <code>App</code> component.</li>
<li>If we need to remove/disable a module, we can simply remove its routing configuration from the <code>App</code> component.</li>
<li>The routes are easier to maintain since each module has its own configuration.</li>
</ul>
<p>Anyway, I hoped you learned something new from me today. Let me know your thoughts in the comments!</p>
<hr />
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Representing Common Data Structures In SQL]]></title><description><![CDATA[When designing an application, you usually start with the business processes involved. Then, you extract the data models involved and map out the respective components/services. It's quite a simplified explanation but, you get what I mean!
As part of...]]></description><link>https://blog.projectkenneth.com/representing-common-data-structures-in-sql</link><guid isPermaLink="true">https://blog.projectkenneth.com/representing-common-data-structures-in-sql</guid><category><![CDATA[data structures]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[Databases]]></category><category><![CDATA[SQL]]></category><category><![CDATA[100DaysOfCode]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Fri, 24 Sep 2021 10:53:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632479962833/6FCbidkvt.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When designing an application, you usually start with the business processes involved. Then, you extract the data models involved and map out the respective components/services. It's quite a simplified explanation but, you get what I mean!</p>
<p>As part of this planning, we use conceptual data structures to represent data models. Once we start the implementation, we then translate these data structures into actual database tables. Ever wondered how that's done? Then you're at the right place!</p>
<p>In this post, we'll talk about how to represent some of the common data structures in an SQL database. </p>
<h2 id="what-data-structures-are-we-working-on">What data structures are we working on?</h2>
<p>For the purpose of this post, we'll cover the ff. data structures:</p>
<ul>
<li><strong>Linked Lists.</strong> A list of items where each item can be connected to one or both of the items directly beside them.</li>
<li><strong>Graphs.</strong> Consists of nodes that can be connected to one or more other nodes.</li>
<li><strong>Trees.</strong> Similar to graphs but without any loops.</li>
<li><strong>Stacks.</strong> A list of items and follows the last-in-first-out principle.</li>
<li><strong>Queues.</strong> A list of items and follows the last-in-first-out principle.</li>
</ul>
<h2 id="lets-simplify-first">Let's simplify first!</h2>
<p>We can go ahead and define the SQL representation for the data structures mentioned above, but, we can still simplify this!</p>
<p>In fact, some of the characteristics mentioned above are more tied to how these structures behave and not on how they store data. After realizing this, I further grouped the data structures into 2 categories:</p>
<ul>
<li><strong>Linear Structures.</strong> These are the data structures that have "edges" or linear connections between their nodes. I placed Linked Lists, Graphs and, Trees under this category.</li>
<li><strong>Ranked Structures.</strong> These are the data structures that are similar to flat lists and where the order of the items is important. I placed Stacks and Queues under this category.</li>
</ul>
<p>Now that we have these categories, we don't really need to represent each individual data structure in SQL. We just need to represent these 2 categories instead!</p>
<h2 id="time-to-represent">Time to represent!</h2>
<p>It's time for me to show you how I will represent the above categories in SQL. Let's go!</p>
<h3 id="linear-structures">Linear Structures</h3>
<p>In terms of representing linear structures in SQL, we just need to take note of 2 things:</p>
<ul>
<li>Each node can have 1 or more edges</li>
<li>Each edge can only go in 1 direction (from Node A to Node B). If we want to represent a reverse edge, we should create a different record for it.</li>
</ul>
<p>Here's the ERD for Linear Structures:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632478309410/mGno1pQTo.png" alt="Graph-Tree-LinkedList.png" /></p>
<p>In the above diagram, we used a many-to-many pattern where we defined 2 tables:</p>
<ul>
<li><strong>Node.</strong> This represents each node in the linear structure.</li>
<li><strong>Edge.</strong> This represents each edge. For the direction, it's always represented as from <em>NodeA</em> to <em>NodeB</em>.</li>
</ul>
<p>Additionally, each node can have 0 or more edges. </p>
<h3 id="ranked-structures">Ranked Structures</h3>
<p>In terms of representing ranked structures, we just need to take note of 2 things:</p>
<ul>
<li>We need to represent lists</li>
<li>Each list should contain one or more items with reference to an item's rank</li>
</ul>
<p>Here's the ERD for Ranked Structures:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632479353234/mk-rwgfJFM.png" alt="Stack-Queue.png" /></p>
<p>In the above diagram, we defined 3 tables:</p>
<ul>
<li><strong>Item.</strong> This represents each item that can be part of a list.</li>
<li><strong>ItemList.</strong> This represents a list.</li>
<li><strong>ItemRank.</strong> This maps out which items belong to which list. Additionally, each mapping will also indicate the rank of an item in a particular list.</li>
</ul>
<p>We made this diagram more flexible so that we can put a single item in multiple lists. Additionally, each ItemRank record has 2 primary keys: <em>ItemListId</em> and <em>Rank</em>. This means that in each list, we don't want items to share a particular rank.</p>
<p>Also, there are other approaches to doing this. If you happen to know one, I'd love to hear from you so, share your thoughts in the comments below!</p>
<h2 id="summary">Summary</h2>
<p>In this post, we went through how to represent some of the common data structures in an SQL database using the ff. steps:</p>
<ol>
<li><strong>What?</strong> Identify the characteristics of the data structure.</li>
<li><strong>Simplify!</strong> Shift your focus to how the data structure stores data.</li>
<li><strong>Represent!</strong> Use the simplified information to create a set of SQL tables to represent the data structure.</li>
</ol>
<p>I know there are tons of other ways to represent these common data structures in SQL.  If you know one, feel free to share them in the comments!</p>
<hr />
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[How To Break Down User Stories Into Smaller Tasks]]></title><description><![CDATA[In this post, I'll talk about my strategy for breaking down user stories into smaller tasks.
What's a User Story?
Before we start, let's define what user stories are. A user story is an informal, natural language description of a software system feat...]]></description><link>https://blog.projectkenneth.com/how-to-break-down-user-stories-into-smaller-tasks</link><guid isPermaLink="true">https://blog.projectkenneth.com/how-to-break-down-user-stories-into-smaller-tasks</guid><category><![CDATA[planning]]></category><category><![CDATA[software development]]></category><category><![CDATA[General Advice]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[100DaysOfCode]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Wed, 22 Sep 2021 12:04:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632311141523/7KBSIqRqc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, I'll talk about my strategy for breaking down user stories into smaller tasks.</p>
<h2 id="whats-a-user-story">What's a User Story?</h2>
<p>Before we start, let's define what user stories are. <a target="_blank" href="https://en.wikipedia.org/wiki/User_story">A user story is an informal, natural language description of a software system feature</a>. </p>
<p>One of the common formats used for creating a user story is this:</p>
<blockquote>
<p>As a <strong>&lt;user with this role&gt;</strong>, I should be able to <strong>&lt;perform this action&gt;</strong> to <strong>&lt;achieve this goal&gt;</strong>.</p>
</blockquote>
<p>Let's look at a real-world example for a blog application:</p>
<blockquote>
<p>As a <strong>content editor</strong>, I should be able to <strong>create a draft</strong> to <strong>work on an article over some time</strong>.</p>
</blockquote>
<h2 id="why-do-i-need-to-define-smaller-tasks">Why Do I Need To Define Smaller Tasks?</h2>
<p>In my experience, breaking down user stories into smaller tasks can help identify common tasks that were originally spread out across multiple user stories. </p>
<p>Remember, user stories are closer to business requirements and not technical ones.</p>
<p>Here's a good example. Let's say that there are a couple of user stories defined to confirm with a user before proceeding with an action. When we break these user stories down, we'll discover that there's a need for a confirmation popup. Since this is a reusable component, we can better plan who will implement it and when will it be implemented.</p>
<p>Essentially, breaking down user stories into smaller tasks allow devs to:</p>
<ul>
<li>Better plan their tasks, therefore, allowing them to provide more accurate estimates</li>
<li>Have a better bug-fixing experience since issues can be mapped to each specific task instead of the larger-scoped user story</li>
<li>Reduce duplicate work (as described in the confirmation popup scenario above)</li>
</ul>
<h2 id="lets-break-it-down">Let's Break It Down</h2>
<p>Now, let's work on the real-world example I gave earlier. </p>
<p>When breaking down a user story, I first think of the following categories:</p>
<ol>
<li>Security</li>
<li>Pre-conditions</li>
<li>Action</li>
</ol>
<p>Each category can either have one or multiple tasks. Let's discuss in detail in each of their respective sections.</p>
<h3 id="security">Security</h3>
<p>The most important category and is even the first part of the user story. In this category, we'll answer the question:</p>
<blockquote>
<p>Who is allowed to perform the action?</p>
</blockquote>
<p>The example user story is only targeted at content editors. Therefore, we need to ensure that. </p>
<p>Since the user story is simple enough, I'll only add one task under this category:</p>
<ul>
<li>Check that the user should have a <strong>Content Editor</strong> role.</li>
</ul>
<p>For more complicated systems, another consideration can be delegation. If a content editor went on leave and has assigned his/her backup editor, the check for this can be another task as well.</p>
<p>Also, the reason why I define the security-related tasks first is that it is going to be used by all the subsequent tasks. This means, that it will be the first task I do and will be implemented as a common/reusable component.</p>
<h3 id="pre-conditions">Pre-conditions</h3>
<p>The tasks under this category should answer this question:</p>
<blockquote>
<p>What needs to be done before the user can perform the action?</p>
</blockquote>
<p>Note that these actions should only be performed after the security checks.</p>
<p>For our example user story, the ff. tasks can be added as part of this category:</p>
<ul>
<li>Check that the user already has a blog. If not, ask the user to create a blog first.</li>
</ul>
<p>In some cases, the smaller tasks here might get attached to another user story.</p>
<p>For example, instead of "asking to create a blog", we may link to a "getting started" feature that was defined by a different user story.</p>
<p>That doesn't mean we don't need to ensure these conditions are met first. These checks are still part of the user story.</p>
<h3 id="action">Action</h3>
<p>Now, on to the main requirement. In this category, we answer this question:</p>
<blockquote>
<p>How can we enable the action for the user?</p>
</blockquote>
<p>Additionally, we should also include validation tasks under this category.</p>
<p>In our case, we'll add the ff. tasks under this category:</p>
<ul>
<li>Add a <strong>New Draft</strong> button to the main navigation.</li>
<li>Once the <strong>New Draft</strong> button is clicked, display the main WYSIWYG editor.</li>
<li>Add a <strong>Save</strong> button to the WYSIWYG editor.</li>
<li>Once the <strong>Save</strong> button is clicked, if there's content in the editor, we create a new draft record and navigate to the draft listing page.</li>
<li>Once the <strong>Save</strong> button is clicked, if the editor is empty, we navigate away from the editor.</li>
</ul>
<p>In the above tasks, everything about the WYSIWYG editor is out of scope. The kind of editor plugin or the other behaviors that should be available in it should all be considered in a separate user story. We just assume that the editor is available for integration.</p>
<h2 id="in-summary">In Summary</h2>
<p>We've reached the end! That one-liner user story has been broken down into 7 smaller tasks.</p>
<p>Just for a quick recap, here are the tasks:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Category</td><td>Task Description</td></tr>
</thead>
<tbody>
<tr>
<td>Security</td><td>Check that the user should have a <strong>Content Editor</strong> role.</td></tr>
<tr>
<td>Pre-conditions</td><td>Check that the user already has a blog. If not, ask the user to create a blog first.</td></tr>
<tr>
<td>Action</td><td>Add a <strong>New Draft</strong> button to the main navigation.</td></tr>
<tr>
<td>Action</td><td>Once the <strong>New Draft</strong> button is clicked, display the main WYSIWYG editor.</td></tr>
<tr>
<td>Action</td><td>Add a <strong>Save</strong> button to the WYSIWYG editor.</td></tr>
<tr>
<td>Action</td><td>Once the <strong>Save</strong> button is clicked, if there's content in the editor, we create a new draft record and navigate to the draft listing page.</td></tr>
<tr>
<td>Action</td><td>Once the <strong>Save</strong> button is clicked, if the editor is empty, we navigate away from the editor.</td></tr>
</tbody>
</table>
</div><p>Again, breaking down user stories into smaller tasks enables better task planning and management. It is a necessary step for devs. </p>
<p>Also, there are other approaches to doing this. If you happen to know one, I'd love to hear from you so, share your thoughts in the comments below!</p>
<hr />
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[A Quick Look: The Software Architecture of Common Web App Features]]></title><description><![CDATA[In this post, I'll walk you through how to implement some of the most common web application features.
For each feature, we'll show the ff. three details:

A real-world example as well as a description of the main challenges for the feature
A list of...]]></description><link>https://blog.projectkenneth.com/a-quick-look-the-software-architecture-of-common-web-app-features</link><guid isPermaLink="true">https://blog.projectkenneth.com/a-quick-look-the-software-architecture-of-common-web-app-features</guid><category><![CDATA[software architecture]]></category><category><![CDATA[design principles]]></category><category><![CDATA[features]]></category><category><![CDATA[hashnodebootcamp]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Tue, 21 Sep 2021 20:23:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632254644640/UY_Rc9fsJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, I'll walk you through how to implement some of the most common web application features.</p>
<p>For each feature, we'll show the ff. three details:</p>
<ol>
<li>A real-world example as well as a description of the main challenges for the feature</li>
<li>A list of components used in the feature</li>
<li>Component diagram</li>
</ol>
<p>Note though that the component list and diagram are not representative of how the real-world examples I provided were actually implemented.</p>
<p>Lastly, the components mentioned here will be abstractions and will therefore not be attached to any specific services/platforms. This will be more of a conceptual overview.</p>
<p>With all of that out of the way, let's start diving in!</p>
<h2 id="reporting">Reporting</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632054749124/oh8EmUfqe.png" alt="image.png" /></p>
<p>The idea of a reporting feature is to display summarized and useful information to users. In most cases, reporting features deal with tons of data. In the above screenshot from Google Analytics, all the data received from websites are summarized and presented using various graphs.</p>
<p>The primary challenge for a reporting feature is ensuring that the summarized data loads quickly. Therefore, the process of summarizing data should be done by a different process separate from the frontend. The frontend's job is to retrieve the summarized data. Nothing more.</p>
<h3 id="component-breakdown">Component Breakdown</h3>
<ul>
<li><strong>Data Ingestor.</strong>  This component receives all the data from all possible sources.</li>
<li><strong>Data Transformer.</strong> The raw data is then transformed by a separate process.</li>
<li><strong>Reporting Database.</strong> Once the data is transformed, it will then be stored in a separate reporting table/cache. This reporting table/cache will then be accessed directly by the frontend.</li>
</ul>
<h3 id="component-diagram">Component Diagram</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632253073417/oxcMy1HYh.png" alt="Reporting.png" /></p>
<h2 id="search">Search</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632055597049/G-i8S13q4.png" alt="image.png" /></p>
<p>For sites with high data volume, providing a search feature is crucial. Search pages should be able to provide results quickly. For more complicated sites, search results are not just ranked by text matching but also by determining search keyword relevance as well.</p>
<p>To achieve this, the searchable items should be indexed beforehand.</p>
<h3 id="component-breakdown">Component Breakdown</h3>
<ul>
<li><strong>Search Index.</strong></li>
<li><strong>Middle Man.</strong> This is the one responsible for interacting with the search index and sending over the search results to the frontend. Paginating and counting over the results should be done by this component as well.</li>
<li><strong>Cache.</strong> For apps with a really large amount of data, the search results are even cached.</li>
</ul>
<h3 id="component-diagram">Component Diagram</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632253063037/fOq0YSFDR.png" alt="Search.png" /></p>
<h2 id="social-feed">Social Feed</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632057290993/A57TWtWsG.jpeg" alt="dole777-EQSPI11rf68-unsplash.jpg" /></p>
<p>A social feed basically shows a list of items relevant to a user, like text or image posts. The relevancy is usually based on two factors:</p>
<ul>
<li>The closeness of the post author to the user</li>
<li>The amount of interest the user has in the post's topic</li>
</ul>
<p>To achieve this, feeds should be pre-calculated. Meaning, a separate and ongoing process will determine the posts that will make up a user's feed. This way, the feed items are prepared before the user even visits his/her feed page.</p>
<h3 id="component-breakdown">Component Breakdown</h3>
<ul>
<li><strong>User Database.</strong> Will house all the users and their relationships.</li>
<li><strong>Post Database.</strong> Will house all the posts created by users. This database should also contain the post's topics as determined by the system.</li>
<li><strong>Feed Generator.</strong> The one responsible for determining and compiling the posts relevant to a user. The compiled posts will then be generated as "feed items" and will be stored in a feed database.</li>
</ul>
<h3 id="component-diagram">Component Diagram</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632253054409/fwmQdUo5t.png" alt="Social Feed.png" /></p>
<h2 id="images">Images</h2>
<p>Images are not technically a full-blown feature but they should be handled properly to deliver a better user experience. </p>
<p>For example, a user can upload a high-definition image (20MB) and, if there's no post-processing done on this original image, showing it on galleries will be a performance concern. Imagine serving a 20MB file to 1,000 users every minute. I won't do that math, but, that's not really ideal.</p>
<h3 id="component-breakdown">Component Breakdown</h3>
<ul>
<li><strong>Image Processor.</strong> This will transform the original image into multiple versions (in different sizes) depending on what's needed by the frontend.</li>
</ul>
<h3 id="component-diagram">Component Diagram</h3>
<p>In this diagram, it is assumed that the images are displayed on a gallery page showing the small version. Then, on a details page which shows a medium version of the image.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632253046039/scFhpdmB0.png" alt="Images (1).png" /></p>
<h2 id="and-now-the-end-is-near">And now, the end is near...</h2>
<p>I hoped you enjoyed reading this article and learned something new from me. I'd be happy to hear your thoughts so be sure to comment down below.</p>
<hr />
<h3 id="credits">Credits</h3>
<ul>
<li>Social Feed sample photo by <a target="_blank" href="https://unsplash.com/photos/EQSPI11rf68">dole777 from Unsplash</a>.</li>
</ul>
<p>Hey, you! Follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[As a Software Developer, I Wish I Had This Mindset When I Was Young]]></title><description><![CDATA[If I can go back 5 years and meet my younger self, I'd give him one piece of advice.

Your professional growth can happen outside of work.

Looking back, I really believe that this mindset would've helped my younger self a lot. Let me tell you why.
T...]]></description><link>https://blog.projectkenneth.com/as-a-software-developer-i-wish-i-had-this-mindset-when-i-was-young</link><guid isPermaLink="true">https://blog.projectkenneth.com/as-a-software-developer-i-wish-i-had-this-mindset-when-i-was-young</guid><category><![CDATA[tips]]></category><category><![CDATA[#growth]]></category><category><![CDATA[personal]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Fri, 17 Sep 2021 21:40:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631909823506/JBJjABOaJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If I can go back 5 years and meet my younger self, I'd give him one piece of advice.</p>
<blockquote>
<p>Your professional growth can happen outside of work.</p>
</blockquote>
<p>Looking back, I really believe that this mindset would've helped my younger self a lot. Let me tell you why.</p>
<h2 id="the-tech-industry-grows-so-fast">The tech industry grows so fast!</h2>
<p>5 years ago, my mindset was very linear. My strategy was just to gain enough experience at one company then, bring that experience to the next one. Outside work, it was all fun. I didn't spend any time studying or researching what's up in the tech space. Then, reality kicked me hard.</p>
<p>The first few roles I had were very similar in terms of the core tech stack used. I was introduced to some new frameworks/platforms along the way. At the time, I thought that being loyal to a single tech stack was enough.</p>
<p>After a few years, I moved to a start-up company. The tech stacks they were using were from everywhere! That's when I realized that most of my technical knowledge was no longer up to date. Azure was everywhere. It was the first time I heard about AngularJS but, Angular 2 was already booming. It felt like I was left behind.</p>
<p>I'm not discounting the experiences I gained from my first few roles. My knowledge of their respective tech domains improved a lot. Plus, I was also able to sharpen my soft skills during those times.</p>
<p>The point is, my personal choices have led me to play catch-up with the rapid changes in the tech industry. That wasn't fun to do. With all honesty, that's on me.</p>
<h2 id="we-all-have-agendas">We all have agendas...</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631908466193/KK1saXttt.jpeg" alt="main-qimg-9e45a7085dd95ecfb7769adad11ca473.jfif" /></p>
<p>The thing is, companies have agendas. People do, too. The moment a person gets employed, the company's and that person's agendas are intersecting. Their technical interests are aligned at this time. </p>
<p>The only thing permanent is change. Sooner or later, there's going to be a time when these two agendas start moving away from each other for whatever reason. This can happen more frequently at the start of one's career since this is usually the "experimental" stage.</p>
<p>5 years ago, this parting of ways happened to me very quickly (and abruptly!). Unfortunately, because of my mindset at the time, I didn't have any vision of what's next. That's when I realized that I should've ensured that I had relevant and up-to-date skills way before these things happened.</p>
<h2 id="find-a-way-to-your-goals">Find a way to your goals.</h2>
<p>I shouldn't have been content with only the knowledge that's directly in front of me. I should've explored my other interests and should've checked out the trends outside the bubble I'm in. If I found something interesting and I felt that it was worth studying, I should've gone for it.</p>
<p>Here's an example. Let's assume I'm currently a web developer in a company focusing on web apps. Then one day, I suddenly became curious about mobile development. This curiosity grew further because I also discovered that mobile development is becoming the next big thing in the industry. What should I do?</p>
<p>I believe there are two options:</p>
<ul>
<li>I can talk to the management and ask if this learning path can be supported. I can check if there are plans to build a mobile development team and bank on that.</li>
<li>I can take on the learning path as a personal improvement exercise. This can serve as a stepping stone for me to move to a mobile development role in or out of my current company.</li>
</ul>
<p>There are a few other scenarios here but, let's not focus on them. Let's focus on the common factor among all of these scenarios — putting in the effort is a must.</p>
<h2 id="my-growth-my-responsibility">My growth. My responsibility.</h2>
<p>Even if there's a bunch of training and learning opportunities provided by a company, it is still my choice whether to grab them or not. This is more true if I had to find these training and learning opportunities outside of the company. Whatever the case is, it should be a conscious effort on my part.</p>
<h3 id="how-should-i-study">How should I study?</h3>
<p>So, what kind of training and learning opportunities am I talking about? These can be conferences, online/in-person training, or certifications. One big concern on this, especially if they're totally not company-sponsored, is the cost. I personally believe that paying for these things is a form of investment in myself. </p>
<p>Of course, it is never a good idea to force oneself to pay for something if they're not comfortable doing so. So, I don't force it if it's not amenable to my current financial situation. During these times, I check free alternatives and focus more on self-practice.</p>
<h3 id="when-do-i-study">When do I study?</h3>
<p>Another big challenge is finding a way to fit all these learning activities into my schedule without affecting the quality of my work. It's not easy but, nobody said it'll be.</p>
<p>Here are a few approaches to handle this that I'd recommend to my younger self:</p>
<ul>
<li><p><strong>Fit it during work hours.</strong> If the learning opportunities are company-sponsored then, this is doable. If not, try squeezing in some readings or watching some tutorials before the day ends. It would also be nice if there's a way to practice during this time. Of course, this is subject to company culture and policies. Check first before doing this.</p>
</li>
<li><p><strong>Pour in some extra time outside of work.</strong> Now, this is more challenging than finding time at work since everyone has their own circumstances. The benefit of doing it this way is that there'll be more freedom and flexibility when it comes to studying. Note though, that it's very important to find enough time to rest as well as to attend to personal responsibilities. Make sure to always protect your personal life!</p>
</li>
<li><p><strong>Be flexible.</strong> Not everything is black and white. If studying during working hours is not possible for a certain day, then probably do it outside work for that day. Of course, if you have to attend to some personal matters, then you can try to squeeze in studying during working hours — again, subject to the same conditions mentioned above.</p>
</li>
</ul>
<p>Whatever approach is preferred, the ability to deliver quality work should not be affected in any way. Remember, the goal is to grow and not to get fired!</p>
<p>The key is finding the right balance to ensure obligations and aspirations do not conflict with each other.</p>
<h2 id="and-now-the-end-is-near">And now, the end is near...</h2>
<p>Thankfully, I'm already living by this mindset and I am always yearning for growth!</p>
<p>Honestly, I would've wanted to go back in time and physically tell my younger self all of these but that's not really possible, isn't it? Nevertheless, I hope this article can help some of the other younger developers out there.</p>
<p>Anyway, I hoped you enjoyed reading this article and learned something new from me. I'd be happy to hear your thoughts so be sure to comment down below.</p>
<p>Also, follow me on <a target="_blank" href="https://twitter.com/projectkenneth">Twitter</a>!</p>
]]></content:encoded></item><item><title><![CDATA[The Birth of Project Kenneth]]></title><description><![CDATA[It took me a while before I was finally able to start working on my online presence. I've been in the industry for almost 10 years. I believe that this is the perfect time to have one. And so, I worked on it! Let me share with you my journey so far.
...]]></description><link>https://blog.projectkenneth.com/the-birth-of-project-kenneth</link><guid isPermaLink="true">https://blog.projectkenneth.com/the-birth-of-project-kenneth</guid><category><![CDATA[hashnodebootcamp]]></category><category><![CDATA[Technical writing ]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Tue, 14 Sep 2021 12:32:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631621668732/9VCEOtrKP.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It took me a while before I was finally able to start working on my online presence. I've been in the industry for almost 10 years. I believe that this is the perfect time to have one. And so, I worked on it! Let me share with you my journey so far.</p>
<h2 id="the-paths-not-taken-and-taken">The Paths Not Taken (and Taken)</h2>
<p>It all started in September 2020 and, my main focus was "How can I share my knowledge in the most effective way?".</p>
<p>At the time, I had three possible paths in mind: side projects, technical articles and, video tutorials.</p>
<p>Since side projects and video tutorials are more interactive, they were my initial choices. Unfortunately, I was dealing with a lot of stuff then. Because of that, I know I lacked the biggest requirement for the two: time.</p>
<p>This is why I chose to write technical articles instead. Since every article is independent of each other, I can work on them whenever I'm free. Essentially, writing technical articles was the least demanding choice for me.</p>
<h2 id="on-technical-articles">On Technical Articles</h2>
<p>For my articles, I chose to focus on the following topics:</p>
<ol>
<li><strong>Tutorials</strong> - I cover the usual step-by-step instructions on how to do certain dev tasks.</li>
<li><strong>Technical Thought Exercises</strong>- Like <a target="_blank" href="https://www.disneyplus.com/series/what-if/7672ZVj1ZxU9">Marvel</a>, I focus on the "what if?" questions in these articles.</li>
<li><strong>The Developer Life</strong> - I know this is not 100% technical but, we do have lives, right?</li>
</ol>
<p>As for my actual technical focus, I'm writing about JavaScript, C#, Azure, OutSystems, .NET, Java, HTML and, CSS. Basically, I cover the tech stack I'm more familiar with as well as whatever I'm studying at present.</p>
<h2 id="stepping-it-up">Stepping It Up</h2>
<p>2020 ended with me having published just two articles. My next article was published almost half a year later (June 2021). Since then, I've been publishing around two articles per month!</p>
<p>The majority of my articles are under the "Technical Thought Exercises" category. I'm planning to publish more tutorials in the next couple of weeks. Be sure to look out for my upcoming articles!</p>
<h2 id="wrapping-it-up">Wrapping It Up</h2>
<p>I do believe that my writing style has significantly improved. I have learned a lot from others. I am now more focused on quality and branding. Of course, I'm always trying to be more consistent.</p>
<p>I know that I still have more to learn. I'm always open to trying out new things. In fact, I am currently registered to the <a target="_blank" href="https://hashnode.com/bootcamp">Hashnode Bootcamp - The Art &amp; Business of Technical Writing</a>. I'm so excited to learn more during this event!</p>
<p>Anyway, thank you so much for reading about my journey!</p>
<p>What do you think should I write about next? Share your thoughts in the comments!</p>
]]></content:encoded></item><item><title><![CDATA[Creating an Event Listener: The Usual, The Okay and The Complicated]]></title><description><![CDATA[This post is part of a  series that explores how flexible programming languages and frameworks can get. We all know that with any given task, there are several approaches available to achieve it. Let's look at this in action!

In this post, we will l...]]></description><link>https://blog.projectkenneth.com/creating-an-event-listener-the-usual-the-okay-and-the-complicated</link><guid isPermaLink="true">https://blog.projectkenneth.com/creating-an-event-listener-the-usual-the-okay-and-the-complicated</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[events]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Fri, 10 Sep 2021 05:04:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631250186728/szAcCWTnl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><em>This post is part of a  <a target="_blank" href="https://blog.projectkenneth.com/series/the-usual-to-complicated">series</a> that explores how flexible programming languages and frameworks can get. We all know that with any given task, there are several approaches available to achieve it. Let's look at this in action!</em></p>
</blockquote>
<p>In this post, we will look at the different approaches in creating an Event Listener.</p>
<p>Of course, there's probably more than three ways to ways to do this in JavaScript, but, I carefully selected three unique ones that better matches the ff. categories: The Usual, The Okay, and The Complicated.</p>
<h2 id="the-usual">The Usual</h2>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EventListener</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> _callbackA = <span class="hljs-function">() =&gt;</span> {};
    <span class="hljs-keyword">let</span> _callbackB = <span class="hljs-function">() =&gt;</span> {};

    <span class="hljs-built_in">this</span>.registerEventAHandler = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">callback</span>) </span>{
        _callbackA = callback;
    }

    <span class="hljs-built_in">this</span>.registerEventBHandler = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">callback</span>) </span>{
        _callbackB = callback;
    }

    <span class="hljs-built_in">this</span>.onEventA = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        _callbackA();
    }

    <span class="hljs-built_in">this</span>.onEventB = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        _callbackB();
    }

    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}
</code></pre><p>In the above implementation, we define a class that has two register functions for two event handlers. Additionally, there are two separate event triggers. Here's how it's used:</p>
<pre><code>let listener = <span class="hljs-keyword">new</span> EventListener();

listener.registerEventAHandler(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event A Happened!'</span>);
});

listener.registerEventBHandler(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event B Happened!'</span>);
});

listener.onEventA();
</code></pre><p>Only downside to this approach is that the handlers and the events are too tightly coupled. Every new event will require two sets of functions to be directly implemented in the class. It works but not really very flexible. Let's step it up a bit.</p>
<h2 id="the-okay">The Okay</h2>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EventListener</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> _callbackMap = {};

    <span class="hljs-built_in">this</span>.registerEventHandler = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName, callback</span>) </span>{
        _callbackMap[eventName] = callback;
    }

    <span class="hljs-built_in">this</span>.onEvent = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName</span>) </span>{
        _callbackMap[eventName]();
    }

    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}
</code></pre><p>The above's a more flexible version — the handlers are now decoupled from the event itself and we can now define multiple event handlers without touching the <code>EventListener</code> class.</p>
<p>The biggest change in this approach is now we've added the <code>_callbackMap</code> private variable. This will store the mapping between each event and their respective handler. This is how it's used:</p>
<pre><code>let listener = <span class="hljs-keyword">new</span> EventListener();

listener.registerEventHandler(<span class="hljs-string">'Event A'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event A Happened!'</span>);
});

listener.registerEventHandler(<span class="hljs-string">'Event B'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event B Happened!'</span>);
});

listener.onEvent(<span class="hljs-string">'Event A'</span>);
</code></pre><p>But what if you need to attach multiple handlers to one event? Technically, this can still be done using this approach. Check this out:</p>
<pre><code><span class="hljs-keyword">let</span> listener = <span class="hljs-keyword">new</span> EventListener();

listener.registerEventHandler(<span class="hljs-string">'Event A'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// First action </span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event A Happened!'</span>);

    <span class="hljs-comment">// Second action</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Now, let\'s do another thing for Event A!'</span>);
});

listener.onEvent(<span class="hljs-string">'Event A'</span>);
</code></pre><p>The above solution works but is not really adhering to the Single Responsibility Principle. It's not really a good design to have one event handler to do two separate actions. By right, there should've been two handlers attached to the same event. Let's look at how that can be done in the next part.</p>
<h2 id="the-complicated">The Complicated</h2>
<p>We now want to be able to attach multiple handlers to a single event. Therefore, we need to change the data type of the <code>_callbackMap</code> variable since each event will now have a list of handlers. Take a look at the new code:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EventListener</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> _callbackMap = {};

    <span class="hljs-built_in">this</span>.registerEventHandler = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName, callback</span>) </span>{
        <span class="hljs-keyword">if</span> (!_callbackMap[eventName]) {
            _callbackMap[eventName] = [];
        }

        _callbackMap[eventName].push(callback);
    }

    <span class="hljs-built_in">this</span>.onEvent = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName</span>) </span>{
        <span class="hljs-keyword">if</span> (_callbackMap[eventName]) {
            _callbackMap[eventName].forEach(<span class="hljs-function">(<span class="hljs-params">handlerData</span>) =&gt;</span> {
                handlerData();
            });
        }
    }

    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}
</code></pre><p>Here's how it's used:</p>
<pre><code>let listener = <span class="hljs-keyword">new</span> EventListener();

let eventAName = <span class="hljs-string">'Event A'</span>;

listener.registerEventHandler(eventAName, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event A Happened!'</span>);
});

listener.registerEventHandler(eventAName, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Now, let\'s do another thing for Event A!'</span>);
});

listener.onEvent(eventAName);
</code></pre><p>The output will now be:</p>
<pre><code><span class="hljs-type">Event</span> <span class="hljs-type">A</span> <span class="hljs-type">Happened!</span>
<span class="hljs-type">Now</span>, <span class="hljs-keyword">let</span>'s <span class="hljs-keyword">do</span> another thing <span class="hljs-keyword">for</span> <span class="hljs-type">Event</span> <span class="hljs-type">A!</span>
</code></pre><p>The above solution now allows multiple handlers for individual events. So, when the event is triggered, all the attached handlers will be executed in the order they were registered. Let's step it up a little bit more. What if we want to control the flow by which the event handlers are executed? Here's how:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EventListener</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> _callbackMap = {};

    <span class="hljs-built_in">this</span>.registerEventHandler = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName, callback, priority = <span class="hljs-number">1</span></span>) </span>{
        <span class="hljs-keyword">if</span> (!_callbackMap[eventName]) {
            _callbackMap[eventName] = [];
        }

        _callbackMap[eventName].push({
            <span class="hljs-attr">callback</span>: callback,
            <span class="hljs-attr">priority</span>: priority
        });

        <span class="hljs-comment">// rearrange the handlers for this event based on priority</span>
        _callbackMap[eventName].sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
            <span class="hljs-keyword">if</span> (a.priority &lt; b.priority) {
                <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (a.priority &gt; b.priority) {
                <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
            }

            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        });
    }

    <span class="hljs-built_in">this</span>.onEvent = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName</span>) </span>{
        <span class="hljs-keyword">if</span> (_callbackMap[eventName]) {
            _callbackMap[eventName].forEach(<span class="hljs-function">(<span class="hljs-params">handlerData</span>) =&gt;</span> {
                handlerData.callback();
            });
        }
    }

    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}

<span class="hljs-keyword">let</span> listener = <span class="hljs-keyword">new</span> EventListener();

<span class="hljs-keyword">let</span> eventAName = <span class="hljs-string">'Event A'</span>;

listener.registerEventHandler(eventAName, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event A Happened!'</span>);
}, <span class="hljs-number">2</span>);

listener.registerEventHandler(eventAName, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Now, let\'s do another thing for Event A!'</span>);
}, <span class="hljs-number">1</span>);

listener.onEvent(eventAName);
</code></pre><p>As for what's changed, the <code>_callbackMap</code> now has a priority field for each of its event-to-handler mapping. When an event is triggered, this priority is used to determine the order of execution of the handlers. </p>
<p>The output will now look like this:</p>
<pre><code><span class="hljs-type">Now</span>, <span class="hljs-keyword">let</span>'s <span class="hljs-keyword">do</span> another thing <span class="hljs-keyword">for</span> <span class="hljs-type">Event</span> <span class="hljs-type">A!</span>
<span class="hljs-type">Event</span> <span class="hljs-type">A</span> <span class="hljs-type">Happened!</span>
</code></pre><p>Pretty neat, right?</p>
<h2 id="the-end">The End</h2>
<p>For your reference, all the code for this post can be found <a target="_blank" href="https://github.com/projectkenneth/tuoc-event-listener">here</a>.</p>
<p>Anyway, there's most likely many more ways to implementing an Event Handler. Feel free to share them by commenting on this post.</p>
<p>I hoped you enjoyed exploring these with me. I'll be posting more in this series (covering other programming languages too!) so make sure to stay tuned!</p>
]]></content:encoded></item><item><title><![CDATA[Introducing RotoscodeJS: Record and share live code snippet changes]]></title><description><![CDATA[I recently released  RotoscodeJS . It's a suite of tools that allows you to record every change you make to a code snippet/file. Then, you can share that recording on your websites or blogs using a player widget. This way, your users can pause at spe...]]></description><link>https://blog.projectkenneth.com/introducing-rotoscodejs-record-and-share-live-code-snippet-changes</link><guid isPermaLink="true">https://blog.projectkenneth.com/introducing-rotoscodejs-record-and-share-live-code-snippet-changes</guid><category><![CDATA[Visual Studio Code]]></category><category><![CDATA[vscode extensions]]></category><category><![CDATA[snippets]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Wed, 01 Sep 2021 11:54:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631303741523/NRtl9JpNk.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently released  <a target="_blank" href="https://rotoscodejs.com/"><strong>RotoscodeJS</strong></a> . It's a suite of tools that allows you to record every change you make to a code snippet/file. Then, you can share that recording on your websites or blogs using a player widget. This way, your users can pause at specific moments.</p>
<p>RotoscodeJS can be embedded on any webpage and even on blogs (as long as the blog supports full embed scripts).</p>
<p>Here it is in action:</p>
<div class="hn-embed-widget" id="rotoscodejs-intro"></div><p><br /></p>
<h1 id="the-recording-process">The Recording Process</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630495664301/__YyTGN9M.gif" alt="Quick Recording Demo" /></p>
<p>So simple, right? Once the recording is complete, an embed code will be provided so you can embed the player widget on your website.</p>
<h1 id="the-build">The Build</h1>
<p>RotoscodeJS is made of 2 components:</p>
<ul>
<li>The  <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=projectkenneth.rotoscodejs-vscodeext">VS Code Extension</a> which serves as the recorder. ( <a target="_blank" href="https://github.com/projectkenneth/rotoscodejs-recorder">Source</a> )</li>
<li>The embeddable player widget. ( <a target="_blank" href="https://github.com/projectkenneth/rotoscodejs-player">Source</a> )</li>
</ul>
<h1 id="your-turn">Your Turn</h1>
<p>Let me know your thoughts on RotoscodeJS. Any feedback is welcome. Looking forward to hearing from you!</p>
<p>If you want to stay updated on RotoscodeJS or on any of my other projects, follow  <a target="_blank" href="https://twitter.com/ProjectKenneth">@projectkenneth</a> (that's me!) on Twitter.</p>
]]></content:encoded></item><item><title><![CDATA[Implementing an Algorithm Selector: The Usual, The Okay and The Complicated]]></title><description><![CDATA[This post is part of a  series that explores how flexible programming languages and frameworks can get. We all know that with any given task, there are several approaches available to achieve it. Let's look at this in action!

In this post, we will l...]]></description><link>https://blog.projectkenneth.com/implementing-an-algorithm-selector-the-usual-the-okay-and-the-complicated</link><guid isPermaLink="true">https://blog.projectkenneth.com/implementing-an-algorithm-selector-the-usual-the-okay-and-the-complicated</guid><category><![CDATA[Java]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[sorting]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Sun, 29 Aug 2021 16:16:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631302769982/v6mMRnc-a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><em>This post is part of a  <a target="_blank" href="https://blog.projectkenneth.com/series/the-usual-to-complicated">series</a> that explores how flexible programming languages and frameworks can get. We all know that with any given task, there are several approaches available to achieve it. Let's look at this in action!</em></p>
</blockquote>
<p>In this post, we will look at the different approaches in implementing an Algorithm Selector. For this article’s purposes, an Algorithm Selector is basically a method or class that determines which appropriate algorithm is best used for a certain input. </p>
<p>Let's say that I want to implement an Algorithm Selector for sorting algorithms. To select the correct algorithm you'll use, I'll base it on the length of the array:</p>
<ul>
<li>For smaller arrays, I decided to use Bubble Sort.</li>
<li>For larger arrays, I want to use Quick Sort.</li>
</ul>
<p>In this example, let's set the threshold to 100. Any array with more than 100 items will be considered a "large" array.</p>
<p>Of course, there's probably more than 3 ways to ways to do this in Java (or any OOP language for that matter), but, I carefully selected three unique ones that better matches the ff. categories: The Usual, The Okay, and The Complicated.</p>
<h2 id="the-usual">The Usual</h2>
<pre><code><span class="hljs-keyword">private</span> int[] sort(int[] arrToSort) {
    <span class="hljs-keyword">if</span> (arrToSort.length &lt;= <span class="hljs-number">100</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.bubbleSort(arrToSort);
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.quickSort(arrToSort);
}

<span class="hljs-keyword">public</span> void execute() {
    <span class="hljs-keyword">var</span> fiftyArray = Helpers.generateArray(<span class="hljs-number">50</span>);
    <span class="hljs-keyword">var</span> hundredFiftyArray = Helpers.generateArray(<span class="hljs-number">150</span>);

    <span class="hljs-keyword">this</span>.sort(fiftyArray); <span class="hljs-comment">// bubble sort</span>
    <span class="hljs-keyword">this</span>.sort(hundredFiftyArray); <span class="hljs-comment">// quick sort</span>
}
</code></pre><p>In the above implementation, I simply used an <code>if</code> statement to determine the correct algorithm to use. Pretty straightforward and it just works. Let's step it up a bit.</p>
<h2 id="the-okay">The Okay</h2>
<pre><code><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span>[] <span class="hljs-title">sort</span>(<span class="hljs-params"><span class="hljs-keyword">int</span>[] arrToSort</span>)</span> {
    <span class="hljs-keyword">var</span> sortingAlgos = <span class="hljs-keyword">new</span> ISortingAlgorithm[] {
        <span class="hljs-keyword">new</span> BubbleSort(),
        <span class="hljs-keyword">new</span> QuickSort()
    };

    <span class="hljs-keyword">var</span> canSort = <span class="hljs-literal">false</span>;
    <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">do</span> {
        canSort = sortingAlgos[i].canSort(arrToSort);

        <span class="hljs-keyword">if</span> (canSort) {
            <span class="hljs-keyword">return</span> sortingAlgos[i].sort(arrToSort);
        }

        i++;
    } <span class="hljs-keyword">while</span> (!canSort &amp;&amp; i &lt; sortingAlgos.length);

    <span class="hljs-keyword">return</span> arrToSort;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span>(<span class="hljs-params"></span>)</span> {
    <span class="hljs-keyword">var</span> fiftyArray = Helpers.generateArray(<span class="hljs-number">50</span>);
    <span class="hljs-keyword">var</span> hundredFiftyArray = Helpers.generateArray(<span class="hljs-number">150</span>);

    <span class="hljs-keyword">this</span>.sort(fiftyArray); <span class="hljs-comment">// bubble sort</span>
    <span class="hljs-keyword">this</span>.sort(hundredFiftyArray); <span class="hljs-comment">// quick sort</span>
}
</code></pre><p>Now we're onto something. I've modified the <code>sort</code> method to use a more flexible way of identifying the best algorithm to use. Instead of hardcoding using an <code>if</code> statement, all sorting algorithms are implemented in their own class. These algorithm classes implements the <code>ISortingAlgorithm</code> interface.</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">ISortingAlgorithm</span> {
    <span class="hljs-function"><span class="hljs-keyword">int</span>[] <span class="hljs-title">sort</span>(<span class="hljs-params"><span class="hljs-keyword">int</span>[] arrToSort</span>)</span>;
    <span class="hljs-function">boolean <span class="hljs-title">canSort</span>(<span class="hljs-params"><span class="hljs-keyword">int</span>[] arrToSort</span>)</span>;
}
</code></pre><p>This interface exposes a <code>canSort</code> method so any class implementation bears the responsibility of checking the input and ultimately declaring "Hey, I'm the one for this array!". A bit cheesy but you get how it works. Additionally, the actual sorting logic (<code>sort</code> method) is implemented inside each algorithm class. </p>
<p>Here's how this looks like for the <code>BubbleSort</code> class:</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BubbleSort</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ISortingAlgorithm</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] sort(<span class="hljs-keyword">int</span>[] arrToSort) {
        System.out.println(<span class="hljs-string">"Sorted "</span> + arrToSort.length+ <span class="hljs-string">" items by bubble sort!"</span>);
        <span class="hljs-comment">// Implement quick sort</span>

        <span class="hljs-keyword">return</span> arrToSort;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">canSort</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] arrToSort)</span> </span>{
        <span class="hljs-keyword">return</span> arrToSort.length &lt;= <span class="hljs-number">100</span>;
    }
}
</code></pre><p>The <code>sort</code> method will then iterate over the array of algorithms. Then, the first one to return <code>true</code> when their <code>canSort</code> method is called will be the algorithm used to sort the input array.</p>
<p>That's quite a bit already, right? Well, let's look at something more exciting.</p>
<h2 id="the-complicated">The Complicated</h2>
<p>The problem with <em>The Okay</em> approach is that the sorting algorithms are tightly coupled with the executing class. All of them are explicitly instantiated inside the <code>sort</code> method. In terms of good OOP design, it's not recommended to have very tight coupling between classes. </p>
<p>So in this approach, we'll use the <a target="_blank" href="https://www.geeksforgeeks.org/chain-responsibility-design-pattern/">Chain of Responsibility</a> design pattern. In this pattern, there's a set of receivers with which the input will pass through. In a few points, here's how this pattern works:</p>
<ol>
<li>Once a receiver receives the input, the receiver will evaluate the input. </li>
<li>If the receiver determines that the input is compatible with it, the receiver will proceed with the actual processing. </li>
<li>If the input is not compatible with the receiver, the current receiver will just pass the input to the next available receiver.</li>
</ol>
<p>For this article, the "receivers" are the sorting algorithm classes. I've now modified them to extend the <code>SortingAlgorithm</code> class:</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SortingAlgorithm</span> {
    <span class="hljs-keyword">private</span> SortingAlgorithm NextAlgo = <span class="hljs-literal">null</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SortingAlgorithm</span>(<span class="hljs-params"></span>)</span> {
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SortingAlgorithm</span>(<span class="hljs-params">SortingAlgorithm NextAlgo</span>)</span> {
        <span class="hljs-keyword">this</span>.NextAlgo = NextAlgo;
    }

    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> boolean <span class="hljs-title">canSort</span>(<span class="hljs-params"><span class="hljs-keyword">int</span>[] arrToSort</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">int</span>[] <span class="hljs-title">sortInternal</span>(<span class="hljs-params"><span class="hljs-keyword">int</span>[] arrToSort</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] <span class="hljs-title">sort</span>(<span class="hljs-params"><span class="hljs-keyword">int</span>[] arrToSort</span>)</span> {
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.canSort(arrToSort)) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.sortInternal(arrToSort);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.NextAlgo != <span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.NextAlgo.sort(arrToSort);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> arrToSort;
        }
    }
}
</code></pre><p>As seen above, the <code>SortingAlgorithm</code> class optionally receives the <code>NextAlgo</code>. This is the next algorithm in the chain and it will be called upon if the current algorithm cannot process the input. For simplicity, if there's no available <code>NextAlgo</code>, the <code>sort</code> method will just return the unprocessed input.</p>
<p>Now, let's look at the actual execution using this approach:</p>
<pre><code><span class="hljs-keyword">var</span> fiftyArray = <span class="hljs-type">Helpers</span>.generateArray(<span class="hljs-number">50</span>);
<span class="hljs-keyword">var</span> hundredFiftyArray = <span class="hljs-type">Helpers</span>.generateArray(<span class="hljs-number">150</span>);

<span class="hljs-keyword">var</span> <span class="hljs-built_in">quickSort</span> = new <span class="hljs-type">QuickSort</span>();
<span class="hljs-keyword">var</span> bubbleSort = new <span class="hljs-type">BubbleSort</span>(<span class="hljs-built_in">quickSort</span>);

<span class="hljs-keyword">var</span> sortChain = new <span class="hljs-type">SortingChain</span>(bubbleSort);

sortChain.<span class="hljs-built_in">sort</span>(fiftyArray); <span class="hljs-comment">// bubble sort</span>
sortChain.<span class="hljs-built_in">sort</span>(hundredFiftyArray); <span class="hljs-comment">// quick sort</span>
</code></pre><p>In the above execution code, the sorting algorithms are actually instantiated outside the algorithm selector class <code>SortingChain</code>. Now, if I need to add/remove sorting algorithms , I don't need to touch the <code>SortingChain</code> class.</p>
<p>If you want to step this up further, you can also use <a target="_blank" href="https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/">Dependency Injection</a> to dynamically load the sorting algorithms. Additionally, there are other design patterns aside from Chain of Responsibility that can be used to achieve the same thing.</p>
<h2 id="the-end">The End</h2>
<p>For your reference, all the code for this post can be found <a target="_blank" href="https://github.com/projectkenneth/tuoc-multiway-logic">here</a>.</p>
<p>Anyway, there's most likely lots of approaches to implementing an Algorithm Selector. Feel free to share them by commenting on this post.</p>
<p>I hoped you enjoyed exploring these with me. I'll be posting more in this series (covering other programming languages too!) so make sure to keep an eye!</p>
]]></content:encoded></item><item><title><![CDATA[Writing a JavaScript Function: The Usual, The Okay and The Complicated]]></title><description><![CDATA[This post is part of a  series  that explores how flexible programming languages and frameworks can get. We all know that with any given task, there are several approaches available to achieve it. Let's look at this in action!

In this post, we will ...]]></description><link>https://blog.projectkenneth.com/writing-a-javascript-function-the-usual-the-okay-and-the-complicated</link><guid isPermaLink="true">https://blog.projectkenneth.com/writing-a-javascript-function-the-usual-the-okay-and-the-complicated</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[functions]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Fri, 13 Aug 2021 16:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631303303198/AmMxNx9pr.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><em>This post is part of a  <a target="_blank" href="https://blog.projectkenneth.com/series/the-usual-to-complicated">series</a>  that explores how flexible programming languages and frameworks can get. We all know that with any given task, there are several approaches available to achieve it. Let's look at this in action!</em></p>
</blockquote>
<p>In this post, we will look at the different approaches in implementing one of the basics in JavaScript: declaring functions. There's probably more than 3 ways to declare functions in JavaScript, it's a fairly flexible language, but, I carefully selected three unique ones that better matches the ff. categories: The Usual, The Okay, and The Complicated.</p>
<h2 id="the-usual">The Usual</h2>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiplyNumbers</span>(<span class="hljs-params">a, b</span>) </span>{
   <span class="hljs-keyword">return</span> a * b;
}
</code></pre><p>We all know about this one. This is simply following the very basic function declaration syntax. Easy to understand and very straightforward. I don' think I need to explain this further. Let's step it up a bit.</p>
<h2 id="the-okay">The Okay</h2>
<pre><code>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">win</span>) </span>{
    win.multiplyNumbers = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a, b</span>) </span>{
        <span class="hljs-keyword">return</span> a * b;
    };
})(<span class="hljs-built_in">window</span>);
</code></pre><p>Now we're onto something. This approach introduces a new layer of scope. A wrapper anonymous function accepts the <code>window</code> object. Inside the anonymous function, the actual multiplication function is assigned to the <code>multiplyNumbers</code> variable of the <code>window</code> object. Since the inner function is attached to the window object, anyone outside of the anonymous function will still be able to access it by simply using the normal syntax:</p>
<pre><code><span class="hljs-attribute">multiplyNumbers</span>(<span class="hljs-number">5</span>, <span class="hljs-number">6</span>);
</code></pre><p>One benefit of this approach is that we can limit the scope of certain variables. Here's another example:</p>
<pre><code>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">win</span>) </span>{
    <span class="hljs-keyword">var</span> PIConst = <span class="hljs-number">3.14</span>;

    win.getCircumference = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">radius</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span> * PIConst * radius;
    };
})(<span class="hljs-built_in">window</span>);
</code></pre><p>In this example, a constant variable is introduced to represent the value of PI. Again, the <code>getCircumference</code> function is still accessible to everyone, but no one will have access to the <code>PIConst</code> variable.</p>
<p>Now, let's move to something more exciting.</p>
<h2 id="the-complicated">The Complicated</h2>
<p>We've looked at the basic function declaration syntax as well as the anonymous approach. What will happen if we combine both? Let's go crazy!</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCircumference</span>(<span class="hljs-params">radius</span>) </span>{
    <span class="hljs-keyword">var</span> PIConst = <span class="hljs-number">3.14</span>;

    <span class="hljs-keyword">return</span> (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">radius_internal</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span> * PIConst * radius_internal;
    })(radius);
}
</code></pre><p>The above approach is pretty much the same as <em>The Okay</em> one. But, instead of an anonymous function wrapping the actual function, I inverted it.</p>
<p>The <code>getCircumference</code> function is not performing the work. It's merely returning an anonymous function that is the one who will do the computation. In terms of the execution, everytime the <code>getCircumference</code> function is called, the internal anonymous function will be executed first. Then, the anonymous function's result will be bubbled out. Looks fun right?</p>
<h2 id="the-end">The End</h2>
<p>There's most likely lots of approaches to declaring functions in JavaScript. Feel free to share them by responding to this post.</p>
<p>I hoped you enjoyed exploring these different approaches with me. I'll be posting more in this series (covering other programming languages too!) so make sure you keep an eye!</p>
]]></content:encoded></item><item><title><![CDATA[Make Siri Control Your TP-Link Kasa Smart Devices]]></title><description><![CDATA[I’ve had a couple of TP-Link Kasa Smart Light Bulbs for the past 2 years. Configured them to be controlled by Google Home and I’ve been lazy to turn our lights on using a switch since then! This has been the setup for 2 years but last week, I wondere...]]></description><link>https://blog.projectkenneth.com/make-siri-control-your-tp-link-kasa-smart-devices-2a6583700aa7</link><guid isPermaLink="true">https://blog.projectkenneth.com/make-siri-control-your-tp-link-kasa-smart-devices-2a6583700aa7</guid><category><![CDATA[smart home]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Sun, 01 Aug 2021 06:31:15 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630177091299/0OOGGswXm.png" alt="Main image" /></p>
<p>I’ve had a couple of TP-Link Kasa Smart Light Bulbs for the past 2 years. Configured them to be controlled by Google Home and I’ve been lazy to turn our lights on using a switch since then! This has been the setup for 2 years but last week, I wondered if there’s a way for my iPhone to natively support controlling these smart light bulbs</p>
<p>A little bit of research here and there and officially, iOS cannot natively support this. Then I found out that if there’s a will, there’s a way! It turns out I can achieve this by combining the powers of IFTTT and iOS Shortcuts. Here’s how I did it.</p>
<h2 id="ifttt">IFTTT</h2>
<p>My goal here was to create an applet that exposed a Webhook as its trigger. The main action in this applet will then be to integrate with the TP-Link Kasa service to control my light bulb. Let’s go through the steps to achieve this.</p>
<ol>
<li><p>I started creating a new applet.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176550439/-UYXqn27h.png" alt /></p>
</li>
<li><p>For the <strong>If This</strong> panel, I used the Webhooks service and configured it to listen to the event “bedroom_light_on”.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176552208/vaueC8ht7.png" alt /></p>
</li>
<li><p>For the <strong>Then That</strong> panel, I used the <strong>TP-Link Kasa</strong> service and chose the <strong>Turn on</strong> action.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176554143/Z7U3DFc6H.png" alt /></p>
</li>
<li><p>Since this was the first time I used this service, IFTTT asked me to authorize the integration with my <strong>TP-Link Kasa</strong> account. I just keyed in my Kasa account credentials and it’s good to go.</p>
<p> ![]https://cdn.hashnode.com/res/hashnode/image/upload/v1630176555887/LgLxGeDWj.png)</p>
</li>
<li><p>Once the integration has been authorized, I was now able to select which device will be turned on by this applet.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176557454/8P4-om0nc.png" alt /></p>
</li>
<li><p>This is how my applet looks like at this stage.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176559729/_R14zEOqK.png" alt /></p>
</li>
<li><p>I clicked <strong>Continue</strong> then specified the Applet title. After which, I clicked on <strong>Finish</strong>.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176561531/HDZB-saqF.png" alt /></p>
</li>
</ol>
<p>That’s it! I now have an applet that can be triggered to turn my smart light bulb on. I also created an applet to turn off the light bulb by just repeating the above steps. Only difference is I changed the Webhook event name and the TP-Link Kasa action accordingly. If you’re an IFTTT Pro user, then you can further condense all of these into a single applet using the more advanced features available to you.</p>
<p>Now, we’re ready for the steps on the iOS Shortcuts side. Not yet. There’s still one last step left to complete the configuration on the IFTTT side — to identify the Webhook URL for this applet. This URL will be used by iOS Shortcut to trigger this IFTTT applet. More on that later.</p>
<p>Here’s how I identified the Webhook URL:</p>
<ol>
<li><p>On my IFTTT dashboard, I clicked on <strong>Explore</strong>.</p>
</li>
<li><p>I searched for the <strong>Webhooks</strong> service then clicked on the <strong>Documentation</strong> button.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176563490/p6juegj6p.png" alt /></p>
</li>
<li><p>I was brought to the documentation page where my API key was indicated. Additionally, the URL to trigger my webhook events is also indicated here.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176565049/yUrNS1Kom.jpeg" alt /></p>
</li>
<li><p>I replaced the <strong>{event}</strong> part of the URL to match the event names I specified when I created the on and off applets.</p>
</li>
</ol>
<p>Now that I had the Webhook URLs (one for each event), I set it aside first and went on to configure the iOS shortcuts on my phone.</p>
<h2 id="ios-shortcuts">iOS Shortcuts</h2>
<p>At this point, I now need to configure iOS to integrate with the IFTTT applets I created earlier. More specifically, I need iOS to be able to trigger the Webhook events I defined. It’s quite simple. I literally created 2 shortcuts that each calls the 2 Webhook URLs I set aside earlier.</p>
<p>I defined the shortcuts by doing these steps:</p>
<ol>
<li><p>I created 2 new iOS Shortcuts</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176566611/McP0k565K.png" alt /></p>
</li>
<li><p>I added the <strong>URL </strong>action and defined it to contain the Webhook URL set aside earlier. One defined with the Webhook URL for the “turn on” applet and the other with the Webhook URL for the “turn off” applet.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176568437/RVLd3oQTD.png" alt /></p>
</li>
<li><p>I then added the <strong>Get Contents of URL</strong> action. By default, this will automatically use the <strong>URL</strong> defined in Step 2.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176570429/T4hni69F8.png" alt /></p>
</li>
<li><p>I clicked on the <strong>Next</strong> button at the top right and then specified the name for the shortcuts.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176572162/LYuvyOilV.png" alt /></p>
</li>
<li><p>At the end, I had the ff. shortcuts created:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176573960/xIOykn0aM.png" alt /></p>
</li>
</ol>
<h2 id="testing-it-out">Testing It Out</h2>
<p>Now that I had the iOS shortcuts and IFTTT applets set up, I can just go and activate any of the turn on/off shortcuts by simply talking to Siri. In my case, my shortcuts are named “Turn Bedroom Light On” and “Turn Bedroom Light Off” respectively. I can just say “Hey Siri, please turn the bedroom light on.” and Siri will automatically identify the correct shortcut to activate.</p>
<p>Now, even if my Google Home can’t hear me, I can still control my bedroom light hands-free just by using my phone!</p>
]]></content:encoded></item><item><title><![CDATA[“What do I want to do?” — Ask this the next time you want to organize your apps]]></title><description><![CDATA[“What do I want to do?” — Ask this the next time you want to organize your apps
Up until recently, my mobile apps have been grouped by categories but I realized that some of these apps do not technically fall under one category. Eventually, I had a d...]]></description><link>https://blog.projectkenneth.com/what-do-i-want-to-do-ask-this-the-next-time-you-want-to-organize-your-apps-cae6087bbcb4</link><guid isPermaLink="true">https://blog.projectkenneth.com/what-do-i-want-to-do-ask-this-the-next-time-you-want-to-organize-your-apps-cae6087bbcb4</guid><category><![CDATA[iphone]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Sun, 11 Jul 2021 04:07:56 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630176836146/q_pNbhQLy.png" alt="My beautiful screenshot" /></p>
<p>“What do I want to do?” — Ask this the next time you want to organize your apps</p>
<p>Up until recently, my mobile apps have been grouped by categories but I realized that some of these apps do not technically fall under one category. Eventually, I had a difficulty fitting in some of these applications to the “correct” category.</p>
<h3 id="blurred-lines-blurred-purposes">Blurred Lines, Blurred Purposes</h3>
<p>Let’s take a look at lifestyle or mall membership apps. In the simplest sense, these apps should fall under the “Shopping” category which is also the category for online shopping apps like Amazon. In today’s world where online shopping is the go-to combined with the fact that some users love earning points (totally not referring to myself), this “Shopping” category can eventually get crowded making it difficult to navigate.</p>
<p>This is when it hit me. I realized that this experience needs to be improved! I’ve given it several tries. I tried moving the points-earning apps to a “Lifestyle” category which clearly separated them from the “just-for-shopping” apps. But then came the video and audio apps. On the audio side, I’ve used Audible to study while Spotify to, well, listen to music. On the video side, should Udemy, LinkedIn Learning and Netflix be really under one folder? I don’t think that I use these apps in the same way.</p>
<h3 id="asking-the-right-question">Asking The Right Question</h3>
<p>This is when I realized that I’ve been looking at this problem the wrong way. I’ve been trying to group my apps by asking “What type of app is this?” instead of asking a more relevant question: “What do I want to do with this app?”.</p>
<p>So, I started asking this question for each app. Eventually, I came up with the groupings as seen on my screenshot. Udemy and LinkedIn Learning goes to the “Learn” group while Netflix goes to the “Watch” group. The original “Shopping” group was renamed to “Buy” and the points-earning group to “Earn Points”. Fun fact, the “Authenticate” group was previously named “Security” and honestly, I didn’t really think that was a good group name at all.</p>
<h3 id="what-do-i-want-to-do-i-want-to-close-this-article">What do I want to do? I want to close this article.</h3>
<p>This grouping style gave me a way to better navigate my apps. When I open my phone, I just ask myself “What do I want to do?” and immediately find the group and app I need to use.</p>
<p>Additionally, I don’t need to have several conflicting thoughts on where I need to put my next app download is. Even if this new app was developed with the intention of allowing users to buy and earn points at the same time, I can just place it in the group that’s more relevant to how I’m going to use this new app.</p>
<p>Do you have other tips on how we can better organize our mobile apps? Share them with me in the responses!</p>
]]></content:encoded></item><item><title><![CDATA[Technical interview on algorithms: Where should I begin?]]></title><description><![CDATA[Picture this. You're in your 3rd job and your career has progressed a lot. In a software developer's life, that would mean you've learned lots of different technologies and gained lots of experiences working with various platforms. This might also me...]]></description><link>https://blog.projectkenneth.com/technical-interview-on-algorithms-where-should-i-begin</link><guid isPermaLink="true">https://blog.projectkenneth.com/technical-interview-on-algorithms-where-should-i-begin</guid><category><![CDATA[Technical interview]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[Regex]]></category><category><![CDATA[sorting]]></category><category><![CDATA[interview]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Fri, 04 Dec 2020 16:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630170481728/KasKkdw5N.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Picture this. You're in your 3rd job and your career has progressed a lot. In a software developer's life, that would mean you've learned lots of different technologies and gained lots of experiences working with various platforms. This might also mean you've gained non-technical experiences like leading teams or client interaction.</p>
<p>Then one day you wake up and decide that it's time to move on. It's time to go and look for a new job. You submitted your resume to several companies and scoured LinkedIn for interesting job postings. Eventually you got some favorable responses and after a few emails, you're now in line for a couple of interviews.</p>
<p>Depending on the role you're applying for, the questions will primarily be focused on your target role and technology which is most likely closely related to your latest experience. But as developers, we all know that there a category of questions that will almost always be asked regardless of the role you're applying for  — <em>algorithms</em>.</p>
<h2 id="dont-lose-them-let-them-linger-at-the-back-of-your-minds">Don't lose them. Let them linger at the back of your minds.</h2>
<p>Let's face it, with all the development worked you've done for the past years, did you really have the time to actually implement and use your own sorting algorithm for a live project? Let's say that once in a while you had to implement your own custom sorting algorithm for very special circumstances. How many times did you actually have to do that?</p>
<p>I'm not saying these concepts are useless. What I'm trying to say is that with years of experience and years of translating high-level business requirements into code, there is a high chance that developers get out of touch with these core concepts.</p>
<p>But in reality, as developers, we should always keep these concepts very close to us. In fact, based on my own experience, I often apply these concepts in my daily work. I just don't realize that I'm doing so.</p>
<p>This is why technical interviewers want to ask you about them. They want to know if you're still able to explain the concepts. Ideally, interviewers shouldn't expect you to memorize names. They should be able to extract your understanding of some of these concepts. At least that's how I did it when I became a technical interviewer myself.</p>
<h2 id="but-there-are-lots-of-them">But there are lots of them!</h2>
<p>Let me reiterate. Interviewers just want to get a glimpse of your understanding of some of these concepts. As you can see, I'm not using the word "all" here. No one should expect something like that from you.</p>
<p>Honestly, if your interviewer seems like he knows all the algorithms in the world, there are 2 possibilities to it. First is either he really practices using all of them in his daily routine (good for him!). Second is he's been doing interviews for quite a while, so he regularly brushes up on them.</p>
<p>Either way, regardless of wherever your interviewer falls in the above two possibilities, their whole strategy will most likely revolve around this: "How comfortable is this candidate when it comes to explaining or discussing algorithms?"</p>
<p>My suggestion is for you to ensure that prior to going to these types of interviews, you brush up on your algorithm knowledge. Pick a few that you can have a comprehensive understanding of. Then, do a high-level review of a couple more.</p>
<h2 id="which-ones-should-i-select">Which ones should I select?</h2>
<p>This next part is based on my experience as an interviewee and of course, as an interviewer. I'll share with you how I choose which algorithms I usually review before going for an interview.</p>
<p>Technical interviewers may ask you to write pseudocode, or even use a specific algorithm to solve a problem on the spot. Based on my experience, the test for algorithm knowledge usually revolves around the ff. categories: Sorting, Path Finding and Text Parsing.</p>
<h3 id="sorting">Sorting</h3>
<p>I always have  <a target="_blank" href="https://medium.com/human-in-a-machine-world/quicksort-the-best-sorting-algorithm-6ab461b5a9d0#:~:text=The%20time%20complexity%20of%20Quicksort,the%20%E2%80%9Cfastest%E2%80%9D%20sorting%20algorithm.">Quick Sort</a>  ready. Regardless of your choice, the idea is to have a sorting algorithm ready when tackling technical interviews. Sorting-related technical problems are always around the corner. Honestly, with all the out-of-the-box sorting functions we use in our daily lives, studying algorithms under this category is very, very vital. You don't want to be known as "that candidate who just uses functions without understanding how they work".</p>
<h3 id="path-finding">Path Finding</h3>
<p>There are lots of algorithms for path finding out there. I personally review BFS, DFS and  <a target="_blank" href="https://briangrinstead.com/blog/astar-search-algorithm-in-javascript/">A*</a>  before any interviews. For BFS and DFS, note that it will be better if you're able to implement them in either a recursive or iterative approach. In other algorithms (like A*), there's a concept of a heuristic. For these, make sure you understand how to identify the correct heuristic for a given problem.</p>
<h3 id="text-parsing">Text Parsing</h3>
<p>This can include manipulating strings or implementing your own Regular Expression engine. I personally believe this category is the trickiest among the 3. In fact, with text parsing, you're often required to mix and match other algorithms in your solution.</p>
<h2 id="finally-practice">Finally, practice!</h2>
<p>Let me emphasize one thing. Whatever set of algorithms you pick, always practice! It is very important to know the ins and outs of each algorithm. In some cases, you may even be asked to combine or expand existing algorithms to solve particular problems. Other interviewers may even ask you to compare the pros and cons for different algorithms.</p>
<p>Additionally, you can primarily focus on the algorithms you pick based on the categories I mentioned above; but, also ensure that you get a chance to have a high-level understanding of other algorithms as well.
Remember, it's your understanding that's being tested and not your memorization skills. It doesn't matter if you can write the pseudocode perfectly. If you're not able to explain it, then that's not going to reflect well for you.</p>
<p>Lastly, if you're asked about an algorithm you don't know anything about. Don't lie. Don't make up an algorithm just based on the name. In this situations, it's better to be honest. Interviewers are trained to dig deeper especially on answers they feel are untrue. The more they dig up, the more you get in trouble. Just say you don't know that specific algorithm. More often than not, your interviewer will ask you about another algorithm or let you pick which one you want to discuss.</p>
<p>Anyway, here's to hoping for a successful next technical interview for you! Cheers!</p>
<p><em>Cover photo from  <a target="_blank" href="https://unsplash.com/@linkedinsalesnavigator">LinkedIn Sales Solutions</a>  on  <a target="_blank" href="https://unsplash.com/photos/nPy0X4xew60">Unsplash</a></em></p>
]]></content:encoded></item><item><title><![CDATA[OutSystems: Let's talk about a naming convention]]></title><description><![CDATA[So, quick introduction first. OutSystems. Low-code. Done!
Very quick indeed right? Well, introducing OutSystems is not the goal of this article but rather, I want to touch on one aspect in using it that I think can still be improved — naming conventi...]]></description><link>https://blog.projectkenneth.com/outsystems-lets-talk-about-a-naming-convention</link><guid isPermaLink="true">https://blog.projectkenneth.com/outsystems-lets-talk-about-a-naming-convention</guid><category><![CDATA[naming]]></category><category><![CDATA[code review]]></category><dc:creator><![CDATA[Kenneth Angelo Reyes]]></dc:creator><pubDate>Sat, 28 Nov 2020 17:25:04 GMT</pubDate><content:encoded><![CDATA[<p>So, quick introduction first. OutSystems. Low-code. Done!</p>
<p>Very quick indeed right? Well, introducing OutSystems is not the goal of this article but rather, I want to touch on one aspect in using it that I think can still be improved — naming conventions.</p>
<p>Well, OutSystems already has their recommended naming conventions listed  <a target="_blank" href="https://success.outsystems.com/Documentation/Best_Practices/Development/OutSystems_Platform_Best_Practices#Naming_conventions">here</a> . One thing I believe is lacking in this are the conventions related to variable names. In fact, based on my experience in the past few years developing in OutSystems, I found that having naming conventions for variable names will be beneficial. This is why I came up with my own version which I'll be sharing with you in a bit.</p>
<h2 id="text-can-be-visual-cues-too">Text can be visual cues too</h2>
<p>Before we delve on my proposed naming convention, let me answer a question that most people will probably be asking right about now: Why?!
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630168465463/w5ik58GAF.png" alt="A sample action containing 2 input parameters, 1 output variable and 1 local variable" /></p>
<p>In the action shown above, we have 4 variables. Two inputs, one local, and one output. They can easily be identified by looking at the variables' respective icons. But, when you start using them in the action itself, these visual cues don't really show up. At the very least, you'd have to cross-check it every time against the logic tree.</p>
<p>This is the kind of experience I wanted to avoid. That's why I started thinking of defining my very own naming convention. I wanted everyone in our team to be able to understand the context of a variable just be looking at its name.</p>
<h2 id="or-is-it-just-a-prefix-convention">Or is it just a prefix convention?</h2>
<p>So, with that out of the way, I present to you my very own naming convention for OutSystems!</p>
<p>Actually, it's not really a full-blown naming convention. My proposal here is more on adding prefixes to variable names so their context can easily be understood.</p>
<p>Here's the different prefixes I used for action variables:</p>
<ol>
<li>Input parameters —  prefix with "In_"</li>
<li>Output parameters — prefix with "Out_"</li>
<li>Local variables — prefix with "Local_"</li>
</ol>
<p>So in the above example, the action will look like this when this convention is used:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630168606360/kfLRUCq0I.png" alt="A sample action containing 2 input parameters, 1 output variable and 1 local variable - this time using the prefixes proposed" /></p>
<p>I started off with the above. Then, I realized we that can still expand this convention to cover screen action names as well.</p>
<ol>
<li>Normal actions triggered by page interaction — prefix with "Action_"</li>
<li>Event handlers for web blocks — prefix with "Event_"</li>
</ol>
<p>Here's how it looks like for a sample screen:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630168643985/F1T75cRN8.png" alt="Sample screen following the proposed action name prefixes" /></p>
<p>Basically, that's it. For anything after the prefix, I still follow the base naming convention defined by OutSystems. So for a button click action, instead of "SubmitOnClick", I'll name it as "Action_SubmitOnClick".</p>
<p>As another benefit, the prefixes will also help you in sorting screen actions making it easier for developers to locate them in the tree.</p>
<h2 id="lets-close-this">Let's close this</h2>
<p>I understand that with this convention, there's more typing involved. But in my opinion, I'd rather sacrifice typing a bit more characters to ensure an even understanding in the team in terms of code we write — or in this case, code we don't write (Low code right?).</p>
<p>To anyone who has reached this point in this article, you may or may not use this convention. In fact, you may or may not like it. But if you do feel that it's something that you can use or improve on, then great! But if you have any reservations or concerns, just feel free to leave your comments below. Hoping to hear from you!</p>
]]></content:encoded></item></channel></rss>