<?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: Lucas Porfirio</title>
    <description>The latest articles on DEV Community by Lucas Porfirio (@lukeskw).</description>
    <link>https://dev.to/lukeskw</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%2F1091725%2F1313759b-5b6c-4f32-9ac4-9e7359b03481.png</url>
      <title>DEV Community: Lucas Porfirio</title>
      <link>https://dev.to/lukeskw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lukeskw"/>
    <language>en</language>
    <item>
      <title>SOLID Principles: They're Rock-Solid for Good Reason!</title>
      <dc:creator>Lucas Porfirio</dc:creator>
      <pubDate>Fri, 02 Feb 2024 17:22:31 +0000</pubDate>
      <link>https://dev.to/lukeskw/solid-principles-theyre-rock-solid-for-good-reason-31hn</link>
      <guid>https://dev.to/lukeskw/solid-principles-theyre-rock-solid-for-good-reason-31hn</guid>
      <description>&lt;p&gt;Just started with &lt;strong&gt;object-oriented programming&lt;/strong&gt; and feeling a bit lost about &lt;strong&gt;SOLID&lt;/strong&gt;? No worries, in this article, I'll explain it to you and provide examples of how to use it in your code development.&lt;/p&gt;

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

&lt;p&gt;In object-oriented programming, &lt;strong&gt;SOLID&lt;/strong&gt; is an acronym for five design principles aimed at enhancing the understanding, development, and maintenance of software.&lt;/p&gt;

&lt;p&gt;By applying this set of principles, you should notice a reduction in bugs, improved code quality, the production of more organized code, decreased coupling, enhanced refactoring, and encouragement of code reuse. Let's get to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. S - Single Responsibility Principle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv564d0p0s36fwo6imofo.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%2Fv564d0p0s36fwo6imofo.png" alt="SRP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SRP - Single Responsibility Principle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one is really simple, but super important: &lt;strong&gt;one class should have one, and only one, reason to change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No more creating classes with multiple functionalities and responsibilities, huh? You've probably encountered or even created a class that does a bit of everything, a so-called &lt;em&gt;God Class&lt;/em&gt;. It might seem fine at the moment, but when you need to make changes to the logic of that class, problems are sure to arise.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;God class: In OOP, this is a class that &lt;code&gt;do&lt;/code&gt; or &lt;code&gt;knows&lt;/code&gt; too much things.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProfileManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;authenticateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Authenticate logic&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;showUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Show user profile logic&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;updateUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Update user profile logic&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setUserPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set permission logic&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 &lt;strong&gt;ProfileManager&lt;/strong&gt; class is violating the SRP principle by performing &lt;strong&gt;FOUR&lt;/strong&gt; distinct tasks. It is validating and updating data, doing the presentation, and to top it off, it's setting the permissions, all at the same time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issues this can cause
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Lack of cohesion -&lt;/code&gt; a class shouldn't take on responsibilities that aren't its own;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Too much information in one place -&lt;/code&gt; your class will end up with many dependencies and difficulties for changes;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Challenges in implementing automated tests -&lt;/code&gt; it's hard to mock such a class.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, applying &lt;strong&gt;SRP&lt;/strong&gt; to the &lt;code&gt;ProfileManager&lt;/code&gt; class, let's see the improvement this principle can bring:&lt;/p&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;authenticateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Authenticate logic&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserProfileManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;showUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Show user profile logic&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;updateUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Update user profile logic&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PermissionManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setUserPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set permission logic&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;You might be wondering, &lt;code&gt;can I apply this only to classes?&lt;/code&gt; The answer is: &lt;strong&gt;NOT AT ALL&lt;/strong&gt;. You can (and should) apply it to methods and functions as well.&lt;/p&gt;

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

&lt;span class="c1"&gt;// ❌&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;taskList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&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="c1"&gt;// Processing logic involving multiple responsibilities&lt;/span&gt;
    &lt;span class="nf"&gt;updateTaskStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;displayTaskDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;validateTaskCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;verifyTaskExistence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&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;// ✅&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateTaskStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Logic for updating task status&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;displayTaskDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Logic for displaying task details&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Task ID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, Description: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;validateTaskCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Logic for validating task completion&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verifyTaskExistence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Logic for verifying task existence&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&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;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Beautiful, elegant, and organized code. This principle is the foundation for the others; by applying it, you should create high-quality, readable, and maintainable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. O - Open-Closed Principle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepfur4p9r55iwbk9i4yy.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%2Fepfur4p9r55iwbk9i4yy.png" alt="OCP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OCP - Open-Closed Principle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Objects or entities should be open for extension but closed for modification.&lt;/strong&gt; If you need to add functionality, it's better to extend rather than modify your source code.&lt;/p&gt;

&lt;p&gt;Imagine that you need a class to calculate the area of some polygons.&lt;/p&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&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;radius&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;sideLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;sideLength&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;areaCalculator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;totalArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shapes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&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;shapes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;shape&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shape&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shape&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;area&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;areaCalculator&lt;/code&gt; class is tasked with calculating the area of diferent polygons, each having its own area logic. If you, 'lil dev, needed to add new shapes, like triangles or rectangles, you'd find yourself &lt;strong&gt;altering&lt;/strong&gt; this class to make the changes, right? That's where you run into a problem, violating the &lt;code&gt;Open-Closed Principle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What solution comes to mind? Probably adding another method to the class and done, problem solved 🤩. Not quite, young Padawan 😓, that's the problem!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modifying an existing class to add new behavior carries a serious risk of introducing bugs into something that was already working.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember: OCP insists that a class should be closed for modification and open for extension.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See the beauty that comes with refactoring the code:&lt;/p&gt;

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

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&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;radius&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;sideLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;sideLength&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AreaCalculator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;totalArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shapes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&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;shapes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;shape&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;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;area&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="nx"&gt;total&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;See the &lt;code&gt;AreaCalculator&lt;/code&gt; class: it no longer needs to know which methods to call to register the class. It can correctly call the area method by calling the contract imposed by the interface, and that's the only thing it needs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As long as they implement the Shape interface, all runs fine.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;blockquote&gt;
&lt;p&gt;Separate extensible behavior behind an interface and invert dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Robert_C._Martin" rel="noopener noreferrer"&gt;Uncle Bob&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Open for extension:&lt;/code&gt; You can add new functionality or behavior to the class without changing its source code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Closed for modification:&lt;/code&gt; If your class already has a functionality or behavior that works fine, don't change its source code to add something new.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. L - Liskov Substitution Principle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62uow23fsa5zk2wz5fz5.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%2F62uow23fsa5zk2wz5fz5.png" alt="LSP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LSP - Liskov Substitution Principle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Liskov Substitution Principle says that &lt;strong&gt;a derived class must be substitutable for its base class.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This principle, introduced by Barbara Liskov in 1987, can be a bit complicated to understand by reading her explanation. Still, no worries, I'll provide another explanation and an example to help you understand.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If for each object o1 of type S there is an object o2 of type T such that, for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T.&lt;/p&gt;

