<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sabbir Siddiqui</title>
    <description>The latest articles on DEV Community by Sabbir Siddiqui (@siddiqus).</description>
    <link>https://dev.to/siddiqus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F190350%2Fbb48ff05-9f53-429f-a386-bc348dc8ef5d.jpeg</url>
      <title>DEV Community: Sabbir Siddiqui</title>
      <link>https://dev.to/siddiqus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/siddiqus"/>
    <language>en</language>
    <item>
      <title>Which for-loop is the fastest in JavaScript?</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Sun, 25 Dec 2022 09:35:46 +0000</pubDate>
      <link>https://dev.to/siddiqus/which-for-loop-is-the-fastest-in-javascript-4hdf</link>
      <guid>https://dev.to/siddiqus/which-for-loop-is-the-fastest-in-javascript-4hdf</guid>
      <description>&lt;p&gt;I was curious to see how fast loops perform in JS after seeing a similar post for C#, so I wrote a quick script to check. &lt;/p&gt;

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

&lt;p&gt;For this test, I tried four different for-loop syntaxes, where each loop was simply incrementing a counter variable 10^8 times, and each loop ran five times to get an average time. Here are the results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for-of: 1616.2 milliseconds&lt;/li&gt;
&lt;li&gt;forEach: 1488.6 milliseconds&lt;/li&gt;
&lt;li&gt;for loop (with index): 282.4 milliseconds&lt;/li&gt;
&lt;li&gt;for loop (with cached array length): 278.8 milliseconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interestingly, for very small arrays (&amp;lt; 10^3 elements) it does not really make a difference. However, for 10^3 to 10^6 size, the result is a bit surprising.&lt;/p&gt;

&lt;p&gt;Results for 1000 iterations:&lt;/p&gt;

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

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forOf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forLoop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forEach&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forLoopCached&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Results for 100,000 iterations:&lt;/p&gt;

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

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forOf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forLoop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forEach&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forLoopCached&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;So when it comes to &amp;lt;10^6 arrays, the classic &lt;code&gt;forEach&lt;/code&gt; seems to be just fine.&lt;/p&gt;

&lt;p&gt;I personally used to use the for-of (slowest) syntax because it seemed like the easiest one, well now we know which one I'm going to start using!&lt;/p&gt;

&lt;p&gt;Here is the script: &lt;a href="https://github.com/siddiqus/useful-scripts/blob/master/for-loop-benchmark.js" rel="noopener noreferrer"&gt;https://github.com/siddiqus/useful-scripts/blob/master/for-loop-benchmark.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;P.S. Happy Holidays everyone!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>node</category>
      <category>loop</category>
    </item>
    <item>
      <title>20 Common NodeJS tools / packages for your backend production app</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Thu, 08 Dec 2022 11:23:28 +0000</pubDate>
      <link>https://dev.to/siddiqus/20-common-nodejs-tools-packages-for-your-backend-production-app-14p9</link>
      <guid>https://dev.to/siddiqus/20-common-nodejs-tools-packages-for-your-backend-production-app-14p9</guid>
      <description>&lt;p&gt;Let's cut to the chase, if you're planning on building a production level backend NodeJS application, chances are you'll need all or most of these packages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Express or NestJS for backend API framework&lt;/li&gt;
&lt;li&gt; Node-convict and dotenv for configuration management&lt;/li&gt;
&lt;li&gt; Joi for API request validations or data validations&lt;/li&gt;
&lt;li&gt; Sequelize ORM for MySQL/Postgres databases, or Mongoose for MongoDb&lt;/li&gt;
&lt;li&gt; RabbitMQ for publishing/subscribing to message queues, or Kafka for streams and message brokers&lt;/li&gt;
&lt;li&gt; Ioredis / node-redis for caching with Redis&lt;/li&gt;
&lt;li&gt; Axios for handling third party API integrations. Need a good command of json API calls and response handling&lt;/li&gt;
&lt;li&gt; Bull queue or Faktory for delayed/background jobs&lt;/li&gt;
&lt;li&gt; Socket.io for real time peer to peer connections&lt;/li&gt;
&lt;li&gt;Jest/Supertest for unit testing or integration testing and coverage reports&lt;/li&gt;
&lt;li&gt;Winston / Morgan for logging (use morgan-body if you want to log request / response, useful for debugging in staging and dev environments)&lt;/li&gt;
&lt;li&gt;Passport.js for authentication, or any custom authentication service using cookie-parser, jsonwebtoken or oath&lt;/li&gt;
&lt;li&gt;Node-cron for cron jobs&lt;/li&gt;
&lt;li&gt;Multer for handling file uploads&lt;/li&gt;
&lt;li&gt;Swagger for OpenAPI documentation (swagger-ui-express or &lt;a class="mentioned-user" href="https://dev.to/nest"&gt;@nest&lt;/a&gt;/swagger)&lt;/li&gt;
&lt;li&gt;Lodash for utilities&lt;/li&gt;
&lt;li&gt;Luxon for date time manipulation, especially when dealing with timezones&lt;/li&gt;
&lt;li&gt;ESLint + TSLint + Prettier for static code analysis and formatting&lt;/li&gt;
&lt;li&gt;Husky for Git hooks&lt;/li&gt;
&lt;li&gt;Docker for containerisation (Not NodeJS specific, but it helps)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Feel free to comment anything that you also work with on a daily basis!&lt;/p&gt;

&lt;h1&gt;
  
  
  softwareengineering #nodejs #typescript #javascript #softwaredevelopment #bestpractices #npm #npmtools #nodetools