&lt;p&gt;Barbara Liskov, 1987&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You got it, right? Nah, probably not. Yeah, I didn't understand it the first time I read it (nor the next hundred times), but hold on, there's another explanation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If S is a subtype of T, then objects of type T in a program can be replaced by objects of type S without altering the properties of this program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Liskov_substitution_principle" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're more of a visual learner, don't worry, here's an example:&lt;/p&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;speakName&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I am a person!&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;speakName&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I am a child!&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Person&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;child&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;printName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;printName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;speakName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// I am a person!&lt;/span&gt;
&lt;span class="nf"&gt;printName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;speakName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// I am a child!&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The parent class and the derived class are passed as parameters, and the code continues to work as expected. Magic? Yeah, it's the magic of our friend Barb.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of violations:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Overriding/implementing a method that does nothing;&lt;/li&gt;
&lt;li&gt;Returning values of different types from the base class.&lt;/li&gt;
&lt;li&gt;Throwing an unexpected exception;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. I - Interface Segregation Principle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbdmugukrcacuqthho5x.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%2Fqbdmugukrcacuqthho5x.png" alt="ISP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ISP - Interface Segregation Principle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one says that &lt;strong&gt;a class should not be forced to implement interfaces and methods it does not use.&lt;/strong&gt; It's better to create more specific interfaces than a big and generic one.&lt;/p&gt;

&lt;p&gt;In the following example, an &lt;strong&gt;Book&lt;/strong&gt; interface is created to abstract book behaviors, and then classes implement this interface:&lt;/p&gt;

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

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OnlineBook&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// does something&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// does something&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PhysicalBook&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// does something&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This implementation doesn't make sense for a book&lt;/span&gt;
    &lt;span class="c1"&gt;// it violates the Interface Segregation Principle&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The generic &lt;code&gt;Book&lt;/code&gt; interface is forcing the &lt;code&gt;PhysicalBook&lt;/code&gt; class to have a behavior that makes no sense (&lt;em&gt;or are we in the Matrix to download physical books?&lt;/em&gt;) and violates both the &lt;strong&gt;ISP&lt;/strong&gt; and &lt;strong&gt;LSP&lt;/strong&gt; principles.&lt;/p&gt;

&lt;p&gt;Solving this problem using &lt;strong&gt;ISP&lt;/strong&gt;:&lt;/p&gt;

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

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Readable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Downloadable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OnlineBook&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Readable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Downloadable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// does something&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// does something&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PhysicalBook&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Readable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// does something&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;Now it's waaay better. We removed the &lt;code&gt;download()&lt;/code&gt; method from the &lt;code&gt;Book&lt;/code&gt; interface and added it to a derived interface, &lt;code&gt;Downloadable&lt;/code&gt;. This way, the behavior is isolated correctly within our context, and we still respect the &lt;strong&gt;Interface Segregation Principle&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. D - Dependency Inversion Principle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F42aomc36xq804pyldlis.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%2F42aomc36xq804pyldlis.png" alt="DIP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DIP - Dependency Inversion Principle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one goes like this: &lt;strong&gt;Depend on abstractions and not on implementations.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;High-level modules should not depend on low-level modules. Both should depend on abstractions.&lt;/p&gt;

&lt;p&gt;Abstractions should not depend on details. Details should depend on abstractions.&lt;/p&gt;

&lt;p&gt;Uncle Bob&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now I'll show a simple code to illustrate DIP. In this example, there's a service that gets the user from the database. First, let's create a concrete class that connects with the database:&lt;/p&gt;

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

&lt;span class="c1"&gt;// Low-level module&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MySQLDatabase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Logic to fetch user data from MySQL database&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;Now, let's create a service class that depends on the concrete implementation:&lt;/p&gt;

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

&lt;span class="c1"&gt;// High-level module&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MySQLDatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&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;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MySQLDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;In the above example, &lt;code&gt;UserService&lt;/code&gt; directly depends on the concrete implementation of &lt;code&gt;MySQLDatabase&lt;/code&gt;. This violates &lt;strong&gt;DIP&lt;/strong&gt; since the &lt;strong&gt;high-level&lt;/strong&gt; class UserService is directly dependent on a &lt;strong&gt;low-level&lt;/strong&gt; class.&lt;/p&gt;

&lt;p&gt;If we want to switch to a different database system (e.g., PostgreSQL), we need to modify the UserService class, which is &lt;code&gt;AWFUL&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Let's fix this code using &lt;strong&gt;DIP&lt;/strong&gt;. Instead of depending on concrete implementations, the high-level class &lt;code&gt;UserService&lt;/code&gt; should depend on abstractions. Let's create a &lt;code&gt;Database&lt;/code&gt; interface as an abstraction:&lt;/p&gt;

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

&lt;span class="c1"&gt;// Abstract interface (abstraction) for the low-level module&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&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;Now, the concrete implementations &lt;code&gt;MySQLDatabase&lt;/code&gt; and &lt;code&gt;PostgreSQLDatabase&lt;/code&gt; should implement this interface:&lt;/p&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MySQLDatabase&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Logic to fetch user data from MySQL database&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Another low-level module implementing the Database interface&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostgreSQLDatabase&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Logic to fetch user data from PostgreSQL database&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;Finally, the UserService class can depend on the &lt;code&gt;Database&lt;/code&gt; abstraction:&lt;/p&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&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;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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 way, the &lt;code&gt;UserService&lt;/code&gt; class depends on the &lt;code&gt;Database&lt;/code&gt; abstraction, not on concrete implementations, fulfilling the &lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;By adopting these principles, developers can create systems more resilient to changes, making maintenance easier and improving code quality over time.&lt;/p&gt;

&lt;p&gt;The entirety of this article is derived from various other articles, my personal notes, and dozens of online videos that I came across while &lt;strong&gt;delving into the realms of Object-Oriented Programming (OOP)&lt;/strong&gt; 🤣. The code snippets utilized in the examples were created based on my interpretation and comprehension of these principles. I really wish, my lil padawan, that I have contributed to advance your understanding and progress in your studies.&lt;/p&gt;

&lt;p&gt;I really hope you liked this article, and don't forget to follow!&lt;/p&gt;

&lt;p&gt;Note: Images taken from &lt;a href="https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898" rel="noopener noreferrer"&gt;this article&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Handling Exceptions to impress in your Tech Interview</title>
      <dc:creator>Lucas Porfirio</dc:creator>
      <pubDate>Wed, 31 Jan 2024 18:16:40 +0000</pubDate>
      <link>https://dev.to/lukeskw/handling-exceptions-to-impress-in-your-tech-interview-4hmf</link>
      <guid>https://dev.to/lukeskw/handling-exceptions-to-impress-in-your-tech-interview-4hmf</guid>
      <description>&lt;p&gt;Exceptions will always be a constant topic when it comes to Object-Oriented Programming, and today, let's find out how to create them like true software artisans!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;When I started learning programming, one of the topics that always scared me was "errors" or anything related to it. However, as I studied more frequently, I realized that errors and/or Exceptions are much more friends than enemies. Of course, to achieve that, you need to understand how to use them in an interesting way for your project.&lt;/p&gt;

&lt;p&gt;In my case, I used to use the &lt;code&gt;throw new Error()&lt;/code&gt; snippet for literally anything, easily getting lost in the codebase due to a generic Exception scattered among many others. In the beginning, it wasn't a problem since I didn't work in a team with observability, so it was all good.&lt;/p&gt;

&lt;p&gt;But over time, as I joined more awesome companies, I encountered excellent implementations of Exceptions, especially using the &lt;code&gt;Factory Pattern&lt;/code&gt;. This method amazed me in how things can be &lt;code&gt;simple and elegant&lt;/code&gt;, even when dealing with errors.&lt;/p&gt;

&lt;p&gt;Today, I'll show you how to develop a taste for writing elegant Exceptions and avoid cluttering your code with a 2km-long error message within the business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What We Want to AVOID
&lt;/h2&gt;

&lt;p&gt;Let's start by giving a bit of context to this article: imagine you're developing an simple social network, and in it, you need to create a simple post for your user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src
├── Post
│   └── Post.php
└── User
    ├── User.php
    └── Permission.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within this context, imagine you're trying to post as an user. Naturally, we'll impose some validation rules with their respective &lt;code&gt;Exceptions&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Lukeskw\User;

use Lukeskw\Post\Post;

class User {

    public function __construct(
        public string $username,
        public email $email,
        protected Permission $permission
    ) {

    }

    public function post(Post $post): void
    {

        if (!$this-&amp;gt;permission-&amp;gt;hasPermission($this-&amp;gt;username)) {
            throw new \Exception(
                'You do not have permission to post because you are a "' . $this-&amp;gt;permission-&amp;gt;name . '". '
            );
        }

        if (strlen($post-&amp;gt;description) &amp;lt; 50) {
            throw new \Exception(
                'You cannot post ' . $post-&amp;gt;id . ' because it only has ' . strlen($post-&amp;gt;description) . ' characters';
            );
        }

        $this-&amp;gt;postToFeed($post);
    }