&lt;/h1&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Sequelite - a lean TypeScript ORM for NodeJS</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Thu, 08 Dec 2022 11:20:10 +0000</pubDate>
      <link>https://dev.to/siddiqus/sequelite-a-lean-typescript-orm-for-nodejs-52k2</link>
      <guid>https://dev.to/siddiqus/sequelite-a-lean-typescript-orm-for-nodejs-52k2</guid>
      <description>&lt;p&gt;I have worked with NodeJS + Sequelize for more than 6 years now, and I can conclude two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sequelize is awesome!&lt;/li&gt;
&lt;li&gt;Model abstraction in a complex system has diminishing returns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The more complex our systems got, the more we tended to go towards a convention of&lt;/p&gt;

&lt;h2&gt;
  
  
  &amp;gt; Basic CRUD with ORM Models, complex stuff with raw queries
&lt;/h2&gt;

&lt;p&gt;So, with that convention and my cumulative experience, I released yet another ORM for NodeJS - &lt;code&gt;Sequelite&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Yes, the name is a little on the nose.&lt;/p&gt;

&lt;p&gt;Just released v1.0.0 of my own #opensource ORM in NodeJS! Link is in the comments.&lt;/p&gt;

&lt;p&gt;Sequelite is a lightweight ORM built on top of Sequelize with proper Typescript support, no annotations, no heavy model classes, and easy setup.&lt;/p&gt;

&lt;p&gt;The main motivations behind creating this package were having&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An easy setup&lt;/li&gt;
&lt;li&gt;Full type support for CRUD operations based on a declared TS interface&lt;/li&gt;
&lt;li&gt;Common raw queries wrapped around Sequelize and exposing them as generic functions, e.g. bulkUpdate, etc.&lt;/li&gt;
&lt;li&gt;Flexible configuration and DB connection through Sequelize&lt;/li&gt;
&lt;li&gt;Out of the box support for MySQL and Postgres, but segregated by separate base models considering their query differences&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Working with Sequelize in the last few years on several projects, I found the model definitions and setup boilerplate to be a bit clunky, although that is the price to pay for an otherwise awesome ORM.&lt;/p&gt;

&lt;p&gt;This project will give you the ability to do basic CRUD queries with full type support, which is convenient. However, in more complex systems and queries, I found raw queries are superior to any ORM wrapper interface since it gives you full control of what you are actually querying, so the client also exposes interfaces for raw select queries.&lt;/p&gt;

&lt;p&gt;Already thinking of some improvements, like&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;declaring an identity column (or columns) within a model class, so internally it will know which ID to use for upsert, or for index related queries.&lt;/li&gt;
&lt;li&gt;strengthening the where clause interface&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Checkout the github source here - &lt;a href="https://github.com/siddiqus/sequelite" rel="noopener noreferrer"&gt;https://github.com/siddiqus/sequelite&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npm - &lt;a href="https://www.npmjs.com/package/@siddiqus/sequelite" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@siddiqus/sequelite&lt;/a&gt;&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>What sets candidates apart?</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Sun, 03 Jul 2022 18:32:41 +0000</pubDate>
      <link>https://dev.to/siddiqus/what-sets-candidates-apart-19i2</link>
      <guid>https://dev.to/siddiqus/what-sets-candidates-apart-19i2</guid>
      <description>&lt;p&gt;"What sets a candidate apart?" - this is a question I often get from junior engineers who are going through interviews and recruiting process.&lt;/p&gt;

&lt;p&gt;Is it Leetcode solving? StackOverflow points or GitHub stars? Those may be some kind of indicator, but beyond the technologies, here are my other key criteria when comes to assessing a candidate&lt;/p&gt;

&lt;p&gt;👉 problem solving thought process - I don't mean solving Leetcode problems, I mean how the candidate approaches practical ones related to a product or existing system&lt;/p&gt;

&lt;p&gt;👉 humility vs arrogance - how they react to negative feedback or criticism, and how they portray their own knowledge and experience&lt;/p&gt;

&lt;p&gt;👉 big picture thinking - do they think of edge cases, external impact, do they ask meaningful follow up questions&lt;/p&gt;

&lt;p&gt;👉 curiosity vs apathy - do they try to understand the reasons behind why they do the things they do, or why certain practices or patterns are in place, or do they just go through the motions without asking questions&lt;/p&gt;

&lt;p&gt;👉 improvement mindset - whether they think about how to better themselves, their code, and their knowledge&lt;/p&gt;

&lt;p&gt;👉 clarity of communication - how clearly they can explain concepts, how well they can explain their own thought process&lt;/p&gt;

&lt;p&gt;👉 collaborative nature - when I give problems I try to phrase it as something we are trying to solve together, not me against them. how they generally react to those situations, and handle back and forth's.&lt;/p&gt;

&lt;p&gt;These can be a huge boost for the candidate's profile and can complement their tech skills, or even overcome shortcomings thereof.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>softwareengineering</category>
      <category>hiring</category>
      <category>career</category>
    </item>
    <item>
      <title>How to deal with Technical Debt</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Sat, 02 Jul 2022 17:36:04 +0000</pubDate>
      <link>https://dev.to/siddiqus/how-to-deal-with-technical-debt-4ckn</link>
      <guid>https://dev.to/siddiqus/how-to-deal-with-technical-debt-4ckn</guid>
      <description>&lt;p&gt;As per Wikipedia,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In software development, technical debt (also known as design debt[1] or code debt) is the implied cost of additional rework caused by choosing an easy (limited) solution now instead of using a better approach that would take longer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As per my opinion and / or experience, there are two kinds of technical debt - intentional and unintentional ones.&lt;/p&gt;

&lt;p&gt;The unintentional ones stem from technical decisions that may not take the big picture in mind, where the engineer is unaware of the debt they are creating for the future. These can happen due to lack of context, lack of experience, or lack of proper impact analysis, or you know just plain human error (we are all human). Processes like pair programming, diligent PR reviews, or allocating more time on task design may be a way to mitigate these kind of issues.&lt;/p&gt;

&lt;p&gt;The intentional ones are from deliberate engineering decisions. A team or someone decided to implement something they knew they would need to fix or refactor in the future, but decided to go ahead with it anyway due to time / deadline / business constraints. Meaning, if there is a debt, it's there for a reason, and has been put on the back-burner along with the others.&lt;/p&gt;

&lt;p&gt;No system is perfect, and in any growing product / software, especially startups, the latter tends to happen for shorter time-to-market. "For now we will do X to solve the problem, but in the future we should do it Y to make it more generic and scalable".&lt;/p&gt;

&lt;p&gt;Now, how to manage this debt? Like any other debt, tech debt can and should be paid in instalments. It's important for tech leads and engineering managers to be aware of tech debt, have a prioritized backlog of the same, and try to incrementally get rid of the debt over time by introducing reworks / refactors / implementations within the Sprint or regular development process as a part of normal tasks. The prioritization would happen based on a combination of business need vs which is more likely to degrade system health in the near future.&lt;/p&gt;

&lt;p&gt;It is also the responsibility of technical leadership to collaborate with and persuade product managers / business teams on considering the additional time towards tech debt before delivering a requested feature.&lt;/p&gt;

&lt;p&gt;For example, let's say there are some new requirements regarding SMS notifications, and the current notification system needs an overhaul. A plea to product managers would be "I know we are trying to achieve ABC with this feature to facilitate growth, however we need some time to refactor our notification system. This will allow us to implement any new notification requirements easily, plus make the notification system more scalable. If we don't do this now, with the growing number of notifications, it will degrade our performance by X hence affecting growth."&lt;/p&gt;

&lt;p&gt;At the end of the day, both tech and business parties should work together, and be aware of the importance of technical debt, how it can affect the current system, and hence the current business. The idea is we are all working together towards a common goal.&lt;/p&gt;

</description>
      <category>technicaldebt</category>
      <category>softwareengineering</category>
      <category>productmanagement</category>
    </item>
    <item>
      <title>Git Rebase got you conflicted? Here's what you can do.</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Tue, 28 Jun 2022 18:49:52 +0000</pubDate>
      <link>https://dev.to/siddiqus/git-rebase-got-you-conflicted-heres-what-you-can-do-38pj</link>
      <guid>https://dev.to/siddiqus/git-rebase-got-you-conflicted-heres-what-you-can-do-38pj</guid>
      <description>&lt;p&gt;Let's say you're working with feature branches. I know Trunk based development is the way to go, but hear me out. If your team is using git flow, this will help you get out of a sticky situation.&lt;/p&gt;

&lt;p&gt;If two people are collaborating on the same feature branch, and one person rebases the branch with main/master and pushes to origin, then the other person will face a load of conflicts when pulling the branch from origin (because of the new rebased commits). Here's how you can refresh your local branch completely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;𝐠𝐢𝐭 𝐟𝐞𝐭𝐜𝐡 𝐨𝐫𝐢𝐠𝐢𝐧 𝐭𝐡𝐞-𝐛𝐫𝐚𝐧𝐜𝐡 (fetch branch from origin)&lt;/li&gt;
&lt;li&gt;𝐠𝐢𝐭 𝐫𝐞𝐬𝐞𝐭 --𝐡𝐚𝐫𝐝 𝐨𝐫𝐢𝐠𝐢𝐧/𝐭𝐡𝐞-𝐛𝐫𝐚𝐧𝐜𝐡 (reset local branch and point to origin)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will update your local branch with the one in the remote. However, if you already made some changes in your own local branch and the other teammate has rebased it, here's what you can do&lt;/p&gt;

&lt;p&gt;Scenario A -&amp;gt; If you already committed the changes, in that case you can just do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;𝐠𝐢𝐭 𝐟𝐞𝐭𝐜𝐡 𝐨𝐫𝐢𝐠𝐢𝐧 𝐭𝐡𝐞-𝐛𝐫𝐚𝐧𝐜𝐡 (fetch remote branch)&lt;/li&gt;
&lt;li&gt;𝐠𝐢𝐭 𝐫𝐞𝐛𝐚𝐬𝐞 𝐨𝐫𝐢𝐠𝐢𝐧/𝐭𝐡𝐞-𝐛𝐫𝐚𝐧𝐜𝐡 (rebase your local with the remote)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Scenario B -&amp;gt; If you were just working on some changes but you did not commit them yet, you can simply&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;𝐠𝐢𝐭 𝐬𝐭𝐚𝐬𝐡 (To stash your local changes)&lt;/li&gt;
&lt;li&gt;follow the initial 2 steps to refresh the local branch&lt;/li&gt;
&lt;li&gt;𝐠𝐢𝐭 𝐬𝐭𝐚𝐬𝐡 𝐩𝐨𝐩 (to get your local changes back)&lt;/li&gt;
&lt;li&gt;continue your work!&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  gitflow #trunkbaseddevelopment #softwareengineering #softwaredevelopment #git #github #versioncontrol
&lt;/h1&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>versioncontrol</category>
    </item>
    <item>
      <title>How to better estimate your tasks</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Fri, 17 Jun 2022 18:14:18 +0000</pubDate>
      <link>https://dev.to/siddiqus/how-to-better-estimate-your-tasks-3e5c</link>
      <guid>https://dev.to/siddiqus/how-to-better-estimate-your-tasks-3e5c</guid>
      <description>&lt;p&gt;First of all, an estimate is just that - an estimate. Most of the time engineers struggle with estimation because of maybe some unforeseen side effects, or because of underestimating the task itself, or a plethora of other reasons.&lt;/p&gt;