    private function postToFeed(Post $post): void
    {
        // do awesome stuff
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've identified two validation rules that throw different exceptions to our client. And believe it or not, it works (in a scenario where the code is complete, ofc) and fulfills the validation role. HOWEVER, after learning that job interviews prioritize the &lt;code&gt;QUALITY OF DELIVERY over the SPEED OF CREATION&lt;/code&gt;, my perspective shifted slightly to understanding how to transform things that seem "strange and ugly" into "simple and elegant" things.&lt;/p&gt;

&lt;p&gt;In this case, I'd really like to avoid two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generic Exceptions;&lt;/li&gt;
&lt;li&gt;Exceptions taking over places meant for business logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't get me wrong; the exceptions will still be where they are, but we'll improve the code's readability.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Refactoring 1: Creating Exceptions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src
├── Post
│   ├── Exceptions
│   │   └── PostException.php
│   └── Post.php
│
└── User
    ├── Exceptions
    │   └── UserPermissionException.php
    ├── User.php
    └── Permission.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright, now let's move on to the part where we create our first "customized" Exception by extending the base Exception to a new class. It's nothing out of this world, but it already enhances our readability and understanding of the code in several aspects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Lukeskw\User;

class PostException extends \Exception
{}

class UserPermissionException extends \Exception
{}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we'll do a simple refactoring in our &lt;code&gt;post()&lt;/code&gt; function, repositioning the default exceptions with the new exception we created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Lukeskw\User;

use Lukeskw\Post\Post;
use Lukeskw\Post\Exceptions\PostException;
use Lukeskw\User\Exceptions\UserPermissionException;

class User {

    public function __construct(
        public string $username,
        public email $email,
        protected Permission $permission
    ) {

    }

    public function post(Post $post): void
    {

        if (!$this-&amp;gt;permission-&amp;gt;hasPermission($this-&amp;gt;username)) {
            throw new UserPermissionException(
                'You do not have permission to post because you are a "' . $this-&amp;gt;permission-&amp;gt;name . '". '
            );
        }

        if (strlen($post-&amp;gt;description) &amp;lt; 50) {
            throw new PostException(
                'You cannot post ' . $post-&amp;gt;id . ' because it only has ' . strlen($post-&amp;gt;description) . ' characters';
            );
        }

        $this-&amp;gt;postToFeed($post);
    }


    private function postToFeed(Post $post): void
    {
        // do awesome stuff
    }
}

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

&lt;/div&gt;



&lt;p&gt;With the new Exceptions, we now know exactly what it's about and, most importantly, where to look in our codebase when this Exception is triggered. It's literally a &lt;code&gt;CTRL + SHIFT + F&lt;/code&gt; and search for the name "UserPermissionException." Makes your life easier, the life of the DevOps who will throw this into NewRelic/DataDog, and so on.&lt;/p&gt;

&lt;p&gt;But something still bothers me a lot... Why are these giant messages in the middle of the business logic? Let's learn a way to hide this under the hood, but before that, we need to go through a Design Pattern called Factory!&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Design Patterns: Factory Pattern
&lt;/h2&gt;

&lt;p&gt;If you've heard of Design Patterns, you probably already understand a bit about what it solves. But in case you don't, I'll explain!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Design Patterns are generic solutions to generic problems." - John Doe&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this idea of generic problems, some people got together and started creating some Software Design principles for you to solve day-to-day problems with a certain agility. Design Patterns are divided into three types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Behavioral Patterns;&lt;/li&gt;
&lt;li&gt;Creational Patterns;&lt;/li&gt;
&lt;li&gt;Structural Patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read more about them on the &lt;a href="//https:/refactoring.guru"&gt;Refactoring Guru website&lt;/a&gt;, and I highly recommend it for any developer to explore this documentation and self-develop. Okay, but let's focus on it, the so-called &lt;a href="https://refactoring.guru/pt-br/design-patterns/factory-method"&gt;Creational Factory (or Factory Method)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The idea of this pattern is to create objects without having to instantiate a thousand things in different classes. You literally manufacture an instance of something and just receive it in a simple call to some function. In the programming world, there are hundreds of millions of calls like &lt;code&gt;Models::make()&lt;/code&gt;, &lt;code&gt;Exception::create()&lt;/code&gt;, &lt;code&gt;ApiWhatever::factory()&lt;/code&gt; so you don't have to access the constructor method of a respective class.&lt;/p&gt;

&lt;p&gt;Taking the example of an API client, where we make the constructor modular in case we need to change the key and secret BUT still give the possibility of a quick call to manufacture the final object:&lt;br&gt;
&lt;/p&gt;

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

    public function __construct(string $clientId, string $clientSecret)
    {
        $this-&amp;gt;client = new Client([
            'clientId' =&amp;gt; $clientId,
            'clientSecret' =&amp;gt; $clientSecret,
        ]);
    }

    public static function make(): self
    {
        return new self(
            env('github.client_id'),
            env('github.client_secret'),
        );
    }

    public function getUserByUsername(string $username = 'lukeskw'): array
    {
        // do a github call..
    }
}

// Calling without creating object

$client = (new GithubClient('awesome-client-id', 'awesome-client-secret'))
    -&amp;gt;getUserByUsername('lukeskw');

// Using Factory

$client = GithubClient::make()
    -&amp;gt;getUserByUsername('lukeskw');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We made a static call, manufacturing all parameters in a succinct way. This "make/factory" or whatever you want to call it can be a very extensive method depending on what you're injecting, but that's not a problem.&lt;/p&gt;

&lt;p&gt;But anyway, we saw that readability using the Factory Pattern was improved; of course, you can put better names for the functions, but at its core, that's it. Now let's go back to our exceptions!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Refactoring 2: Refining the Exceptions
&lt;/h2&gt;

&lt;p&gt;Great, we've learned a bit about the factory; now let's apply it.&lt;/p&gt;

&lt;p&gt;We'll create a factory method for our exception that makes sense in the context of what's happening. Yeah, none of that "make" or "create" in these moments. Exceptions need to tell at least a minimal story for the user or developer about what's happening, and that's what we'll focus on.&lt;/p&gt;

&lt;p&gt;After a slight refactoring in our &lt;code&gt;UserPermissionException&lt;/code&gt;, we have the result of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserPermissionException extends \Exception
{
    public static function permissionNotFound(string $permission): self
    {
        $message = sprintf('You do not have permission to post because you are a "%s".', $permission);
        return new self(
            message: $message,
            code: 403 // Forbidden
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after calling this factory in our code, we can notice an improvement in readability and maintainability since we isolated the information of the Exception within it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; public function post(Post $post): void
    {

        if (!$this-&amp;gt;permission-&amp;gt;hasPermission($this-&amp;gt;username)) {
            throw UserPermissionException::permissionNotFound($this-&amp;gt;permission-&amp;gt;name);
        }

        if (strlen($post-&amp;gt;description) &amp;lt; 50) {
            throw new PostException(
                'You cannot post ' . $post-&amp;gt;id . ' because it only has ' . strlen($post-&amp;gt;description) . ' characters';
            );
        }

        $this-&amp;gt;postToFeed($post);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, refactoring the next one, we have the same idea of changing the &lt;code&gt;PostException&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PostException extends \Exception
{
    public static function minCharacters(string $postId, int $postCharCount): self
    {

        $message = sprintf(
           'You cannot post %s because it only has %c characters', $postId, $postCharCount,
        );

        return new self(
            message: $message,
            code: 403 // Forbidden
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now our &lt;code&gt;post()&lt;/code&gt; is looking wonderful!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; public function post(Post $post): void
    {

        if (!$this-&amp;gt;permission-&amp;gt;hasPermission($this-&amp;gt;username)) {
            throw UserPermissionException::permissionNotFound($this-&amp;gt;permission-&amp;gt;name);
        }

        if (strlen($post-&amp;gt;description) &amp;lt; 50) {
            throw PostException::minCharacters($post-&amp;gt;id, strlen($post-&amp;gt;description));
        }

        $this-&amp;gt;postToFeed($post);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is it wonderful? Yes. But there's still something bothering me... Why pass primitive types when these exceptions are "communicating" with classes?&lt;/p&gt;

&lt;p&gt;It would be much cleaner if we pass the reference of the entire object to the Exception, and inside it, it resolves what it needs to use. After all, what if we need more things in the future, and it doesn't hurt to make it look nice, right?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Lukeskw\Post;

use Lukeskw\Post\Post;

class PostException extends \Exception
{
     public static function minCharacters(Post $post): self
    {

        $message = sprintf(
           'You cannot post %s because it only has %c characters', $post-&amp;gt;id, strlen($post-&amp;gt;description),
        );

        return new self(
            message: $message,
            code: 403 // Forbidden
        );
    }
}

---------------------------------------------------------------

namespace Lukeskw\User;

use Lukeskw\User\Permission;

class UserPermissionException extends \Exception
{
    public static function permissionNotFound(Permission $permission): self
    {
        $message = sprintf('You do not have permission to post because you are a "%s".', $permission-&amp;gt;name);
        return new self(
            message: $message,
            code: 403 // Forbidden
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the final result of our method is just charming, with encapsulated exceptions that will also give you great feedback in your job interview.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Lukeskw\User;

use Lukeskw\Post\Post;
use Lukeskw\Post\Exceptions\PostException;
use Lukeskw\User\Exceptions\UserPermissionException;

class User {

    public function __construct(
        public string $username,
        public email $email,
        protected Permission $permission
    ) {

    }

    public function post(Post $post): void
    {

        if (!$this-&amp;gt;permission-&amp;gt;hasPermission($this-&amp;gt;username)) {
          throw UserPermissionException::permissionNotFound($this-&amp;gt;permission);
        }

        if (strlen($post-&amp;gt;description) &amp;lt; 50) {
            throw PostException($post);
        }

        $this-&amp;gt;postToFeed($post);
    }


    private function postToFeed(Post $post): void
    {
        // do awesome stuff
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Conclusion
&lt;/h2&gt;

&lt;p&gt;Exceptions are by far one of the most "annoying" things to deal with. After all, nobody wants errors popping up on the client's screen. But overall, they just need to be well-written, and adding a bit of charm with static calls, and BOOM, you get praise and a positive points in the job interview.&lt;/p&gt;

&lt;p&gt;I really hope you liked this article, and don't forget to follow!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>php</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Improving Laravel's Queue Performance</title>
      <dc:creator>Lucas Porfirio</dc:creator>
      <pubDate>Fri, 15 Sep 2023 19:12:56 +0000</pubDate>
      <link>https://dev.to/lukeskw/improving-laravels-queue-performance-421j</link>
      <guid>https://dev.to/lukeskw/improving-laravels-queue-performance-421j</guid>
      <description>&lt;p&gt;I didn't always use Laravel the way I do today. In the beginning, I made a lot of mistakes, and I believe that's part of the maturing and evolving process, so let's call it normal. Perhaps I've made the same mistakes you have, or maybe even more. One of the many mistakes I made was, for example, making all my validations inside the controller😂 Fortunately, I recognized my mistake very early on and was able to correct it in time.&lt;/p&gt;

&lt;p&gt;Now, considering the context of queues (jobs), another mistake I've made is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SaveAccessLog implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public function __construct(protected User $user)
    {
        //
    }

    public function handle(): void
    {
        Log::create([
            'user_id' =&amp;gt; $this-&amp;gt;user-&amp;gt;id,
            // ...
        ]);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you know what the problem is with this piece of code? I already know what you're thinking: "It's not creating the log via a relationship!" Did I get it right? Don't worry; this is just an example! If you're not a hardcore Laravel user, you probably won't see the issue; everything seems normal. If you couldn't find the answer, don't worry. I'll explain it to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Problem
&lt;/h2&gt;

&lt;p&gt;First of all, this is not an error but rather a Laravel behavior that prevents us from extracting the maximum potential from our queues, resulting in a performance issue in terms of execution time.&lt;/p&gt;

&lt;p&gt;Have you noticed that every Laravel queue class includes four traits?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SaveAccessLog implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's where the point to be observed lies. One of these traits is "SerializesModels." This trait is responsible for serializing and deserializing all the properties in the queue class. Inside it, it uses another trait called "SerializesAndRestoresModelIdentifiers," which, in turn, performs other tasks by consuming other Laravel classes, for example, identifying if a serialized property is an instance of a model so it can be correctly retrieved from the database.&lt;/p&gt;

&lt;p&gt;Basically, what Laravel needs to do at this point in the execution is, as mentioned above, serialize the properties of the queue class so that they can be stored in databases - regardless of their type. When the queue is actually executed, these properties should be available for use in their original state, preserving the values given to the properties when the queue record was created. This helps us understand that the larger the object to be serialized, the more work Laravel needs to do to perform serialization and deserialization, and that's where the problem lies.&lt;/p&gt;

&lt;p&gt;A queue is stored in the database like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "uuid": "31378037-ebd2-4cd0-9abf-b9cfac94c8c9",
    "displayName": "App\\Jobs\\SaveAccessLog",
    "job": "Illuminate\\Queue\\CallQueuedHandler@call",
    "maxTries": null,
    "maxExceptions": null,
    "failOnTimeout": false,
    "backoff": null,
    "timeout": null,
    "retryUntil": null,
    "data": {
        "commandName": "App\\Jobs\\SaveAccessLog",
        "command": "O:22:\"App\\Jobs\\SaveAccessLog\":1:{s:6:\"\u0000*\u0000car\";O:45:\"Illuminate\\Contracts\\Database\\ModelIdentifier\":5:{s:5:\"class\";s:14:\"App\\Models\\Car\";s:2:\"id\";i:1;s:9:\"relations\";a:0:{}s:10:\"connection\";s:6:\"sqlite\";s:15:\"collectionClass\";N;}}"
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If, after deserialization, the property is a model, then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Illuminate/Queue/SerializesAndRestoresModelIdentifiers.php

protected function getRestoredPropertyValue($value)
{
    // ...

    return is_array($value-&amp;gt;id)
        ? /* ... */
        : $this-&amp;gt;restoreModel($value); // 👈🏻
}

public function restoreModel($value)
{
    return $this-&amp;gt;getQueryForModelRestoration(
        (new $value-&amp;gt;class)-&amp;gt;setConnection($value-&amp;gt;connection), $value-&amp;gt;id
    )-&amp;gt;useWritePdo()-&amp;gt;firstOrFail()-&amp;gt;load($value-&amp;gt;relations ?? []); // 👈🏻
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solving This Problem
&lt;/h2&gt;

&lt;p&gt;Many developers insist on "injecting" an entire object into the queue class—often as an instance of a model, carrying numerous relationships—without realizing that for the context of that task, perhaps only one, two, or three properties of the model would be necessary.&lt;/p&gt;

&lt;p&gt;Let's look at the example again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SaveAccessLog implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public function __construct(protected User $user)
    {
        //
    }

    public function handle(): void
    {
        Log::create([
            'user_id' =&amp;gt; $this-&amp;gt;user-&amp;gt;id,
            // ...
        ]);
    }
}

// ...

SaveAccessLog::dispatch(User::first());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you see that only the user's id is REALLY in use in the above example? So, why do I need to send the entire user object? That doesn't make any sense! The best approach to IMPROVE THIS CODE would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SaveAccessLog implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public function __construct(protected int $userId)
    {
        //
    }

    public function handle(): void
    {
        Log::create([
            'user_id' =&amp;gt; $this-&amp;gt;userId,
            // ...
        ]);
    }
}

// ...

SaveAccessLog::dispatch(User::first()-&amp;gt;id);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the difference? Basically, if I only need the user's id, then I send ONLY the user's id. At this point, you might ask, "But won't Laravel serialize this the same way?" I confess that this is a GREAT question! The answer is: YES, but the effort Laravel needs to serialize and deserialize an int is MUCH LESS than for an entire object.&lt;/p&gt;

&lt;p&gt;Here is the serialization of the improved code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "uuid": "8fd5f768-8421-467c-8cb6-4a0973ca9829",
    "displayName": "App\\Jobs\\SaveAccessLog",
    "job": "Illuminate\\Queue\\CallQueuedHandler@call",
    "maxTries": null,
    "maxExceptions": null,
    "failOnTimeout": false,
    "backoff": null,
    "timeout": null,
    "retryUntil": null,
    "data": {
        "commandName": "App\\Jobs\\SaveAccessLog",
        "command": "O:22:\"App\\Jobs\\SaveAccessLog\":1:{s:8:\"\u0000*\u0000userId\";i:1;}"
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how it is smaller in the data section? It's worth noting that with the improved code example approach, Laravel won't perform a database query when the queue is actually executed since we haven't injected a model instance, but only the user's id.&lt;/p&gt;

&lt;p&gt;Did you think I forgot about situations where we need to inject more than one property into the queue class? For such cases, in my view, the ideal approach is to send an array with everything needed for execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SaveAccessLog implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public function __construct(protected array $user)
    {
        //
    }

    public function handle(): void
    {
        Log::create([
            'user_id'    =&amp;gt; $this-&amp;gt;user['id'],
            'user_email' =&amp;gt; $this-&amp;gt;user['email'],
            // ...
        ]);
    }
}

// ...

SaveAccessLog::dispatch(User::first()-&amp;gt;toArray());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;It's okay if you don't see the point in this right now! Take the learning and carry it with you because I guarantee that one day you will need it, and then you will see the difference. In my case, this only made sense to me when I needed to scale the performance and execution time of my queues because it was with this technique that I achieved IMPRESSIVE queue execution results.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>From XMLHttpRequest to Fetch API: How Fetch became the Way Forward for JS Development</title>
      <dc:creator>Lucas Porfirio</dc:creator>
      <pubDate>Thu, 29 Jun 2023 03:50:21 +0000</pubDate>
      <link>https://dev.to/lukeskw/from-xmlhttprequest-to-fetch-api-how-fetch-became-the-way-forward-for-js-development-2a9b</link>
      <guid>https://dev.to/lukeskw/from-xmlhttprequest-to-fetch-api-how-fetch-became-the-way-forward-for-js-development-2a9b</guid>
      <description>&lt;h3&gt;
  
  
  Hello there ✌
&lt;/h3&gt;

&lt;p&gt;This week I have been reading about the "recently" added Fetch API in NodeJS, which got me thinking about how we moved from XMLHttpRequests to the Fetch API. As developers, I really think we should understand the history behind the things we use daily.&lt;/p&gt;

&lt;p&gt;XMLHttpRequest (XHR) has long been the go-to choice for making asynchronous HTTP requests. But, with the introduction of the Fetch API, a newer alternative has emerged. We will now explore why the Fetch API is considered the way forward for JavaScript development, and why it has quickly gained popularity among us, web developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawbacks of XMLHttpRequests
&lt;/h2&gt;

&lt;p&gt;XHR, while functional, comes with a few limitations. Its syntax is complex and often requires extensive boilerplate code. Beyond that, XHR responses are based on event listeners, leading to the famous callback hell and unreadable code. The Fetch API addresses these drawbacks, providing a simpler and more intuitive approach to handling network requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplicity of the Fetch API
&lt;/h2&gt;

&lt;p&gt;I guess we all can agree that ES6 changed the internet, presenting us with many new resources, including the Fetch API. With that said, one of the major advantages of the API is its simplicity. The API is built around the concept of promises, allowing for cleaner and more readable code. Now we can easily chain operations using the .then() method, making the code flow more intuitive and way easier to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community adoption
&lt;/h2&gt;

&lt;p&gt;The Fetch API has gained significant popularity within the JavaScript community. It is widely used in modern frameworks and libs, and extensive resources and documentation are available for developers to explore and learn from. By using the Fetch API, &lt;br&gt;
devs jump right into a sharing community that's all about working together.&lt;/p&gt;

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

&lt;p&gt;There are tons of reasons for why we moved to the Fetch API, such as standardization, CORS support, async/await and others. The API represented a significant step forward for JavaScript networking, offering a simpler, more flexible, and future-proof approach compared to the traditional XMLHttpRequest. Its seamless integration with promises, improved syntax, and robust support for modern web standards make it the preferred choice for making asynchronous HTTP requests. By using the Fetch API, developers can unlock the full potential of JavaScript networking and build more reliable, and scalable apps for the web.&lt;/p&gt;

&lt;p&gt;I truly love the history behind all this revolution we're living, and I really enjoyed writing this. I hope you like the read as well! ❤&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Unlocking the Potential of Async in JavaScript</title>
      <dc:creator>Lucas Porfirio</dc:creator>
      <pubDate>Fri, 09 Jun 2023 05:03:17 +0000</pubDate>
      <link>https://dev.to/lukeskw/unlocking-the-potential-of-async-in-javascript-4mgc</link>
      <guid>https://dev.to/lukeskw/unlocking-the-potential-of-async-in-javascript-4mgc</guid>
      <description>&lt;p&gt;Today I was wandering around Dev.to and found &lt;a href="https://dev.to/ptheodosiou/understanding-promises-in-javascript-5c0"&gt;this&lt;/a&gt; great article about promises, and it gave me the idea to discuss about asynchronous Javascript.&lt;/p&gt;

&lt;p&gt;As you should know by now, JS is standardized by ECMA International, and every year they develop new features to the language we all know and love. And in 2017, with the 8th version of  ECMAScript(ES8), they announced a new syntactic suggar for our Promises: &lt;strong&gt;Async and Await&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Async/await is a newer way to handle Promises within our code, avoiding the creation of cascades of &lt;strong&gt;&lt;code&gt;.then&lt;/code&gt;&lt;/strong&gt; as we often see on our codes. It's worth noting that we are still working with Promises, but they become less visible and less verbose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax
&lt;/h2&gt;

&lt;p&gt;We use the prefix &lt;strong&gt;&lt;code&gt;async&lt;/code&gt;&lt;/strong&gt; before defining a function to indicate that we are dealing with asynchronous code, and with the added prefix, we can use &lt;strong&gt;&lt;code&gt;await&lt;/code&gt;&lt;/strong&gt; before Promises to indicate a point to be awaited by the code. Let's understand how this works in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Promise way (pre ES8)
function fetchBooks(book) {
  fetch(`/books/${book}`).then(response =&amp;gt; {
    console.log(response);
  });
}

// Async/Await way (ES8+)
async function fetchBooks(book) {
  const response = await fetch(`/books/${book}`);
  console.log(response);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how the code became clearer. We no longer need to declare &lt;strong&gt;&lt;code&gt;.then&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;.catch&lt;/code&gt;&lt;/strong&gt; and worry about a Promise not executing before using its result because await takes on the role of waiting for the request to return its result.&lt;/p&gt;

&lt;p&gt;I believe that the biggest problem solved by async/await is the famous Promise cascade, affectionately called &lt;strong&gt;Promise Hell&lt;/strong&gt;. Let's imagine the following code written in ES6 (without async/await):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch('/users/lukeskw').then(user =&amp;gt; {
  fetch(`/groups/${user.id}`).then(groups =&amp;gt; {
    groups.map(group =&amp;gt; {
      fetch(`/group/${group.id}`).then(groupInfo =&amp;gt; {
        console.log(groupInfo);
      });
    })
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tangled mess of code and &lt;strong&gt;&lt;code&gt;.then&lt;/code&gt;&lt;/strong&gt; statements that we see can be easily improved using this syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function fetchUserAndGroups() {
  const user = await fetch('/users/lukeskw');
  const groups = await fetch(`/groups/${user.id}`);

  groups.map(group =&amp;gt; {
    const groupInfo = await fetch(`/group/${group.id}`);
    console.log(groupInfo);
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each time we define an &lt;strong&gt;&lt;code&gt;await&lt;/code&gt;&lt;/strong&gt;, we are indicating to our interpreter to wait for the next Promise to execute and return a result before proceeding. This way, we prevent the subsequent lines from executing without the necessary variables.&lt;/p&gt;

&lt;p&gt;It's worth remembering that every function we define with async automatically becomes a Promise. This means that we can attach asynchronous functions to each other. Let's see how this looks in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function fetchUser() {
  const response = await fetch('/users/lukeskw');

  return response;
}

async function fetchGroups() {
  const user = await fetchUser();

  const response = await fetch(`/groups/${user.id}`);

  console.log(response);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  And what about the &lt;strong&gt;&lt;code&gt;.catch&lt;/code&gt;&lt;/strong&gt;?
&lt;/h2&gt;

&lt;p&gt;So far, we have seen how to capture the result of the previous &lt;strong&gt;&lt;code&gt;.then&lt;/code&gt;&lt;/strong&gt; and assign it to a variable using await. But how do we handle errors? With this syntax, we can use the good ol' try/catch to ensure that errors in our code and Promise responses don't leave traces for the end user. Let's see how this works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Promise syntax (ES6)

function fetchUser() {
  fetch('/users/lukeskw')
    .then(response =&amp;gt; console.log(response));
    .catch(err =&amp;gt; console.log('Error:', err));
}

// New syntax (ES8+)

async function fetchUser() {
  try {
    const response = await fetch('/users/lukeskw');

    console.log(response);
  } catch (err) {
    console.log('Error:', err);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to making the code more elegant, a great utility is to use a single catch for multiple Promises. This way, if the errors from these Promises have the same outcome for the end user, we can handle them in one place (while still separating them into multiple try/catch blocks if the errors are different).&lt;/p&gt;

&lt;h2&gt;
  
  
  And when to use it?
&lt;/h2&gt;

&lt;p&gt;That's a tough question to answer, but for me, there is no restrictions to using async/await. In fact, it's been a while since I wrote a .then because I believe that the new syntax makes the code cleaner.&lt;/p&gt;

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

&lt;p&gt;Async/await simplifies error handling with the familiar try/catch blocks, allowing us to centralize error handling logic and provide a better user experience. It also enhances code readability by reducing promise hell and minimizing nested structures.&lt;/p&gt;

&lt;p&gt;Whether you're fetching data from an API, performing database queries, or handling any asynchronous task, async/await is a valuable tool in your JavaScript arsenal. Its adoption has become increasingly widespread, and it has quickly become the preferred approach for handling asynchronous operations.&lt;/p&gt;

&lt;p&gt;So no more need of writing cascades of &lt;strong&gt;&lt;code&gt;.then&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;.catch&lt;/code&gt;&lt;/strong&gt; that we were used to 😁&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Higher Order Functions explained</title>
      <dc:creator>Lucas Porfirio</dc:creator>
      <pubDate>Mon, 29 May 2023 16:54:47 +0000</pubDate>
      <link>https://dev.to/lukeskw/higher-order-functions-explained-35pe</link>
      <guid>https://dev.to/lukeskw/higher-order-functions-explained-35pe</guid>
      <description>&lt;p&gt;Lately, I've been immersing myself in the study of functional programming. Being someone who enjoys sharing knowledge with others, I have chosen to write this article and share my current knowledge and experience.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a web developer, it's essential to continuously study new techniques and find ways to enhance your code. Even more so in the JavaScript world, where it experiences daily changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One valuable technique to explore in Javascript is the utilization of higher order functions. These functions have the capability to accept one or more functions as arguments or even return a function as their output.&lt;/p&gt;

&lt;p&gt;Within this article, we will delve into the concept of higher order functions, and some simple implementation methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what is a Higher Order Function?
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions"&gt;Mozilla's&lt;/a&gt; documentation, a function is a block of code that performs a task or calculates a value. &lt;/p&gt;

&lt;p&gt;In JavaScript, functions are treated as first-class citizens, meaning they can be used and manipulated just like any other data type, such as strings, arrays, or objects.&lt;/p&gt;

&lt;p&gt;Here are some examples of what you can do with functions when they are treated as first-class citizens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign them to a variable.&lt;/li&gt;
&lt;li&gt;Set them as properties of an object.&lt;/li&gt;
&lt;li&gt;Store them in arrays.&lt;/li&gt;
&lt;li&gt;Use them as an argument to a function or as a return from a function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the fouth item is exactly the definition of a Higher Order Function, which is:  &lt;strong&gt;a higher-order function is a function that takes one or more functions as arguments and/or returns a function as its result.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simply put, it operates on functions just like any other data type in JavaScript. And this is possible only because in JavaScript, functions are considered first-class citizens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing Functions as Arguments
&lt;/h2&gt;

&lt;p&gt;One of the most powerful aspects of higher-order functions is their ability to accept other functions as arguments. This allows us to abstract common functionality into reusable functions and pass them dynamically to higher-order functions.&lt;/p&gt;

&lt;p&gt;Let's see how we can write a code that shows this using HOFs:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbkib0030hksri274isl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbkib0030hksri274isl.png" alt="Implementation of a function passed as an argument" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the code above, we created a higher-order function called "higherOrderFunction" that performs a simple math operation on a number. By passing a separate function, like multiplyByTwo, as an argument to higherOrderFunction, we can customize the operation in our favor. In this example, the multiplyByTwo function doubles the given number. This approach helps us write more flexible and reusable code, as we can easily change the operation or even use different functions with the same higher order function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Returning Functions
&lt;/h2&gt;

&lt;p&gt;Higher-order functions can also return functions as their results. This allows for the creation of specialized functions or the generation of dynamic functions, enabling customization to suit specific contexts or requirements.&lt;br&gt;
Here's an example:&lt;/p&gt;

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

&lt;p&gt;In the snippet above, the createGreeting function produces a customized greeting function. This inner function combines a provided greeting message with a given name, resulting in personalized greetings. By utilizing createGreeting with various greeting messages, we can generate distinct greeting functions that can be reused to greet different names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in HOFS in JavaScript
&lt;/h2&gt;

&lt;p&gt;The coolest part of learning higher order functions is definitely understanding that this is a core JS feature. Many of the built-in JavaScript functions, such as those operating on arrays, strings, DOM methods, promise methods, and others, are higher order functions that offer a significant level of abstraction to us. To name a few, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Array.prototype.map()&lt;/li&gt;
&lt;li&gt;Array.prototype.forEach()&lt;/li&gt;
&lt;li&gt;Array.prototype.filter()&lt;/li&gt;
&lt;li&gt;Array.prototype.reduce()&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Higher order functions in JavaScript are a powerful tool that empowers developers to create code that is expressive, reusable, and modular. By treating functions as first-class citizens, we can pass them as arguments and even return functions from other functions, opening up the possibilities of functional programming. Understanding higher order functions allows you to enhance your JavaScript programming skills and elevate the overall quality of your code.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