&lt;p&gt;Secondly, as an engineer you have to keep in mind that your primary goal is not to estimate the task itself, but to get a clear idea of what you will be implementing. The more details you know about what you are going to implement, the better an idea you will have about how much time it might take. Here are some steps that will help you achieve that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Ensure a central list of requirements, e.g. acceptance criteria is in place. if you can identify any edge cases within the requirements immediately, add them to the list. Solid requirements will help you build a solid feature. It is also up to the engineer to analyse the requirements and add to them, because the product manager might not come up with all the various cases that need to be handled. This will also help QA and engineers devise the test cases for unit tests, manual tests and integration testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you have all your requirements in one place, start thinking about the data flow. What is the trigger point? What is the initial source of data? What kind of data will you need to store, and where (in db or cache)? How will the client eventually get access to this data? What kind of processing do you want to do to this data so that it meets the given requirements? Thinking about the data flow from start to finish, and writing down the steps will help you arrive at the overall design.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schema changes - now that you know what the data flow will be, you can use that to write down the schema level changes e.g DDL statements, any new or alter table commands, adding indexes, partitions, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API Design - from the data flow, and schema, you will get to know what APIs need to be implemented or updated. Think step by step what APIs you need to achieve your requirements. Are you creating new resources? updating existing ones? or fetching the new data to show somewhere?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration points - think about where will this new feature be integrated, whether your APIs will be consumed within the same module, or by another backend, or by a frontend UI. Think about the challenges the integrations might face, for example how will authentication/authorization work, does it need pagination, does your module need to be idempotent, what will happen if any external system makes concurrent requests with the same data, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Impact analysis - how will your change impact the rest of the system? Chances are you are changing an existing system (or extending it). What will be the side effects? Do you need to emit any events to let other modules know what you are doing? Will your changes break any other module flows? Here analysing the existing system is important to understand how your changes will fit in, and how you can ensure continuity to the existing flows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Task breakdown - Finally, now you should have a complete idea of what to do in order to implement this feature. If you did step 2 right, then this should be easier now. Using all of the analysis from above, start listing your todos / subtasks one by one in order in terms of what is needed to be done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally cross check your todos/subtasks to make sure all the acceptance criteria are being met. If you find any further edge cases like "x flow should not break", or "y system should be notified", add those to your acceptance criteria. By the end of this exercise, you will have a well-documented process for how to implement the feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that you will have a good idea about what needs to be done, and will have a granular level breakdown of the tasks/subtasks, you can ballpark each subtask (should each be within 1-4 hours), then add up the hours to get a final estimate. Don't forget to account some time for writing unit tests / integration tests, and then also some buffer for some unforeseen circumstances (it happens). By now you will have a more reasonable estimate of how long the whole thing should take.&lt;/p&gt;

&lt;p&gt;Key words are "more reasonable". However, a fair warning - you still might not be able to complete the task in the time you thought. It happens to everyone, welcome to software development :)&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>estimations</category>
      <category>taskbreakdown</category>
    </item>
    <item>
      <title>Git commands I find very useful and why</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Sat, 28 Aug 2021 04:51:11 +0000</pubDate>
      <link>https://dev.to/siddiqus/git-commands-i-find-very-useful-and-why-kl7</link>
      <guid>https://dev.to/siddiqus/git-commands-i-find-very-useful-and-why-kl7</guid>
      <description>&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;git checkout [some-branch] -- [some/file/path.ts]&lt;/code&gt;&lt;br&gt;
This will check out (and stage) that specific file from that specific branch into your local branch. This is great for working in teams where changes are being made in the same codebase in parallel. Suppose in another branch your teammate wrote a util that you can also use, or if you yourself want to get the latest version of a file to remove avoid unnecessary merge conflicts. An alternative to these scenarios is:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;git cherry-pick [commit-hash]&lt;/code&gt;&lt;br&gt;
Get code from a specific commit into your own branch. You can use the --no-commit flag to stage the changes before committing them to your branch (in which case the history/hash will be changed). Useful if you want to copy over an exact commit from another branch to your own. Again, useful working in teams. Also useful if you yourself committed changes to the wrong branch, and you want to bring those changes over to the proper branch. After which you want to do:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;git reset [--hard] HEAD~[n]&lt;/code&gt;&lt;br&gt;
Let's say you committed directly in master branch because you forgot to checkout of your own branch. Or you pulled into a local branch that was rebased in remote and now your history is all messed up. Lots of different scenarios, one easy fix. The --hard reset will get rid of all changes permanently, so use this with extreme caution. Not using the --hard option will just remove the commit. For merge commits n=1 will work, but once the commits pile on it might get more difficult to use. Nevertheless, very useful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;git commit --amend&lt;/code&gt;&lt;br&gt;
For when you want to make a small change to your previous commit but don't want to create a new commit. If you haven't pushed the branch then it works fine, if already pushed then you'll need to &lt;code&gt;--force&lt;/code&gt; it, since you're effectively rewriting history :)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>git</category>
      <category>versioncontrol</category>
      <category>github</category>
    </item>
    <item>
      <title>NodeJS + ESLint + Prettier - Simplest setup ever</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Mon, 23 Aug 2021 20:01:43 +0000</pubDate>
      <link>https://dev.to/siddiqus/nodejs-eslint-prettier-simplest-setup-ever-1p7j</link>
      <guid>https://dev.to/siddiqus/nodejs-eslint-prettier-simplest-setup-ever-1p7j</guid>
      <description>&lt;p&gt;Don't expect any fancy images in this post, let's get down to business. I'm just gonna hope you're using yarn because you should be.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;yarn add eslint --dev&lt;/code&gt; (from &lt;a href="https://eslint.org/docs/user-guide/getting-started"&gt;here&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;yarn run eslint --init&lt;/code&gt; (also from above link)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Follow whatever options your heart desires in the &lt;code&gt;eslint&lt;/code&gt; setup prompts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get rid of the &lt;code&gt;package-lock.json&lt;/code&gt; cause likely the &lt;code&gt;eslint&lt;/code&gt; cli used npm to install something. tsk. Remove that file, and just run &lt;code&gt;yarn&lt;/code&gt; to make things right again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;yarn add prettier eslint-config-prettier eslint-plugin-prettier @typescript-eslint/parser -D&lt;/code&gt; (from &lt;a href="https://sourcelevel.io/blog/how-to-setup-eslint-and-prettier-on-node#user-content-how-to-configure-prettier-with-eslint"&gt;here&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your repo should have an &lt;code&gt;.eslintrc.js&lt;/code&gt; file by now that looks like this:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;es2021&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest/globals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;airbnb-base&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eslint:recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prettier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@typescript-eslint/parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;parserOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ecmaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sourceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@typescript-eslint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prettier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;semi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;always&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;single&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import/extensions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ignorePackages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;never&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;never&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;never&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tsx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;never&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import/no-dynamic-require&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;global-require&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import/prefer-default-export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-underscore-dangle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-await-in-loop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-restricted-syntax&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-return-await&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-console&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prettier/prettier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;trailingComma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;es5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;singleQuote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;printWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tabWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;endOfLine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;arrowParens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;always&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;And an &lt;code&gt;.eslintignore&lt;/code&gt; that looks like this: (if not create one)
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add a command in your &lt;code&gt;package.json&lt;/code&gt; to run lint fixes
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lintfix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint src --fix --cache"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you want to use &lt;a href="https://www.npmjs.com/package/husky"&gt;husky&lt;/a&gt; for pre-commit hooks, be my guest. You can check the site for instructions but here they are anyway:
a. &lt;code&gt;yarn add husky --save-dev&lt;/code&gt;
b. &lt;code&gt;npx husky install&lt;/code&gt;
c. &lt;code&gt;npx husky add .husky/pre-commit "yarn eslint &amp;amp;&amp;amp; git add -A"&lt;/code&gt;
d. git add -A
e. git commit -m "finally configured eslint and prettier and husky without any 🐄 💩&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>eslint</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Writing fully testable React components using the 'Helper Pattern'</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Sat, 14 Dec 2019 06:34:40 +0000</pubDate>
      <link>https://dev.to/siddiqus/writing-fully-testable-react-components-using-the-helper-pattern-162l</link>
      <guid>https://dev.to/siddiqus/writing-fully-testable-react-components-using-the-helper-pattern-162l</guid>
      <description>&lt;p&gt;I am still learning about React Hooks and Redux (I know, I need to catch up quick), and I know writing basic React classes is pretty much dated at this point, but I wanted to share a little tidbit that I found to be useful over the years.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Consider a CRUD application for products, where a user can view a list of products (paginated), and create, modify, or delete a product. The component class would look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ProductsPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// state may include product list, product form variables, loadingStatus, etc.&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// some product service to manage products&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// some code to fetch data for list view&lt;/span&gt;

    &lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;_renderPageHeaderWithCreateButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;_renderProductTable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;_renderProductModal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;_renderLoadingModal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;_renderErrorAlert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fragment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_renderErrorAlert&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_renderPageHeaderWithCreateButton&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_renderProductTable&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_renderProductModal&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_renderLoadingModal&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/React.Fragment&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is usually how I like to organize my React classes. Apart from the usual functions for button clicks, I also like to split my render function into smaller chunks if it starts to get bigger, and then later decide to split this into separate components as needed. A user might see a simple list but there's a lot going on in this component. &lt;/p&gt;

&lt;p&gt;After mounting, the class needs to set a 'loading' state, and then fetch data from a server using the 'ProductService', and if the call is successful, set the data to a 'productList' state variable, or otherwise handle errors. Then if a user wants to create or modify a product, you have to manage the state for a modal along with form variables. All in all, we end up with a lot of state variables and button actions to manage.&lt;/p&gt;

&lt;p&gt;Apart from splitting this up into smaller components and having to pass down state and actions, could we make this one component less bulky and the state easier to manage? Also think about unit testing. Jest provides the tools to test React components, but do we really need those to test our logic? I tried using the Logic/View pattern before where there would be one React component for the view and one for managing all the logic e.g. 'ProductsPage' and 'ProductsPageView'. That seemed great at first, but the logic was still contained in a React component that didn't necessarily need to be. So I thought about flipping this pattern on it's head. Could I have a view class where I delegate managing all the logic to another class, but one that wasn't a React component? Yes I could! &lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: The Helper Pattern
&lt;/h2&gt;

&lt;p&gt;The idea was simple - each React component would have a Helper class that would manage all the logic for that component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ProductsPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ProductsPageHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pay attention&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// some state vars&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addProduct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ... other stuff&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you notice, the helper class is initialized with 'this'. Why would we do this? (pun intended) We would have access to all of the React component's props and state variables and can manage the logic from there. Take a look at the new 'onAddButtonClicked' method, where most of the logic is taken away in the helper. Here is an example of the helper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ProductsPageHelper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// our React component&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// this is now removed from the React class&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;addProduct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// some logic to add a product using the product service&lt;/span&gt;
        &lt;span class="c1"&gt;// returns new state e.g. new product list or errors&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ... other functions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Okay, great. We have some separation of logic from the React component, and most of the logic is now in a 'helper' class which is a regular Javascript class. Could we do better? The answer is yes! Why manage the state in two different places where you could manage the state in one? Finally after a few more iterations, this is what I came up with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ProductsPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productsPageHelper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ProductsPageHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productsPageHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// init state variables&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// state fully managed here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;onAddButtonClicked&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addProduct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// state fully managed here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;onDeleteButtonClicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// state fully managed here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;onUpdateButtonClicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// state fully managed here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ...render functions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I initialized the state from the helper method 'getInitialState', so the developer working on the helper class knows what state variables the component has without actually looking at the view component.&lt;/li&gt;
&lt;li&gt;All the state is now fully managed from the helper class&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You could reduce the React component code even further by getting rid of the event functions and the 'bind' code, by using the arrow function syntax in JSX. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// for a product list view&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Row&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* {some code for product row} */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;Delete&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Row&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is the helper class now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ProductsPageHelper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// our React component&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// this is now removed from the React class&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;_updateState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;getInitialState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;productList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;productFormVars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="na"&gt;productModalIsShown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;_handleGetProductsSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productList&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_updateState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;productList&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;_handleGetProductsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// some error handling&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_updateState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;some error message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_handleGetProductsSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_handleGetProductsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ... other functions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Woohoo! As you can see, the state can be accessed/managed just by using &lt;code&gt;this.component.state&lt;/code&gt; and &lt;code&gt;this.component.setState&lt;/code&gt;. Now since the helper is just any other Javascript class, we can easily get full test coverage on this. For example, to test the logic for 'componentDidMount':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ProductsPageHelperTest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should get products and set state properly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;helper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ProductsPageHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockProductList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockProductList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;productList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mockProductList&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can just pass a 'mockComponent' object with an initial state and the 'setState' stubbed function to fully test the state change behavior. Testing the React component also became easier since all the logic was driven by the Helper class, you could write tests by stubbing the helper methods and checking to see if those were called when appropriate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outcomes
&lt;/h2&gt;

&lt;p&gt;What was the benefit from doing all of this?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Leaner component classes - The previously bulky React classes were now much leaner and easier to go through at a glance.&lt;/li&gt;
&lt;li&gt;Code consistency - The pattern helped to make development easier for everyone on the team as all the components' states were managed in the same way, so team members knew what to expect.&lt;/li&gt;
&lt;li&gt;Improved productivity and collaboration - You could have multiple team members working in parallel on the same component where one person would work on the view while another person could work on the logic. A backend engineer with some Javascript experience could work on the helper class, as long as the methods / contracts were defined. This made the team more cross functional.&lt;/li&gt;
&lt;li&gt;Code coverage - Before using this pattern, team members avoided writing unit tests since using Enzyme was painful when it came to logic contained within the React components. Code coverage went from 30% to over 80% after using the Helper pattern, since now all of the logic could be tested.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now it's time to leave this behind and move forward into the world of Redux and Hooks! :)&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>testing</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>3 things about Infinity in JavaScript you probably already knew, but didn't know why</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Mon, 02 Dec 2019 12:50:01 +0000</pubDate>
      <link>https://dev.to/siddiqus/3-things-about-infinity-in-javascript-you-probably-already-knew-but-didn-t-know-why-3h8k</link>
      <guid>https://dev.to/siddiqus/3-things-about-infinity-in-javascript-you-probably-already-knew-but-didn-t-know-why-3h8k</guid>
      <description>&lt;h1&gt;
  
  
  1. The largest denominator
&lt;/h1&gt;

&lt;p&gt;If you run the standard &lt;code&gt;1/0&lt;/code&gt; in Javascript, this yields the Infinity type. But what about very small denominators? If you keep making the denominator smaller, the result will obviously keep getting bigger. But when will it reach Infinity?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.0000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Infinity
10
999999999999999.9
9.999999999999999e+42
1e+85
1.0000000000000001e+304
1e+305
1e+306
1.0000000000000001e+307
1e+308
Infinity
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So as we reach the 309th decimal place, we get Infinity. This might not be a novel revelation, because as we all may know (actually TIL) that &lt;em&gt;1.797693134862315E+308 is the limit of a floating point number&lt;/em&gt;. This is also a roundabout way of asking &lt;em&gt;When does a number turn into Infinity in Javascript?&lt;/em&gt;. As you would expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e306&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1e+306&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e307&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1e+307&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e308&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1e+308&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e309&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Infinity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  2. Parsing Infinity
&lt;/h1&gt;

&lt;p&gt;Sometimes we don't always get what we want when we parse stuff. Infinity at the least is no different. Observe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Infinity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Tada! Okay but the first line can be explained pretty easily. &lt;code&gt;parseInt&lt;/code&gt; is expecting a string type parameter, and if the argument cannot be converted into a ninteger, it returns &lt;code&gt;NaN&lt;/code&gt;. So this makes sense since &lt;code&gt;Infinity&lt;/code&gt; is not within Javascript's integer range.&lt;/p&gt;

&lt;p&gt;However, as we've seen in the previous point, Infinity is actually represented by the &lt;code&gt;float&lt;/code&gt; type in Javascript. Hence the &lt;code&gt;parseFloat&lt;/code&gt; result makes sense!&lt;/p&gt;

&lt;p&gt;Also, a bonus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; NaN&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; NaN...&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 18&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 18...&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 151176378&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 385849803&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 13693557269&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 28872273981&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 1201203301724&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; 1461559270678...&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Infinity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I got that from this &lt;a href="https://github.com/denysdovhan/wtfjs#parseint-is-a-bad-guy"&gt;fun repo&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Infinity is not a number, right?
&lt;/h1&gt;

&lt;p&gt;Okay so without getting too much into Number Theory (I'm not even bragging, I have no idea about Number Theory), let's see how Javascript deals with Infinity as a type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "number"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Okay, so it's a number. But is it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="kc"&gt;Infinity&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt; &lt;span class="c1"&gt;// Infinity&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="kc"&gt;Infinity&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wait, what? Okay speaking in Javascript terms, when you write &lt;code&gt;Infinity - Infinity&lt;/code&gt;, it is evaluated as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;Infinity&lt;/code&gt; and &lt;code&gt;-Infinity&lt;/code&gt; are different 'objects' in Javascript, this would yield a &lt;code&gt;NaN&lt;/code&gt;. So wait, it's not a number? or is it? I actually don't know this one.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>infinity</category>
    </item>
    <item>
      <title>Quest for a practical NodeJS API Framework</title>
      <dc:creator>Sabbir Siddiqui</dc:creator>
      <pubDate>Sun, 24 Nov 2019 09:04:18 +0000</pubDate>
      <link>https://dev.to/siddiqus/quest-for-a-practical-nodejs-api-framework-5a82</link>
      <guid>https://dev.to/siddiqus/quest-for-a-practical-nodejs-api-framework-5a82</guid>
      <description>&lt;p&gt;While working on REST APIs with &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express JS&lt;/a&gt; / Node, I came across some common challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I had to configure Express the same way every time using some common stuff - body parser, cors, validators etc.&lt;/li&gt;
&lt;li&gt;It's a free-for-all in terms of how you organize your code when it comes to Express, best practices in terms of coding and code organization had to be implemented manually every time.&lt;/li&gt;
&lt;li&gt;There is built in central error handling in Express, but it's not declarative, and you'd want a more elegant solution as well as have more control over errors on specific endpoints.&lt;/li&gt;
&lt;li&gt;Documenting APIs seemed like a chore since you needed to setup swagger, and maintain a separate swagger JSON file which is kind of removed from your actual code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FlF8PJ3j.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FlF8PJ3j.gif" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Working with Express for the last 3 years, I started thinking about how to use ES6 classes and OOP to implement REST controllers, about common patterns and ways I can modularize the APIs I develop. Each REST endpoint has a URL, an HTTP method, and a function it carries out. Any REST controller would be for handling requests for a given endpoint e.g. "/products", with different functions for handling the different HTTP methods. So I began my quest, and my first iteration of a would-be framework was to have a BaseController that each REST controller would extend. Here is a snippet of such a REST controller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Foelkmpu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Foelkmpu.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s say the ProductController manages actions regarding products of an e-commerce site. A productService is injected through the constructor, and a method is implemented for getting a single product based on its ID. &lt;/p&gt;

&lt;p&gt;Pay attention to two parts of the code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The API validation is done at the beginning of the method, where it returns out of the method if there are errors. This was done using &lt;a href="https://www.npmjs.com/package/express-validator" rel="noopener noreferrer"&gt;express-validator&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Whatever error is thrown inside the method is caught and sent to the next middleware using the "next" function, to avoid the general "internal server error" response.
We will need to remember these two points later in the article.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You may notice that the controller has a property “router”, which is actually an Express router, and the “route_” prefix convention is used to register any endpoint for that router, both of which are implemented code in the BaseController. So now if you wanted to have an API for products, you could do this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FuPDoBES.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FuPDoBES.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently I’ve been working on a project where we have several microservices using Java Spring Boot, and it was interesting to see Spring Boot has a similar convention as I derived here. Not to brag, but I mean it's common sense, right?&lt;/p&gt;

&lt;p&gt;Then I thought, what happens if you bring nested APIs into the mix? Let’s say each product has reviews associated with it, and we need a set of endpoints to go with that. How would we organize our code then? We would have a separate controller for reviews with their CRUD functions, but would the URI “/:id/reviews” be repeated for each one? Here’s what I wanted the ReviewController to look like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FVhC89Q9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FVhC89Q9.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This controller allows endpoints to create a review, get all reviews, and get a single review by ID. How would we define the paths for these endpoints? Then came the idea of “subroutes”, where I implemented a mechanism to define nested routes within a controller itself. Just like the “routes_” prefix convention, I added a ‘subroutes’ method in the BaseController which you would extend in your own controller and return an array of controllers to be registered in the Express router internally. Here is an example of how to use the 'subroutes' method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FiM9WmwN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FiM9WmwN.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s say I declare the “/products” path from where my main app is routed like before, and with this particular example what we have done is declare the following APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET /products&lt;/li&gt;
&lt;li&gt;POST /products/:id/review&lt;/li&gt;
&lt;li&gt;GET /products/:id/review&lt;/li&gt;
&lt;li&gt;GET /products/:id/review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay great, now there was a way to do nested APIs, and we could keep declaring controllers for root level routes or subroutes for nested paths, and the framework handled registering the paths. However, this became kind of a mess, or so I figured after taking a step back. Here is all that was wrong with the ‘framework’ so far (as far as I know):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The code was very verbose&lt;/li&gt;
&lt;li&gt;Different controller classes would be tied to each other&lt;/li&gt;
&lt;li&gt;You would have to pass around services to controllers that had no business with them specifically&lt;/li&gt;
&lt;li&gt;Remember how I mentioned the API validation and error handling? As I wrote out a few more APIs, I realized I would have to repeat those two lines in every single controller method. No can do.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This was a mess. It broke the Single Responsibility Principle, and probably a few others that don't want to think about anymore. It’s not the controller’s job to register other controllers is it? Is it the controller’s job to register any endpoints at all? Why should I write the same lines of code to validate APIs and catch errors every single time? I created a monster! Surely this could be done better, where some things are done centrally, and maybe we could just define the controllers and externally handle the routing somehow?&lt;/p&gt;

&lt;p&gt;I showed one of my colleagues what I had so far, and discussed ways to take out the subroutes feature and make that mechanism independent of any controller. That seemed doable, so then I ended up with independent controllers that can be configured into any route or subroute. “At this rate, you’ll be left with a single JSON file for defining this whole damn API” - my colleague joked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWXD99FH.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWXD99FH.gif" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was funny, but as I laughed I immediately thought, why not? If controllers are made up of independent endpoints, and subroutes are just a collection of those endpoints, could we rearrange the code to make all of this fully modular? Since the ‘subroutes’ is just an array of objects, and the individual HTTP routes can also be defined using objects (path, HTTP method, controller, etc.), aren’t we just looking at a big object that has a bunch of objects inside it, that kind of look like the big object itself?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FZSs2uPJ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FZSs2uPJ.gif" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My quest took a recursive turn to a recursive turn to a recursive turn to a…okay you get the point. I figured let’s just have a recursive object to define the routes and their functions. And henceforth, a few weeks of coding later, &lt;a href="https://www.npmjs.com/package/@siddiqus/expressive" rel="noopener noreferrer"&gt;Expressive&lt;/a&gt; was born!&lt;/p&gt;

&lt;p&gt;Expressive is meant to be flexible but opinionated, because sometimes it's good to have opinions about best practices. It's still Express JS under the covers, with the middleware flexibility, and now I had a modular way of defining every endpoint. This is what I ended up with:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FfHy24gl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FfHy24gl.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made an 'ExpressApp' class that takes the router and recursively registers the express endpoints with it's respective routes and functions. You will also notice that each endpoint has a 'validator' with it, and now since each 'controller' is it's own endpoint, the validation code is refactored into a single line internally to avoid repetition.&lt;/p&gt;

&lt;p&gt;That's all in one file, but you can see how you could put the "rootRouter" object in one file, the "productsRouter" in another file, and the "reviewRouter" in another, and define endpoints in a very declarative way. This way you could define your root level entities in your APIs in one router file, and the rest would follow. The code was still verbose, so a little refactoring and I came up with this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FAQtLknN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FAQtLknN.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There, that's much better! I introduced two new exports - 'Route' and 'subroute' for their respective definitions. Since I was just using objects with the same properties, I thought why not encapsulate them and make things easier to implement and more readable.&lt;/p&gt;

&lt;p&gt;Last but not least, API documentation was a concern. Now I figured since each endpoint itself is an independent object, and Swagger definitions are the same thing, why not add a 'doc' property where I can just put a Swagger JSON object? The next steps were naturally to integrate Swagger and Swagger UI (in development mode, but also configurable), where by default it would create the basic Swagger templates for each endpoint that you declare in your router endpoints using the path and method, and you could declare the full API documentation using the 'doc' property, like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FET7od1F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FET7od1F.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run the app, the docs are available on the "/docs" route by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Ftzw02PV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Ftzw02PV.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great success! Now we have an API framework with built in documentation! And you can see which routes are present right away, even if the docs aren't specifically declared!&lt;/p&gt;

&lt;p&gt;The ExpressApp class also takes a second object parameter for defining middleware and other options. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLCcVDnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLCcVDnz.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can generally configure your whole API with this class. I was happy with the framework so far because it solved my aforementioned problems. It had built-in middleware like &lt;a href="https://www.npmjs.com/package/body-parser" rel="noopener noreferrer"&gt;body-parser&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/cors" rel="noopener noreferrer"&gt;cors&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/express-validator" rel="noopener noreferrer"&gt;express-validator&lt;/a&gt;, etc. that's common for every REST API I want to build. I could specifically define a centralized error handling middleware function. I could define API endpoints in a declarative way that makes sense, while having a maintainable code structure. And I could document my code with ease.&lt;/p&gt;

&lt;p&gt;I recently came across this article that compares various NodeJS Rest API frameworks, and it was amusing to see the evolution of the frameworks from Express, and how it seems my own framework's endpoint declaration is similar to LoopBack's. We have been able to use my own framework at my current place of work in a few different projects and since it's built on top of Express which we had already done, integrating it with CI/CD was no challenge. I was happy to see my coworkers had fun while using the framework, and that I wasn't the only one that found the features useful. The journey has been fun and fulfilling, and I know I can use the Expressive framework for building REST APIs pretty confidently, but as usual I'm always learning new things, and trying to find ways to make this framework better. And so, my quest continues!&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Github: &lt;a href="https://github.com/siddiqus/expressive" rel="noopener noreferrer"&gt;https://github.com/siddiqus/expressive&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NPM: &lt;a href="https://www.npmjs.com/package/@siddiqus/expressive" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@siddiqus/expressive&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Inspiration article: &lt;a href="https://strongloop.com/strongblog/compare-express-restify-hapi-loopback/" rel="noopener noreferrer"&gt;https://strongloop.com/strongblog/compare-express-restify-hapi-loopback/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>express</category>
      <category>node</category>
      <category>restapis</category>
    </item>
  </channel>
</rss>
