<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Andrew Savetchuk's Blog]]></title><description><![CDATA[My tech blog covers a wide range of topics on the latest trends, programming languages, frameworks, and tools in the ever-evolving world of technology.]]></description><link>https://blog.savetchuk.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 03:33:59 GMT</lastBuildDate><atom:link href="https://blog.savetchuk.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Redesign Your Github Page]]></title><description><![CDATA[I haven't updated my GitHub page for a while and decided to give it a new look. It turned out to be very simple, and it's good if you want your profile to stand out from the millions of others. Also, sometimes recruiters and HR professionals can find...]]></description><link>https://blog.savetchuk.com/how-to-redesign-your-github-page</link><guid isPermaLink="true">https://blog.savetchuk.com/how-to-redesign-your-github-page</guid><category><![CDATA[GitHub]]></category><category><![CDATA[resume]]></category><category><![CDATA[personalbrand]]></category><category><![CDATA[portfolio]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Wed, 15 Mar 2023 05:14:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679026395539/6e1f92b9-5fd1-46bf-814e-5e79ac5fb2d6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I haven't updated my GitHub page for a while and decided to give it a new look. It turned out to be very simple, and it's good if you want your profile to stand out from <a target="_blank" href="https://techcrunch.com/2022/10/25/microsoft-says-github-now-has-a-1b-arr-90m-active-users/">the millions of others</a>. Also, sometimes recruiters and HR professionals can find you on GitHub and contact you, as has happened to me several times before.</p>
<p>So I put in a little effort and in just one day I went from this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678682814009/39c14c49-7879-4a2d-8358-a2947d958c26.jpeg" alt class="image--center mx-auto" /></p>
<p>To this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678682822969/c10b400f-5c73-46cd-a5a3-c547e8f8b4d2.jpeg" alt class="image--center mx-auto" /></p>
<p>Most of the time was spent on editing the text and skills. <a target="_blank" href="https://github.com/AndrewSavetchuk">Click here</a> to check out my GitHub profile or keep reading and edit yours.</p>
<h2 id="heading-left-column">Left Column</h2>
<p>With the left column, everything is simple. Click on the "Edit profile" button and fill in all the fields. Keep in mind that GitHub often adds new features, so it's worth checking back from time to time to see if they've added anything to this column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678684294107/8013caf0-e500-4b25-a038-1fc1b86e7722.jpeg" alt /></p>
<p>If you want to customize the left column even more, you should check out <a target="_blank" href="https://github.com/Schweinepriester/github-profile-achievements#achievements">GitHub Achievements</a>. Most of them aren't easy to unlock, but getting them is a good way to prove your skill level.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678684959156/3ec0b4c5-11cc-4f1d-9f43-6692ae45152e.jpeg" alt /></p>
<h2 id="heading-main-area">Main Area</h2>
<p>This is where things get more interesting. In addition to the pinned repositories and <a target="_blank" href="https://gist.github.com/AndrewSavetchuk">gists</a>, you can create an entire page with information about yourself. To do so, just create a repository and name it the same as your GitHub username.</p>
<p>For example, my GitHub username is <strong>AndrewSavetchuk</strong>, so my GitHub repository for my profile page is also named <a target="_blank" href="https://github.com/AndrewSavetchuk/AndrewSavetchuk"><strong>AndrewSavetchuk</strong></a>. You are welcome to take a look or use some of my code to make changes to your profile.</p>
<p>In the newly created repository, you will need to edit the <code>README.md</code> file to make changes to your page. There you can use <a target="_blank" href="https://github.github.com/gfm/">markdown</a> as well as HTML.</p>
<p>I decided to add some text about me, a list of languages and technologies, the latest blog posts, social links and one widget that shows my GitHub contributions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678856301533/0070c318-b671-4d31-835a-542575c179c3.jpeg" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678856313155/e4bcabca-2db2-4d95-a6cd-5f6ae0e38bd4.jpeg" alt class="image--center mx-auto" /></p>
<p>If you need more inspiration, I recommend you visit this website - <a target="_blank" href="https://zzetao.github.io/awesome-github-profile/">https://zzetao.github.io/awesome-github-profile/</a>. It's a collection of well-designed GitHub pages that I often use to see what widgets are used by others.</p>
<p>You may also like the images I used for skills and social links, you can find them here: <a target="_blank" href="https://github.com/alexandresanlim/Badges4-README.md-Profile">https://github.com/alexandresanlim/Badges4-README.md-Profile</a></p>
<p>As you can see, redesigning GitHub's page is not a challenging task and now that you have learned how to do it, why not put your newfound knowledge into action? Try out the ideas discussed in this article and see how they work for you.</p>
<hr />
<p>I hope you found this information helpful, stay tuned for more content! I also post on <a target="_blank" href="https://twitter.com/AndrewSavetchuk">Twitter</a> and <a target="_blank" href="https://mas.to/@AndrewSavetchuk">Mastodon</a> if you want more content on web development and other technologies in your feed :)</p>
]]></content:encoded></item><item><title><![CDATA[Overview of MVC Architectural Pattern]]></title><description><![CDATA[MVC stands for Model-View-Controller and is a software architecture pattern commonly used to develop software applications. Although originally designed for desktop computing, MVC has been widely adopted as a design for World Wide Web applications in...]]></description><link>https://blog.savetchuk.com/overview-of-mvc-architectural-pattern</link><guid isPermaLink="true">https://blog.savetchuk.com/overview-of-mvc-architectural-pattern</guid><category><![CDATA[Web Development]]></category><category><![CDATA[backend]]></category><category><![CDATA[mvc]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[patterns]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Fri, 03 Mar 2023 00:30:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677792474312/2f1e1216-2d57-48ca-bd66-8395e3f1519c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>MVC stands for Model-View-Controller and is a software architecture pattern commonly used to develop software applications. Although originally designed for desktop computing, MVC has been widely adopted as a design for World Wide Web applications in major programming languages.</p>
<hr />
<p>The Model-View-Controller pattern was originally created in the late 1970s by Trygve Reenskaug, a Norwegian computer scientist, while he was working at Xerox PARC (Palo Alto Research Center). The MVC pattern was intended to help separate the concerns of the user interface design from the underlying application logic, making it easier to develop, test and maintain software.</p>
<p>Since then, the MVC pattern has become a widely used design pattern in software development and has been applied to many different types of applications and platforms, including web development, desktop applications, mobile apps, and more. Although there are several implementations of MVC, the most important point of the pattern remains the same - the division of responsibility.</p>
<p>There are other patterns similar to MVC, such as MVP (Model–View–Presenter) or MVVM (Model-View-ViewModel), but these are beyond the scope of this article. In this article, we will focus on a traditional MVC architecture for web applications.</p>
<p>If you have worked with frameworks like Laravel, Ruby on Rails, or Flask, you may already be familiar with the MVC architecture. It divides the program into three interrelated components:</p>
<ul>
<li><p>Model</p>
</li>
<li><p>View</p>
</li>
<li><p>Controller</p>
</li>
</ul>
<h3 id="heading-model">Model</h3>
<p>The Model often represents a table in an application's database and is responsible for reading and writing data, as well as persisting the application state.</p>
<p>In MVC, the Model is designed to be independent of the View and the Controller. It can be tested and developed separately from the other parts of the application.</p>
<h3 id="heading-view">View</h3>
<p>The View is responsible for displaying data to users and handling user interaction. In the traditional interpretation of the MVC pattern, the View should not communicate directly with the Model. The Controller should update the View after receiving information from the Model about any changes to the data.</p>
<p>However, in practice, direct access to the Model is not uncommon, for example in small or simple applications. While this approach can simplify development in some cases, it can also make code more difficult to maintain and test over time, as changes to the Model can break views that rely on it. It also violates the principle of separation of concerns, which can make the code less modular.</p>
<h3 id="heading-controller">Controller</h3>
<p>The Model and the View are connected together through controllers. The Controller is responsible for receiving and processing user input, manipulating the Model (fetching/creating/updating/deleting data), and updating the View (returning the appropriate response to be rendered).</p>
<h2 id="heading-visual-representation-of-mvc-for-a-web-app">Visual Representation of MVC for a Web App</h2>
<p>Below is a diagram of one possible take on the MVC pattern for a web application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677794202537/680b698c-b1c2-4ab5-9f3d-537097788b71.jpeg" alt class="image--center mx-auto" /></p>
<p>Let's take a closer look at what is happening here:</p>
<ol>
<li><p>A user enters a URL in a browser and sends a request to a web application to open a specific page, in our case <strong>https://website.com/pages</strong>. Similarly, a user can send other types of requests, for example, a POST request from a web page to create a new record in the database.</p>
</li>
<li><p>In order to know which page/response to show the user based on their request, the web application has a list of routes. Those are, essentially, URL patterns associated with different pages which the application tries to match with the requested URL. Routes are associated with controllers, or rather with a specific function inside the controller known as a controller action. If the application finds a matching route (<strong>/pages</strong> in our case), it invokes the route-related controller action. If the route is not found, the application returns a 404 error.</p>
</li>
<li><p>With help of the routes, the <strong>PagesController</strong> action is called and that controller receives the user's request. PagesController then goes to <strong>PageModel</strong> to retrieve the necessary data, in our case, a list of pages. In other cases, the Controller may ask the Model to create a new record or modify an existing one based on the user's request.</p>
</li>
<li><p>As discussed previously, the Model often represents a table in an application's database, in our case, PageModel is connected with the <strong>pages</strong> database table.</p>
</li>
<li><p>The Model makes a request to read or write data from the database. The database executes the specified command, in our case, it is fetching all pages from the pages table and returns the result (data) to PageModel.</p>
</li>
<li><p>PageModel returns the pages data to PagesController.</p>
</li>
<li><p>The Controller passes the data received from the Model to the View. Finally, the View renders the requested page using data received from the Controller. The View is the last page a user sees in their browser.</p>
</li>
</ol>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
<hr />
<h2 id="heading-source">Source</h2>
<ol>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">Model–view–controller - Wikipedia</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Trygve_Reenskaug">Trygve Reenskaug - Wikipedia</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The Difference Between Types (Type Aliases) And Interfaces in TypeScript]]></title><description><![CDATA[Today, more and more people and companies are using TypeScript. It is among the top 10 programming languages in the PYPL index. And this is not surprising, since TypeScript allows you to catch many errors at compile time, not at runtime, that is befo...]]></description><link>https://blog.savetchuk.com/the-difference-between-types-type-aliases-and-interfaces-in-typescript</link><guid isPermaLink="true">https://blog.savetchuk.com/the-difference-between-types-type-aliases-and-interfaces-in-typescript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Wed, 22 Feb 2023 01:42:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677016762080/b9fbed31-f117-44af-abfc-b5db13c599f4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, more and more people and companies are using TypeScript. It is among the top 10 programming languages in the <a target="_blank" href="https://pypl.github.io/PYPL.html">PYPL index</a>. And this is not surprising, since TypeScript allows you to catch many errors at compile time, not at runtime, that is before they are released to production.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676938186642/d03715cd-f8fa-45bf-a079-ee3b131fa70a.png" alt="Top 10 programming languages according to PYPL Index as of February 2023" class="image--center mx-auto" /></p>
<p><em>Top 10 programming languages according to PYPL Index as of February 2023.</em></p>
<p>Some of you who decide to try TypeScript might get confused with type aliases and interfaces because they are both similar and used to define the shape and structure of values in a statically typed way. This means that it is possible to describe the same object using a type alias or an interface:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Option #1: using a type alias</span>
<span class="hljs-keyword">type</span> Person = {
  firstName: <span class="hljs-built_in">string</span>;
  lastName: <span class="hljs-built_in">string</span>;
  age: <span class="hljs-built_in">number</span>;
};

<span class="hljs-comment">// Option #2: using an interface</span>
<span class="hljs-keyword">interface</span> Person {
  firstName: <span class="hljs-built_in">string</span>;
  lastName: <span class="hljs-built_in">string</span>,
  age: <span class="hljs-built_in">number</span>;
};
</code></pre>
<p>You might be asking yourself why we have two options for describing the <code>Person</code> object instead of one. And are there any differences or specific use cases between type aliases and interfaces? Yes, and you will find out about them in a moment.</p>
<p>Before we begin, I should mention that the correct term for a <strong>type</strong> is <strong>type alias</strong>, but for simplicity, I will use those two terms interchangeably.</p>
<h2 id="heading-difference-1-objects-and-functions">Difference #1: Objects and Functions</h2>
<p>Both types and interfaces can be used to describe the shape of an object or a function signature. However, the syntax is different. A type is defined using the <code>type</code> keyword, followed by the name, an equals sign and the type definition:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> SampleObject = {
  a: <span class="hljs-built_in">string</span>;
  b: <span class="hljs-built_in">string</span>;
};
</code></pre>
<p>An interface is defined using the <code>interface</code> keyword, followed by the name and the interface definition in curly braces:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> SampleObject {
  a: <span class="hljs-built_in">string</span>;
  b: <span class="hljs-built_in">string</span>;
};
</code></pre>
<p>As you can see, there is not much difference in syntax between the two examples. However, when we want to define a function signature, the difference becomes more noticeable:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Using the "type" keyword</span>
<span class="hljs-keyword">type</span> SampleFunction = <span class="hljs-function">(<span class="hljs-params">param1: <span class="hljs-built_in">string</span>, param2: <span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-built_in">boolean</span>;

<span class="hljs-comment">// Using the "interface" keyword</span>
<span class="hljs-keyword">interface</span> SampleFunction {
  (param1: <span class="hljs-built_in">string</span>, param2: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">boolean</span>;
}
</code></pre>
<p>In practice, either approach can be used to define a function in TypeScript, and the choice between them often comes down to personal preference or project standards.</p>
<h2 id="heading-difference-2-other-types">Difference #2: Other Types</h2>
<p><strong>Unlike an interface, the type alias can be used to create named types for all other types including:</strong></p>
<ul>
<li><p><strong>primitives</strong></p>
</li>
<li><p><strong>unions (union types)</strong></p>
</li>
<li><p><strong>tuples</strong></p>
</li>
<li><p><strong>mapped types</strong></p>
</li>
</ul>
<h3 id="heading-primitives">Primitives</h3>
<p>Just in case, I will remind you that there are six primitive types in JavaScript and TypeScript: boolean, number, string, null, undefined, and symbol. Here is an example of how to represent primitives in TypeScript using the <code>type</code> keyword:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Name = <span class="hljs-built_in">string</span>;
<span class="hljs-keyword">type</span> Age = <span class="hljs-built_in">number</span>;
<span class="hljs-keyword">type</span> IsStudent = <span class="hljs-built_in">boolean</span>;
</code></pre>
<p>With interfaces, you cannot directly define a named type for a primitive type.</p>
<h3 id="heading-unions">Unions</h3>
<p>A variable with a union type can hold a value of any of the constituent types. Union types can be formed by combining two or more other types, separated by a vertical bar (<code>|</code>).</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Example #1: union type that allows a variable to hold </span>
<span class="hljs-comment">// one of the three specified string literal values.</span>
<span class="hljs-keyword">type</span> SampleType1 = <span class="hljs-string">'Coffee'</span> | <span class="hljs-string">'Tea'</span> | <span class="hljs-string">'Water'</span>;

<span class="hljs-comment">// Example #2: union type that allows a variable to hold </span>
<span class="hljs-comment">// a value that is either a string or a number.</span>
<span class="hljs-keyword">type</span> SampleType2 = <span class="hljs-built_in">string</span> | <span class="hljs-built_in">number</span>;

<span class="hljs-comment">// Example #3: union type that allows a variable to hold</span>
<span class="hljs-comment">// any of the values that are allowed by SampleType1 or SampleType2</span>
<span class="hljs-keyword">type</span> SampleType = SampleType1 | SampleType2;
</code></pre>
<p>Same as with primitives, you cannot directly define a union type using the <code>interface</code> keyword, however, it is possible to have a union type as an object property:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> SampleObject {
  myProperty: <span class="hljs-built_in">string</span> | <span class="hljs-built_in">number</span>;
}
</code></pre>
<hr />
<p><strong>There are some limitations when using union types that you should be aware of:</strong></p>
<ul>
<li>An interface cannot extend a union type:</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> SampleUnionType = <span class="hljs-built_in">string</span> | <span class="hljs-built_in">number</span>;

<span class="hljs-comment">// The code below will not work</span>
<span class="hljs-keyword">interface</span> <span class="hljs-keyword">extends</span> SampleUnionType { ... }
</code></pre>
<ul>
<li>A class cannot implement a union type:</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> SampleUnionType = <span class="hljs-built_in">string</span> | <span class="hljs-built_in">number</span>;

<span class="hljs-comment">// The code below will not work</span>
<span class="hljs-keyword">class</span> SampleClass <span class="hljs-keyword">implements</span> SampleUnionType { ... }
</code></pre>
<p><em>A class can implement an interface or type alias, both in the same way. However, it can not implement a type alias that names a union type.</em></p>
<h3 id="heading-tuples">Tuples</h3>
<p>A tuple is a type that allows you to specify a fixed-length array of values where each element has a specific data type. Here is an example of how to create a type for an array with only two elements:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> PersonTuple = [<span class="hljs-built_in">string</span>, <span class="hljs-built_in">number</span>];

<span class="hljs-keyword">const</span> person: PersonTuple = [<span class="hljs-string">"John Doe"</span>, <span class="hljs-number">25</span>];
</code></pre>
<p>Even though this can be achieved using interfaces as shown below, you will lose access to all of the array methods. If you try to call <code>person.length</code> on the variable created from the interface, you will get the following error: Property 'length' does not exist on type 'PersonTuple'.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677008728128/b42df13b-0498-4e54-9c17-ed43f1e37869.png" alt class="image--center mx-auto" /></p>
<p>You will have to manually add those methods (length, push, concat, etc.) to the interface as shown below. However, this is not something you want to do. If you need a tuple, consider using a type alias.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// How to mimic array methods</span>
<span class="hljs-keyword">interface</span> PersonTuple
{
    <span class="hljs-number">0</span>: <span class="hljs-built_in">string</span>;
    <span class="hljs-number">1</span>: <span class="hljs-built_in">number</span>;
    length: <span class="hljs-number">2</span>;
}

<span class="hljs-keyword">const</span> person: PersonTuple = [<span class="hljs-string">"John Doe"</span>, <span class="hljs-number">25</span>];

<span class="hljs-built_in">console</span>.log(person.length); <span class="hljs-comment">// This will now work</span>
</code></pre>
<h3 id="heading-mapped-types">Mapped Types</h3>
<p>Mapped types allow you to transform an existing type into a new type by applying a mapping operation to each property of the original type.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> NewType = {
  [Property <span class="hljs-keyword">in</span> OldType]: MappingOperation;
}
</code></pre>
<p>Here, <code>OldType</code> is the original type that you want to transform, and <code>Property</code> represents each property in <code>OldType</code>. <code>MappingOperation</code> is a TypeScript type operator that defines how each property in <code>OldType</code> will be transformed.</p>
<p>In the example below we create a new type <code>B</code>, which has all the properties of <code>A</code>, but with each property made optional.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> B = {
  [Property <span class="hljs-keyword">in</span> keyof A]?: A[Property];
}
</code></pre>
<p><em>TypeScript does not currently support typing mapped types with interfaces.</em></p>
<h2 id="heading-difference-3-declaration-merging">Difference #3: Declaration Merging</h2>
<p>If you have two interfaces that you define with the same name in the same scope, they will be merged. Consider this example:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Declaring SampleType interface for the 1st time</span>
<span class="hljs-keyword">interface</span> SampleType {
  a: <span class="hljs-built_in">number</span>;
  b: <span class="hljs-built_in">number</span>;
};

<span class="hljs-comment">// Declaring SampleType interface for the 2nd time</span>
<span class="hljs-keyword">interface</span> SampleType {
  c: <span class="hljs-built_in">number</span>;
  d: <span class="hljs-built_in">number</span>;
};

<span class="hljs-comment">// The second interface declaration extends the first one by adding</span>
<span class="hljs-comment">// two new properties. Now SampleType has four properties: a, b, c, d</span>
<span class="hljs-keyword">const</span> sampleType: SampleType = {
  a: <span class="hljs-number">1</span>,
  b: <span class="hljs-number">2</span>,
  c: <span class="hljs-number">3</span>,
  d: <span class="hljs-number">4</span>,
};
</code></pre>
<p>We cannot do the same with types. This is important to consider if you are the author of a library and want your users to be able to extend its functionality by merging interfaces. It will allow them to combine their own type declarations with those provided by the library, effectively "extending" or "augmenting" the library's API.</p>
<h2 id="heading-difference-4-extention">Difference #4: Extention</h2>
<p>Interfaces can extend other interfaces using the <code>extends</code> keyword which allows for greater flexibility and modularity:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> Named {
  name: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">interface</span> Ageable {
  age: <span class="hljs-built_in">number</span>;
}

<span class="hljs-keyword">interface</span> Person <span class="hljs-keyword">extends</span> Named, Ageable {
  sayHello(): <span class="hljs-built_in">void</span>;
}
</code></pre>
<p>Types can also be extended using an intersection type. An intersection type combines multiple types into one. Consider this example:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Example #1</span>
<span class="hljs-keyword">type</span> A = { a: <span class="hljs-built_in">number</span> };
<span class="hljs-keyword">type</span> B = { b: <span class="hljs-built_in">number</span> };
<span class="hljs-keyword">type</span> C = A &amp; B;

<span class="hljs-keyword">const</span> c: C = { a: <span class="hljs-number">10</span>, b: <span class="hljs-number">20</span> };

<span class="hljs-comment">// Example #2</span>
<span class="hljs-keyword">type</span> A = { a: <span class="hljs-built_in">number</span> };
<span class="hljs-keyword">type</span> B = A &amp; { b: <span class="hljs-built_in">number</span> };

<span class="hljs-keyword">const</span> b: B = { a: <span class="hljs-number">10</span>, b: <span class="hljs-number">20</span> };
</code></pre>
<p>As you can see, the <code>&amp;</code> operator is used to create a new type by combining multiple existing types. The new type has all properties of the existing types.</p>
<hr />
<p>We can also mix them together as shown below. Interfaces and type aliases are not mutually exclusive. An interface can extend a type alias and vice versa.</p>
<ul>
<li>Interface extends another interface:</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> A { sampleProperty: <span class="hljs-built_in">number</span>; }
<span class="hljs-keyword">interface</span> B <span class="hljs-keyword">extends</span> A { sampleProperty: <span class="hljs-built_in">number</span>; }
</code></pre>
<ul>
<li>Interface extends a type alias:</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> A = { sampleProperty: <span class="hljs-built_in">number</span>; }
<span class="hljs-keyword">interface</span> B <span class="hljs-keyword">extends</span> A { sampleProperty: <span class="hljs-built_in">number</span>; }
</code></pre>
<ul>
<li>Type alias extends another type alias:</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> A = { sampleProperty: <span class="hljs-built_in">number</span>; };
<span class="hljs-keyword">type</span> B = A &amp; { sampleProperty: <span class="hljs-built_in">number</span>; };
</code></pre>
<ul>
<li>Type alias extends interface:</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> A { sampleProperty: <span class="hljs-built_in">number</span>; }
<span class="hljs-keyword">type</span> B = A &amp; { sampleProperty: <span class="hljs-built_in">number</span>; };
</code></pre>
<p>There are some limitations to what can be extended with interfaces. For example, primitive types, union types, classes, and enums, cannot be extended with interfaces.</p>
<h2 id="heading-what-should-i-use">What Should I Use?</h2>
<p><strong>In general, it is recommended to use interfaces for defining object shapes, and types for defining other types of values. However, it is up to you and your team to decide which option to use as long as you are consistent.</strong></p>
<p>For example, every object should be typed as an interface and everything else as a type. Or you can use interfaces or types for everything, but not both for values of the same type (e.g. types and interfaces for objects). Communication with your team and consistency are crucial for quality code.</p>
<p>Here is a good cheat sheet that I often refer to, however, it may differ for everyone:</p>
<p>When to use <code>type</code>:</p>
<ul>
<li><p>Use <code>type</code> when defining primitives</p>
</li>
<li><p>Use <code>type</code> when defining unions</p>
</li>
<li><p>Use <code>type</code> when defining tuples</p>
</li>
<li><p>Use <code>type</code> when defining functions</p>
</li>
<li><p>Use <code>type</code> when defining mapped types</p>
</li>
</ul>
<p>When to use <code>interface</code>:</p>
<ul>
<li><p>Use <code>interface</code> for all object types where using <code>type</code> is not required</p>
</li>
<li><p>Use <code>interface</code> when you want to take advantage of declaration merging</p>
</li>
</ul>
<h2 id="heading-keep-an-eye-on-the-changelog">Keep an Eye on the Changelog</h2>
<p>The limitations and differences described in this article are current as of February 2023. However, with new versions of TypeScript, they can change. It is important to keep an eye on the <a target="_blank" href="https://devblogs.microsoft.com/typescript/">release notes</a> to stay informed about new changes and features.</p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
<hr />
<h2 id="heading-source">Source</h2>
<ol>
<li><p><a target="_blank" href="https://pypl.github.io/PYPL.html">PYPL PopularitY of Programming Language</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/37233735/interfaces-vs-types-in-typescript/52682220">Interfaces vs Types in TypeScript - Stack Overflow</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html">TypeScript: Documentation - Everyday Types</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html">TypeScript: Documentation - Mapped Types</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Overview of String Conversion in JavaScript]]></title><description><![CDATA[When I started working with JavaScript many years ago, I learned that to convert a value to a string, I could use value.toString().
This method worked well and was sufficient to complete the tasks I had at the time. However, as I progressed and start...]]></description><link>https://blog.savetchuk.com/overview-of-string-conversion-in-javascript</link><guid isPermaLink="true">https://blog.savetchuk.com/overview-of-string-conversion-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Mon, 20 Feb 2023 04:04:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760200694780/86ebfefa-7342-4b9d-a17f-5d533642fd42.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I started working with JavaScript many years ago, I learned that to convert a value to a string, I could use <code>value.toString()</code>.</p>
<p>This method worked well and was sufficient to complete the tasks I had at the time. However, as I progressed and started collaborating with other developers, I discovered additional ways to convert a value to a string. Here’s the full list:</p>
<ul>
<li><p><code>value.toString()</code></p>
</li>
<li><p><code>value + ''</code> or <code>`${value}` </code></p>
</li>
<li><p><code>String(value)</code></p>
</li>
<li><p><code>JSON.stringify()</code></p>
</li>
</ul>
<p>I was surprised to learn that each of these approaches works slightly differently, and I think experienced developers should be aware of these differences. In this article, we’ll dive into how each method behaves so you can choose the one that best suits your needs.</p>
<h2 id="heading-option-1-valuetostring">Option #1: value.toString()</h2>
<p><code>value.toString()</code> is an explicit conversion to a string because you are directly calling a method to perform the conversion. This option works only if the value is an object that has a <code>toString()</code> method; otherwise, it will throw a <code>TypeError</code>. Here are some examples to illustrate the difference:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// The variables below are objects that have toString() method</span>
<span class="hljs-comment">// Primitive data types such as number and boolean are also objects</span>

<span class="hljs-keyword">const</span> a = <span class="hljs-number">50</span>;
<span class="hljs-keyword">const</span> b = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">const</span> c = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> d = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Andrew"</span> };

<span class="hljs-built_in">console</span>.log(a.toString()); <span class="hljs-comment">// =&gt; "50"</span>
<span class="hljs-built_in">console</span>.log(b.toString()); <span class="hljs-comment">// =&gt; "true"</span>
<span class="hljs-built_in">console</span>.log(c.toString()); <span class="hljs-comment">// =&gt; "1, 2, 3"</span>
<span class="hljs-built_in">console</span>.log(d.toString()); <span class="hljs-comment">// =&gt; "[object Object]"</span>

<span class="hljs-comment">// The variables below are not objects and do not have toString()</span>
<span class="hljs-comment">// method. Calling .toString() on them will result in TypeError</span>

<span class="hljs-keyword">const</span> e = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">const</span> f = <span class="hljs-literal">undefined</span>;

<span class="hljs-built_in">console</span>.log(e.toString()); 
<span class="hljs-comment">// TypeError: Cannot read properties of null (reading 'toString')</span>

<span class="hljs-built_in">console</span>.log(f.toString()); 
<span class="hljs-comment">// TypeError: Cannot read properties of undefined (reading 'toString')</span>
</code></pre>
<p>Good news: all standard objects in JavaScript - such as <code>Number</code>, <code>Array</code>, and <code>Function</code> have the <code>toString()</code> method implemented. It is used whenever an object needs to be represented as text (for example, in HTML) or whenever an object is implicitly converted to a string.</p>
<p><strong>The important thing to remember is that calling</strong> <code>value.toString()</code> <strong>on</strong> <code>null</code> <strong>or</strong> <code>undefined</code> <strong>will throw a</strong> <code>TypeError</code><strong>.</strong> This happens because these values are not objects and therefore do not have a <code>toString()</code> method.</p>
<p>You can also override the <code>toString()</code> method for your own objects or even for existing built-in objects. However, modifying built-in prototypes is generally discouraged, as it can cause unexpected behavior in other parts of your code or in third-party libraries.</p>
<h2 id="heading-option-2-stringvalue">Option #2: String(value)</h2>
<p><code>String(value)</code> is another explicit way to convert a value to a string using the String constructor. However, it works a bit differently than <code>value.toString()</code>. <strong>When you call</strong> <code>String(value)</code> <strong>on</strong> <code>null</code> <strong>or</strong> <code>undefined</code><strong>, it will return a string with</strong> <code>"null"</code> <strong>or</strong> <code>"undefined"</code> <strong>respectively.</strong> And this is the most important difference to remember.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> a = <span class="hljs-number">50</span>;
<span class="hljs-keyword">const</span> b = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">const</span> c = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> d = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Andrew"</span> };

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(a)); <span class="hljs-comment">// =&gt; "50"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(b)); <span class="hljs-comment">// =&gt; "true"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(c)); <span class="hljs-comment">// =&gt; "1, 2, 3"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(d)); <span class="hljs-comment">// =&gt; "[object Object]"</span>

<span class="hljs-comment">// Note that we do not get a TypeError </span>
<span class="hljs-comment">// when calling String() on null or undefined</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(<span class="hljs-literal">null</span>));      <span class="hljs-comment">// =&gt; "null"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(<span class="hljs-literal">undefined</span>)); <span class="hljs-comment">// =&gt; "undefined'</span>
</code></pre>
<p><strong>One important thing to note:</strong> since String is a constructor, it is possible to call it with the <code>new</code> keyword - <code>new String(value)</code>. <strong>You should rarely use it this way.</strong></p>
<p>When <code>String</code> is called as a function, it coerces the parameter to a string primitive. However, when <code>String</code> is called as a constructor (with <code>new</code>), it creates a String object, which is not a primitive. This produces different results:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> a = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">"Hello from 2023!"</span>);
<span class="hljs-keyword">const</span> b = <span class="hljs-built_in">String</span>(<span class="hljs-string">"Hello from 2023!"</span>);

<span class="hljs-built_in">console</span>.log(a); <span class="hljs-comment">// =&gt; String {"Hello, 2023!"}</span>
<span class="hljs-built_in">console</span>.log(b); <span class="hljs-comment">// =&gt; "Hello, 2023!"</span>

<span class="hljs-built_in">console</span>.log(a === <span class="hljs-string">'Hello from 2023!'</span>); <span class="hljs-comment">// =&gt; false</span>
<span class="hljs-built_in">console</span>.log(b === <span class="hljs-string">'Hello from 2023!'</span>); <span class="hljs-comment">// =&gt; true</span>

<span class="hljs-built_in">console</span>.log(a <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">String</span>); <span class="hljs-comment">// =&gt; true</span>
<span class="hljs-built_in">console</span>.log(b <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">String</span>); <span class="hljs-comment">// =&gt; false</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span> a); <span class="hljs-comment">// =&gt; "object"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span> b); <span class="hljs-comment">// =&gt; "string"</span>
</code></pre>
<h2 id="heading-option-3-value-or-value">Option #3: value + "" or `${value}`</h2>
<p>When you concatenate a string with any other value, JavaScript will automatically convert the other value to a string. This is an implicit way to convert a value to a string because the <code>+</code> operator is not specifically designed for string conversion. Instead, it is a general-purpose operator that can be used for addition or string concatenation, depending on the types of the operands.</p>
<p>When you try to convert <code>null</code> or <code>undefined</code> to string, it will not result in TypeError:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> a = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">const</span> b = <span class="hljs-literal">undefined</span>;

<span class="hljs-built_in">console</span>.log(a + <span class="hljs-string">""</span>); <span class="hljs-comment">// =&gt; "null"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${a}</span>`</span>); <span class="hljs-comment">// =&gt; "null"</span>

<span class="hljs-built_in">console</span>.log(b + <span class="hljs-string">""</span>); <span class="hljs-comment">// =&gt; "undefined"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${b}</span>`</span>); <span class="hljs-comment">// =&gt; "undefined"</span>
</code></pre>
<p>However, I am not a big fan of using this method because it involves implicit string conversion and it can be difficult for other developers unfamiliar with JavaScript to understand how the code works at the first glance.</p>
<p>Whenever possible, I prefer to use <code>String(value)</code> or <code>JSON.stringify(value)</code> (comes next in the article), which are explicit conversions that do not throw a TypeError when calling on <code>null</code> or <code>undefined</code>.</p>
<h2 id="heading-option-4-jsonstringifyvalue">Option #4: <strong>JSON.stringify(value)</strong></h2>
<p>This method is particularly useful for converting objects and arrays to JSON strings because it can handle nested objects and arrays. Remember what we got when we called <code>value.toString()</code> or <code>String(value)</code> on array or objects?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> a = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> b = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Andrew"</span> };

<span class="hljs-built_in">console</span>.log(a.toString()); <span class="hljs-comment">// =&gt; "1,2,3"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(a)); <span class="hljs-comment">// =&gt; "1,2,3"</span>

<span class="hljs-built_in">console</span>.log(b.toString()); <span class="hljs-comment">// =&gt; "[object Object]"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(b)); <span class="hljs-comment">// =&gt; "[object Object]"</span>
</code></pre>
<p>This is not the case with <code>JSON.stringify()</code>, consider this example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> a = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> b = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Andrew"</span> };

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(a)); <span class="hljs-comment">// =&gt; "[1,2,3]"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(b)); <span class="hljs-comment">// =&gt; '{"name":"Andrew"}'</span>
</code></pre>
<p>As you can see, when we call <code>JSON.stringify()</code> on arrays, we get a valid JSON array as a string, and when we call <code>JSON.stringify()</code> on objects, we get a valid JSON object as a string. This also works when we have nested arrays or objects:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> a = [ [<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>], <span class="hljs-number">5</span> ];
<span class="hljs-keyword">const</span> b = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Andrew"</span>, <span class="hljs-attr">skills</span>: [ <span class="hljs-string">"JavaScript"</span>, <span class="hljs-string">"TypeScript"</span> ] };

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(a)); <span class="hljs-comment">// =&gt; '[["a","b"],5]'</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(b)); <span class="hljs-comment">// =&gt; '{"name":"Andrew","skills":["JavaScript","TypeScript"]}'</span>
</code></pre>
<p>Calling <code>JSON.stringify()</code> on <code>null</code> or <code>undefined</code> works the same as with <code>String()</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(<span class="hljs-literal">null</span>)); <span class="hljs-comment">// =&gt; "null"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(<span class="hljs-literal">undefined</span>)); <span class="hljs-comment">// =&gt; "undefined"</span>
</code></pre>
<p><code>JSON.stringify()</code> is a more complex method than the previous ones, and in addition to the value to be converted to a string, it also takes two optional parameters: <code>placeholder</code> and <code>space</code>. Refer to the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">MDN Docs</a> if you want to learn more.</p>
<h2 id="heading-converting-dates-to-string">Converting Dates to String</h2>
<p>When we try to convert JavaScript dates to a string, the first three options work the same, while <code>JSON.stringify()</code> gives a different result. Consider this example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-number">2023</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(date)); 
<span class="hljs-comment">// =&gt; "Sun Jan 01 2023 10:00:00 GMT-0500 (Eastern Standard Time)"</span>

<span class="hljs-built_in">console</span>.log(date.toString()); 
<span class="hljs-comment">// =&gt; "Sun Jan 01 2023 10:00:00 GMT-0500 (Eastern Standard Time)"</span>

<span class="hljs-built_in">console</span>.log(date + <span class="hljs-string">""</span>); 
<span class="hljs-comment">// =&gt; "Sun Jan 01 2023 10:00:00 GMT-0500 (Eastern Standard Time)"</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(date)); 
<span class="hljs-comment">// =&gt; '"2023-01-01T15:00:00.000Z"'</span>
</code></pre>
<p>In this case, <code>JSON.stringify()</code> returns the date in ISO simplified extended format (ISO 8601). This is because the date object we pass to <code>JSON.stringify()</code> method implements the <code>toJSON()</code> method which returns a string (the same as <code>date.toISOString()</code>).</p>
<h2 id="heading-always-consider-performance">Always Consider Performance</h2>
<p>Now, you may be tempted to use <code>JSON.stringify()</code> all the time as it offers the most complete conversion. However, you should know that <code>String()</code> is likely to be faster than <code>JSON.stringify()</code> because it is a simpler operation that does not involve parsing or formatting the input value as a JSON string.</p>
<p><code>String()</code> simply converts the input value to a string using a simple set of rules, as we discussed earlier. This operation is generally fast and efficient, especially for primitive values.</p>
<p>On the other hand, <code>JSON.stringify()</code> is a more complex operation that involves parsing the input value and generating a JSON string that represents the object in a standardized format. Depending on the size and complexity of the input value, this operation can be relatively slow and resource intensive.</p>
<p>Even though the performance difference may not be significant, I strongly recommend choosing the right method wisely: if you do not need a JSON string in a standardized format, use <code>String(value)</code> or <code>value.toString()</code>, otherwise, use <code>JSON. stringify(value)</code>.</p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
<hr />
<h2 id="heading-source">Source</h2>
<ol>
<li><p><a target="_blank" href="https://www.w3schools.com/jsref/jsref_object_tostring.asp">JavaScript Object toString() Method - W3Schools</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/String">String() Constructor - MDN Docs</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">JSON.stringify() - MDN Docs</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The Difference Between Docker Images and  Docker Containers]]></title><description><![CDATA[If you are new to learning and working with Docker, you might be wondering how Docker images differ from Docker containers. Without further ado, let's dive into it.
Both Images and Containers are two distinct concepts in the Docker ecosystem and we n...]]></description><link>https://blog.savetchuk.com/the-difference-between-docker-images-and-docker-containers</link><guid isPermaLink="true">https://blog.savetchuk.com/the-difference-between-docker-images-and-docker-containers</guid><category><![CDATA[Docker]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Sat, 18 Feb 2023 03:53:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676690543483/c88f1a71-1203-4bb5-9940-690a4b1ab0be.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are new to learning and working with Docker, you might be wondering how Docker images differ from Docker containers. Without further ado, let's dive into it.</p>
<p>Both Images and Containers are two distinct concepts in the Docker ecosystem and we need them both in order to work with Docker.</p>
<h2 id="heading-docker-containers">Docker Containers</h2>
<p>Docker containers are small packages that contain our application and the environment required to run it (system tools, libraries, settings, etc). We can think of containers as running/executable units of software, the units we run locally, on servers and cloud providers in order to start our application.</p>
<h2 id="heading-docker-images">Docker Images</h2>
<p>Docker images are read-only templates of Docker containers. In order to create a Docker Container, we need a template or blueprint which is a Docker Image. Therefore, containers are dependent on images and use them to construct a run-time environment and run an application.</p>
<p>Docker images are typically built using a Dockerfile, which is a script that specifies the instructions for building the image. Docker images are stored in a registry and can be shared and reused by other users.</p>
<p>We can run multiple containers from the same image as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676692289080/b17018fa-79ce-461b-8afc-eb417fbaa48b.png" alt class="image--center mx-auto" /></p>
<p>It is also worth mentioning that we can create Docker images based on other Docker images and this is often referred to as "layering" Docker images. The newly created Docker image inherits all the files and settings from the parent image, and we can add new files, dependencies, and configurations as needed.</p>
<h2 id="heading-summary">Summary</h2>
<ul>
<li><p>A Docker image is a read-only template or snapshot of a Docker container.</p>
</li>
<li><p>A Docker container is a runnable instance of a Docker image.</p>
</li>
<li><p>Images contain applications code, meanwhile, containers run it.</p>
</li>
<li><p>We can use one image to create multiple containers on different servers.</p>
<hr />
<p>  I hope you found this information helpful, stay tuned for more content! :)</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Add TypeScript to Existing Next.js Project]]></title><description><![CDATA[It is becoming increasingly common to use TypeScript with JavaScript frameworks such as React, Vue or Express. I have my personal website built on Next.js which is a framework for building React applications with nice features such as server-side ren...]]></description><link>https://blog.savetchuk.com/how-to-add-typescript-to-existing-nextjs-project</link><guid isPermaLink="true">https://blog.savetchuk.com/how-to-add-typescript-to-existing-nextjs-project</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Thu, 16 Feb 2023 17:37:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676577849399/6f15c671-cec2-4b39-ab7e-67434ef1de48.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is becoming increasingly common to use TypeScript with JavaScript frameworks such as React, Vue or Express. I have my personal website built on Next.js which is a framework for building React applications with nice features such as server-side rendering, automatic code splitting, and optimized performance. One of my 2023 resolutions was to work more with TypeScript, so I decided to add it to my current website and document the whole process.</p>
<p><strong>Note:</strong> It is possible to add TypeScript during the initialization phase of the project, but this article is intended for those who already have Next.js projects and want to add TypeScript to them.</p>
<h2 id="heading-to-add-typescript-to-an-existing-nextjs-project-you-can-follow-these-steps">To Add Typescript to an Existing Next.js Project, You Can Follow These Steps:</h2>
<h3 id="heading-step-1-of-7">Step 1 of 7</h3>
<p>Install the necessary dependencies by running the following command in your project's root directory:</p>
<pre><code class="lang-bash">npm install -D typescript @types/react @types/react-dom @types/node
</code></pre>
<p>This will install the TypeScript compiler and the necessary type definitions for React and Node.js.</p>
<h3 id="heading-step-2-of-7">Step 2 of 7</h3>
<p>Rename the existing <code>jsconfig.json</code> to <code>tsconfig.json</code>, or create a new <code>tsconfig.json</code> if the former file does not exist. Now we need to update the contents of the file to include TypeScript-specific configuration options. Merge your configuration with the code below if required:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"compilerOptions"</span>: {
    <span class="hljs-attr">"target"</span>: <span class="hljs-string">"es5"</span>,
    <span class="hljs-attr">"lib"</span>: [<span class="hljs-string">"dom"</span>, <span class="hljs-string">"dom.iterable"</span>, <span class="hljs-string">"esnext"</span>],
    <span class="hljs-attr">"allowJs"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"skipLibCheck"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"strict"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"forceConsistentCasingInFileNames"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"noEmit"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"esModuleInterop"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"module"</span>: <span class="hljs-string">"esnext"</span>,
    <span class="hljs-attr">"moduleResolution"</span>: <span class="hljs-string">"node"</span>,
    <span class="hljs-attr">"resolveJsonModule"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"isolatedModules"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"jsx"</span>: <span class="hljs-string">"preserve"</span>,
    <span class="hljs-attr">"incremental"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"baseUrl"</span>: <span class="hljs-string">"."</span>,
    <span class="hljs-attr">"paths"</span>: {
      <span class="hljs-attr">"@/components/*"</span>: [<span class="hljs-string">"components/*"</span>],
      <span class="hljs-attr">"@/pages/*"</span>: [<span class="hljs-string">"pages/*"</span>]
    }
  },
  <span class="hljs-attr">"include"</span>: [<span class="hljs-string">"next-env.d.ts"</span>, <span class="hljs-string">"**/*.ts"</span>, <span class="hljs-string">"**/*.tsx"</span>],
  <span class="hljs-attr">"exclude"</span>: [<span class="hljs-string">"node_modules"</span>]
}
</code></pre>
<h3 id="heading-step-3-of-7">Step 3 of 7</h3>
<p>Update <code>next.config.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('next').NextConfig}</span> </span>*/</span>
<span class="hljs-keyword">const</span> nextConfig = {
  <span class="hljs-attr">i18n</span>: {
    <span class="hljs-attr">defaultLocale</span>: <span class="hljs-string">'en'</span>,
    <span class="hljs-attr">locales</span>: [<span class="hljs-string">'en'</span>],
  },
  <span class="hljs-attr">reactStrictMode</span>: <span class="hljs-literal">true</span>,
};

<span class="hljs-built_in">module</span>.exports = nextConfig;
</code></pre>
<h3 id="heading-step-4-of-7">Step 4 of 7</h3>
<p>Rename any existing <code>.js</code> files to <code>.ts</code> or <code>.tsx</code>, depending on whether the file contains JSX or not. For example, if you have a file called <code>pages/index.js</code>, rename it to <code>pages/index.tsx</code>.</p>
<p>You can also rename your existing directories such as <code>pages</code> or <code>components</code> to <code>pages-old</code> and <code>components-old</code> and create new empty directories with TypeScript files in case you need to reference the original files later.</p>
<h3 id="heading-step-5-of-7">Step 5 of 7</h3>
<p>Update any files that import other files to use the <code>.ts</code> or <code>.tsx</code> extension. For example, if you have a file called <code>index.ts</code> that imports a file called <code>header.js</code>, update the import statement in <code>index.ts</code> to use the <code>.ts</code> or <code>.tsx</code> extension like so: <code>import Header from './header.tsx';</code></p>
<h3 id="heading-step-6-of-7">Step 6 of 7</h3>
<p>Covert your JavaScript code into TypeScript code. Here is an example of how to convert <code>pages/_app.js</code> <em>to</em> <code>pages/_app.tsx</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">'normalize.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@/styles/index.scss'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyApp;
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-string">'normalize.css'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@/styles/index.scss'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { AppProps } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/app'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params">{ Component, pageProps }: AppProps</span>) </span>{
  <span class="hljs-keyword">return</span> &lt;Component {...pageProps} /&gt;;
}
</code></pre>
<h3 id="heading-step-7-of-7">Step 7 of 7</h3>
<p>Restart your development server by running <code>npm run dev</code>, and your TypeScript code should now be compiled and running alongside your React code.</p>
<p><strong>Note:</strong> you may need to adjust some of these steps depending on the specific structure of your project. However, these steps should be a good starting point for most projects.</p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
]]></content:encoded></item><item><title><![CDATA[ChatGPT Is Still Not Good Enough]]></title><description><![CDATA[Some people have told me that they fear that ChatGPT (and AI in general) will take over the developer's jobs. I honestly do not see how this can happen (at least in the next 5-10 years) and I believe that AI tools are only tools that can help develop...]]></description><link>https://blog.savetchuk.com/chatgpt-is-still-not-good-enough</link><guid isPermaLink="true">https://blog.savetchuk.com/chatgpt-is-still-not-good-enough</guid><category><![CDATA[chatgpt]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Thu, 09 Feb 2023 21:40:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679026380618/310bbf7e-6839-4de0-8497-fd23aea80262.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Some people have told me that they fear that ChatGPT (and AI in general) will take over the developer's jobs. I honestly do not see how this can happen (at least in the next 5-10 years) and I believe that AI tools are only tools that can help developers work more efficiently. Can it change in the future? Sure, but it will not happen soon.</p>
<p>Whenever I hear that ChatGPT is going to take someone's place, I encourage people to try actively using ChatGPT for at least a week. I do use it more often than Google, and while it helps to find the right information without annoying ads, it still often gives me incorrect answers to simple questions.</p>
<p>For example, here is me asking ChatGPT how to add a multi-select option to Choices.js (a JavaScript library I use in a Laravel project to make custom selectors).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675977753553/1ac757e3-59e3-4c72-a8b0-eb3f20c3e0c7.jpeg" alt="Example of incorrect response from ChatGPT" class="image--center mx-auto" /></p>
<p>As you can see, ChatGPT suggested that I should add <code>multiple: true</code> to the configuration object. I tried and it did not work. Instead, I decided to add the <code>multiple</code> property to the HTML tag itself and it did the trick (<code>&lt;select multiple...&gt;</code>).</p>
<p>Next, I wanted to be able to unselect some previously selected options, but the "X" button I expected to see did not appear. So I asked ChatGPT again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675977993514/7c632e7d-07e0-46b8-a697-e3cd0c5498a4.jpeg" alt="Example of incorrect response from ChatGPT 2" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675978016985/868352fd-c06d-4db3-8a00-fc3db38da931.jpeg" alt="Example of incorrect response from ChatGPT 3" class="image--center mx-auto" /></p>
<p>As with the previous question, this time I got the wrong answer again. Even though the given piece of code is complete and works, it is not the piece I asked for.</p>
<p>Let's see one more example when ChatGPT gave me the correct answer, but in my opinion, the answer could be a bit better.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675978158818/adae9f3a-8caf-4260-a577-e95e3affbe49.jpeg" alt="Example of correct response from ChatGPT" class="image--center mx-auto" /></p>
<p>I asked ChatGPT to instantiate the date in Laravel, add 30 days to it, and display it in the following format: 13/2/2023. The code ChatGPT gave me this time was correct, however, Laravel has a <code>now()</code> helper that you can use instead of <code>Carbon\Carbon::now()</code> which I think makes your code cleaner. If I did not know about the shorthand, I would have had to write more code. It would be great if AI tools like ChatGPT offered you multiple solutions and explained the benefits and differences of each.</p>
<p>As of 2023, ChatGPT is pretty much the same tool as Google or StackOverflow, but without the ads (I wonder how long it will stay this way though). I do realize that the model will learn and grow over time, but I wonder if it could keep up with the latest technology trends in the future. For now, it works just well, periodically giving wrong responses, but still not good enough to give up other tools such as old but good StackOverflow.</p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
]]></content:encoded></item><item><title><![CDATA[How to Find Large Files  in an AWS S3 Bucket Using Command Line Interface]]></title><description><![CDATA[I recently struggled to find the right command to search for large files in an AWS S3 bucket and spent many hours researching this topic. I am new to Amazon CloudShell, so I had to ask the community for help, and I even created an account on AWS re:P...]]></description><link>https://blog.savetchuk.com/how-to-find-large-files-in-an-aws-s3-bucket-using-command-line-interface</link><guid isPermaLink="true">https://blog.savetchuk.com/how-to-find-large-files-in-an-aws-s3-bucket-using-command-line-interface</guid><category><![CDATA[AWS]]></category><category><![CDATA[Amazon S3]]></category><category><![CDATA[AWS s3]]></category><category><![CDATA[Amazon Web Services]]></category><category><![CDATA[aws cli]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Fri, 20 Jan 2023 00:00:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676694409367/2058a642-99ba-4895-bc6e-68241db565b6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently struggled to find the right command to search for large files in an AWS S3 bucket and spent many hours researching this topic. I am new to Amazon CloudShell, so I had to ask the community for help, and I even created an account on AWS <a target="_blank" href="https://repost.aws">re:Post</a> (aka the StackOverflow alternative for Amazon Web Services). Although I recommend using it if you need help with AWS, due to the small number of users on re:Post you can usually get help faster on StackOverflow. In my opinion, if you have a question, it is better to ask on both platforms.</p>
<h2 id="heading-finding-files-using-aws-cloudshell">Finding Files using AWS CloudShell</h2>
<p>For this example, I have chosen Amazon CloudShell as the easiest tool to use with the AWS CLI that does not require any software to be installed on your computer. You can use any other tool you like.</p>
<p>To find the N most recent largest files in an AWS S3 bucket, you need to open <a target="_blank" href="http://console.aws.amazon.com">console.aws.amazon.com</a> and find CloudShell (I recommend adding it to your favourites in case you need to use it again).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674162333577/e3be9148-b230-4680-b4dd-8477b8f2d5cb.png" alt class="image--center mx-auto" /></p>
<p>Before running the command you need to know your S3 bucket name. When you have it ready, you can use the command below to find files:</p>
<pre><code class="lang-bash">aws s3api list-objects-v2 --bucket BUCKETNAME --query <span class="hljs-string">'sort_by(Contents[?LastModified&gt;=`2023-01-01`], &amp;Size)[-5:]'</span>
</code></pre>
<p>Replace <code>BUCKETNAME</code> with your S3 bucket name and change the date (<code>2023-01-01</code>) as needed. After running the command, your output should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674162592716/62704586-5e03-45af-974d-2e8256e90174.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-ignore-lastmodified-property">Ignore LastModified Property</h2>
<p>If you want to find the last N files regardless of the LastModified property, you can configure your command like this:</p>
<pre><code class="lang-bash">aws s3api list-objects-v2 --bucket BUCKETNAME --query <span class="hljs-string">'sort_by(Contents, &amp;Size)[-5:]'</span>
</code></pre>
<h2 id="heading-adjusting-the-number-of-files">Adjusting the Number of Files</h2>
<p>You can adjust the number of files to be returned by changing the number in the square brackets (<code>[-5:]</code>), or you can remove the square brackets with the contents inside to display all files sorted by size. Be careful to run such a command on a large bucket though, as it can take minutes to perform the operation (I did it once...).</p>
<h2 id="heading-bonus-command">Bonus Command</h2>
<p>There is another command that I rarely use but thought it would be useful to share.</p>
<pre><code class="lang-bash">aws s3 ls --summarize --human-readable --recursive s3://BUCKETNAME
</code></pre>
<p>This command will display all files in the bucket in a compact form with LastModified, Size and Name properties. If you have ever run the <code>ls</code> command on a Linux/Unix operating system before, you know what to expect.</p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
]]></content:encoded></item><item><title><![CDATA[What Is PHP CS Fixer and How It Can Help You Keep Your Code Cleaner]]></title><description><![CDATA[What is PHP CS Fixer​
PHP CS Fixer stands for PHP Coding Standards Fixer. This is a tool that fixes your code to follow standards. There are various PHP coding standards that you can follow, such as the popular PSR-1, and PSR-12 published by the PHP ...]]></description><link>https://blog.savetchuk.com/what-is-php-cs-fixer-and-how-it-can-help-you-keep-your-code-cleaner</link><guid isPermaLink="true">https://blog.savetchuk.com/what-is-php-cs-fixer-and-how-it-can-help-you-keep-your-code-cleaner</guid><category><![CDATA[PHP]]></category><category><![CDATA[tools]]></category><category><![CDATA[clean code]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Thu, 05 May 2022 09:24:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676578312336/df20a977-95d5-4d19-9e99-29be17624326.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-php-cs-fixer">What is PHP CS Fixer​</h2>
<p>PHP CS Fixer stands for <strong>PHP Coding Standards Fixer</strong>. This is a tool that fixes your code to follow standards. There are various PHP coding standards that you can follow, such as the popular <a target="_blank" href="https://www.php-fig.org/psr/psr-1/">PSR-1,</a> and <a target="_blank" href="https://www.php-fig.org/psr/psr-12/">PSR-12</a> published by the PHP Framework Interoperability Group (the full list of PSR standards can be found <a target="_blank" href="https://www.php-fig.org/psr/">here</a>).</p>
<p>There are also other community-driven standards like the <a target="_blank" href="https://symfony.com/doc/current/contributing/code/standards.html">Symphony</a>.</p>
<p>With PHP CS Fixer, you can follow multiple coding standards at once, or you can also define your own or your team's own coding standard through configuration. If you have ever worked with JavaScript and Eslint in particular, think of PHP CS Fixer as an alternative to Eslint for PHP.</p>
<p>Manually fixing coding standards in your code is a very tedious process, so PHP CS Fixer is a great solution. It helps you and your team ensure that you all follow the same rules when writing code, thus keeping it cleaner.</p>
<h2 id="heading-installation">Installation​</h2>
<p>The recommended way to install PHP CS Fixer is to use <a target="_blank" href="https://getcomposer.org/download/">Composer</a> in a dedicated directory in your project, for example in the <code>tools/php-cs-fixer</code>.</p>
<pre><code class="lang-bash">mkdir --parents tools/php-cs-fixer
composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer
</code></pre>
<p>For more details and other installation methods, see <a target="_blank" href="https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/installation.rst">installation instructions</a>.</p>
<h2 id="heading-usage">Usage</h2>
<h3 id="heading-usage-option-1">Usage: Option 1​</h3>
<p>Assuming you installed PHP CS Fixer as instructed above, you can run the following command to fix the files PHP files in the <code>src</code> directory:</p>
<pre><code class="lang-bash">tools/php-cs-fixer/vendor/bin/php-cs-fixer fix src
</code></pre>
<p>See <a target="_blank" href="https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/usage.rst">usage</a>, list of <a target="_blank" href="https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/rules/index.rst">built-in rules</a>, list of <a target="_blank" href="https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/ruleSets/index.rst">rule sets</a>, and <a target="_blank" href="https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/config.rst">configuration file</a> documentation for more details. If you need to apply code styles that are not supported by the tool, you can <a target="_blank" href="https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/custom_rules.rst">create custom rules</a>.</p>
<h3 id="heading-usage-option-2-editor-integration">Usage: Option 2 (Editor Integration)​</h3>
<p>However, executing a command manually does not seem to be a convenient approach. I personally prefer to run PHP CS Fixer by pressing a pre-configured keyboard shortcut in PHP Storm.</p>
<p>You can configure PHP CS Fixer for various code editors as described below:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/Glavin001/atom-beautify">Atom</a></p>
</li>
<li><p><a target="_blank" href="https://plugins.netbeans.apache.org/catalogue/?id=36">NetBeans</a></p>
</li>
<li><p><a target="_blank" href="https://www.jetbrains.com/help/phpstorm/using-php-cs-fixer.html">PhpStorm</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/benmatselby/sublime-phpcs">Sublime Text</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/stephpy/vim-php-cs-fixer">Vim</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/junstyle/vscode-php-cs-fixer">VS Code</a></p>
</li>
</ul>
<h3 id="heading-usage-option-3-run-php-cs-fixer-on-every-commit">Usage: Option 3 (Run PHP CS Fixer on every commit)​</h3>
<p>As an alternative option, you can fix your code on every commit using <a target="_blank" href="https://www.npmjs.com/package/husky">Husky</a> and <a target="_blank" href="https://www.npmjs.com/package/lint-staged">lint-staged</a>. Using these tools PHP CS Fixer will run on your staged files, in other words, on the files you want to commit. <a target="_blank" href="https://sebastiandedeyne.com/running-php-cs-fixer-on-every-commit-with-husky-and-lint-staged/">Here is a great article</a> explaining how to set up these tools to work with PHP CS Fixer.</p>
<h2 id="heading-easy-way-of-configuring-php-cs-fixer">Easy way of configuring PHP CS Fixer​</h2>
<p>If you are new to PHP Coding Standards and want to quickly configure PHP CS Fixer, I highly recommend using <a target="_blank" href="https://mlocati.github.io/php-cs-fixer-configurator/">PHP CS Fixer Configurator</a> by <a target="_blank" href="https://github.com/mlocati">Michele Locati</a>. It has a pre-defined set of rules that you can select and create your own configuration.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651742353193/rXNpYXhtE.png" alt="Screen Shot 2022-05-05 at 11.57.28 AM.png" /></p>
<p>Most rules, when clicked, will display general information about the rule, available configuration options, and usage examples. The PHP CS Fixer configuration file generated by this tool can be exported to use in your project and then imported again in case you want to do some modifications.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651742385573/Kq-Ttr1zi.png" alt="Screen Shot 2022-05-05 at 11.57.45 AM.png" /></p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
<hr />
<h2 id="heading-source">Source</h2>
<ol>
<li><p><a target="_blank" href="https://github.com/FriendsOfPHP/PHP-CS-Fixer">FriendsOfPHP/PHP-CS-Fixer: A tool to automatically fix PHP Coding Standards issues</a></p>
</li>
<li><p><a target="_blank" href="https://mlocati.github.io/php-cs-fixer-configurator/">PHP-CS-Fixer Configurator</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[What Are Idempotent HTTP Methods?]]></title><description><![CDATA[Idempotent HTTP methods​
An idempotent HTTP method is a method that can be called multiple times with the same input and produce the same result, without changing the state of the server.
Idempotency essentially means that the result of a successfull...]]></description><link>https://blog.savetchuk.com/what-are-idempotent-http-methods</link><guid isPermaLink="true">https://blog.savetchuk.com/what-are-idempotent-http-methods</guid><category><![CDATA[backend]]></category><category><![CDATA[APIs]]></category><category><![CDATA[http]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Mon, 25 Apr 2022 08:43:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676579186847/1bb60e90-c0fd-4414-b314-c3c97d45da86.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-idempotent-http-methods">Idempotent HTTP methods​</h2>
<p>An idempotent HTTP method is a method that can be called multiple times with the same input and produce the same result, without changing the state of the server.</p>
<p>Idempotency essentially means that the result of a successfully performed request does not depend on the amount of its execution. For example, in arithmetic, adding zero to a number is an idempotent operation.</p>
<h2 id="heading-why-do-we-need-idempotency">Why do we need Idempotency?​</h2>
<p>API consumers can make mistakes and write the client code in such a way that there can be duplicate requests coming to the API. Idempotency is needed to make APIs fault-tolerant so that duplicated requests do not leave the system unstable.</p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
]]></content:encoded></item><item><title><![CDATA[The Difference Between Design Patterns and Design Principles]]></title><description><![CDATA[Design patterns and design principles are both important concepts in software engineering, but they refer to different things.
Design Patterns
Design Patterns are techniques for how to design and architect your code. They are reusable low-level solut...]]></description><link>https://blog.savetchuk.com/the-difference-between-design-patterns-and-design-principles</link><guid isPermaLink="true">https://blog.savetchuk.com/the-difference-between-design-patterns-and-design-principles</guid><category><![CDATA[design patterns]]></category><category><![CDATA[design principles]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Mon, 11 Apr 2022 19:25:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676581983395/67575cd3-c220-47e8-807c-6e64a68467e9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Design patterns and design principles are both important concepts in software engineering, but they refer to different things.</p>
<h2 id="heading-design-patterns">Design Patterns</h2>
<p>Design Patterns are techniques for how to design and architect your code. They are reusable low-level solutions to commonly occurring software design problems, so instead of inventing the wheel, we follow design patterns that are well-proven, tested by others, and safe to follow.</p>
<p>Each design pattern has a different use case and applies to a different scenario, they are also typically specific to a programming language or technology and often provide implementation details.</p>
<p><strong>Examples of Design Patterns:</strong></p>
<ul>
<li><p>Adapter Pattern (converts the interface of a class into another interface that clients expect, allowing classes to work together)</p>
</li>
<li><p><a target="_blank" href="https://blog.savetchuk.com/overview-of-the-active-record-pattern">Active Record Pattern</a> (a database table or view is wrapped into a class)</p>
</li>
<li><p>MVC Pattern (separates application's logic into three interconnected components: the Model, the View, and the Controller)</p>
</li>
<li><p>Singleton Pattern (one class can only have one instance at a time)</p>
</li>
</ul>
<h2 id="heading-design-principles">Design Principles</h2>
<p>Design principles, on the other hand, are general (high-level) guidelines that help inform good software design to ensure scalable software architecture and mastery. In most cases, you need to follow them to have quality code. They are more abstract and less prescriptive than design patterns and are typically not dependent on any specific programming language or technology.</p>
<p>For example, the Single Responsibility Principle (SRP) suggests that a class should have only one reason to change. This is a high-level statement that we should keep in mind while designing or creating classes for our application. SRP does not provide specific implementation steps and it is up to developers how they implement it in their applications.</p>
<p>Sometimes, design principles imply some design patterns. For example, the Open/Closed principle closely implies the Strategy pattern. Meanwhile, the Dependency Injection principle has strong ties to the MVC pattern.</p>
<p><strong>Examples of Design Principles:</strong></p>
<ul>
<li><p>DRY Principle (Don't Repeat Yourself)</p>
</li>
<li><p>KISS Principle (Keep It Simple, Stupid)</p>
</li>
<li><p>Single Responsibility Principle (a class should have only one reason to change)</p>
</li>
<li><p>SOLID Principles (an acronym for five design principles)</p>
</li>
</ul>
<h2 id="heading-tldr">TL;DR</h2>
<ul>
<li><p>Design Patterns are specific (low-level) solutions to specific problems. You should have a very good reason every time you decide to implement a pattern.</p>
</li>
<li><p>Design Principles are general (high-level) guidelines that help inform good software design. You should have a very good reason every time you decide not to follow principles.</p>
</li>
<li><p>Both concepts are important for building high-quality software, and they can be used in conjunction to create robust and maintainable systems.</p>
</li>
</ul>
<hr />
<p>I hope you found this information helpful, stay tuned for more content! :)</p>
<hr />
<h2 id="heading-source">Source</h2>
<ol>
<li><a target="_blank" href="https://stackoverflow.com/questions/31317141/whats-the-difference-between-design-patterns-and-design-principles">ruby on rails - What's the difference between design patterns and design principles? - Stack Overflow</a></li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The Difference Between Unix and Linux]]></title><description><![CDATA[Today, Linux is in great demand. You can see its use everywhere, on servers, desktops, smartphones, and even some electrical devices such as refrigerators. Some people consider Unix and Linux as synonyms, but that is not true. Let's take a closer loo...]]></description><link>https://blog.savetchuk.com/the-difference-between-unix-and-linux</link><guid isPermaLink="true">https://blog.savetchuk.com/the-difference-between-unix-and-linux</guid><category><![CDATA[Linux]]></category><category><![CDATA[unix]]></category><category><![CDATA[operating system]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Thu, 31 Mar 2022 21:43:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676581325378/6b35026e-64d7-4d26-939e-3ccc9fc4ca13.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, Linux is in great demand. You can see its use everywhere, on servers, desktops, smartphones, and even some electrical devices such as refrigerators. Some people consider Unix and Linux as synonyms, but that is not true. Let's take a closer look.</p>
<h2 id="heading-unix">Unix​</h2>
<p>Before Linux and Windows, the computer world was dominated by Unix. Unix is a family of computer operating systems that derive from the original AT&amp;T Unix (the mother OS as some people call it) that was invented in the '60s and over time has become a standard or certification. Only systems fully compliant with and certified to the <a target="_blank" href="https://en.wikipedia.org/wiki/Single_UNIX_Specification">Single UNIX Specification</a> qualify as "Unix", others are called "Unix-like". For example, nowadays Mac OS is certified as UNIX certified while Linux is Unix-Like.</p>
<p>However, over time, Unix became less popular. The main problem with Unix was that it was very expensive. You needed expensive machinery, an expensive license, and an expensive administrator. We are talking about tens of thousands of dollars or euros a year, not the computer you buy as a student. This still applies to <strong>IBM AIX</strong>, <strong>HP-UX</strong>, and <strong>Sun Solaris</strong>, which are mostly used by large companies and organizations, although it would be cheaper for them to run everything on Linux.</p>
<h2 id="heading-linux">Linux​</h2>
<p>Linux is a Unix-like operating system that behaves in a manner similar to a Unix system, although not necessarily conforming to or being certified to any version of the Single UNIX Specification. Technically, it is created from scratch, except for some parts where software providers gave away their code. The term Linux is applied to a number of open-source Unix-like operating systems based on the Linux kernel (the main component of a Linux operating system) known as distributions: <strong>Ubuntu</strong>, <strong>Debian</strong>, <strong>CentOS</strong>, <strong>Fedora</strong>, and so on.</p>
<p>Many operating systems were developed to be like Unix, but none have become as popular as Linux. Linux arose from the desire to have an affordable OS that would be cheap and could run on common hardware, like the average PC. One of the features was to make it "free" with the appropriate license: <a target="_blank" href="https://en.wikipedia.org/wiki/GNU_General_Public_License">GNU</a>. It is freely available, costs nothing to download and install, and can run on a cheap computer, take Raspberry Pi, for example. Using Linux as a user or admin is mostly the same as using Unix as the commands are very similar. If you have ever worked with a Linux and Mac OS terminal, you have probably noticed it.</p>
<hr />
<p>We can say that asking about the differences between Unix and Linux is like asking about the differences between Mammals and Dogs. All dogs are mammals, but we can say that they are usually more suitable for pets than other mammals. This is not to say that other mammals, such as cats, cannot be excellent pets. Similarly, it would be fair to say that Linux is generally less expensive than Unix, but this does not preclude the existence of expensive Linux or free Unix distributions.</p>
<hr />
<h2 id="heading-key-features">Key Features</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Linux</td><td>Unix</td></tr>
</thead>
<tbody>
<tr>
<td>Linux is used everywhere, on servers, desktops, smartphones, and even some electrical devices such as refrigerators.</td><td>Unix is used on servers, workstations, and PCs.</td></tr>
<tr>
<td>Linux is an open-source operating system that is freely available to everyone.</td><td>Unix is an operating system that can be only used by its copyrighters.</td></tr>
<tr>
<td>Linux is open-source, it is developed by sharing and collaborating with developers from around the world.</td><td>Unix was developed by AT&amp;T Labs, various commercial vendors, and non-profit organizations.</td></tr>
<tr>
<td>The term Linux is applied to a number of open-source Unix-like operating systems based on the Linux kernel (the main component of a Linux operating system) known as distributions: Ubuntu, Debian, CentOS, Fedora, and so on.</td><td>Unix is a family of computer operating systems that derive from the original AT&amp;T Unix. Unix has three distributions IBM AIX, HP-UX, and Sun Solaris. Apple also uses Unix to create the OSX operating system.</td></tr>
</tbody>
</table>
</div><h2 id="heading-tldr">TL;DR</h2>
<p>Unix and Linux are both operating systems, with Unix being an older and proprietary system, while Linux is an open-source system based on Unix.</p>
<hr />
<p>I hope you found this information helpful, stay tuned for more content! :)</p>
<hr />
<h2 id="heading-source">Source</h2>
<ol>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Unix">Unix - Wikipedia</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Linux">Linux - Wikipedia</a></p>
</li>
<li><p><a target="_blank" href="https://unix.stackexchange.com/questions/282752/difference-between-unix-and-linux">Difference between Unix and Linux - Unix &amp; Linux Stack Exchange</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The Difference Between Service Classes and Traits in PHP]]></title><description><![CDATA[The main difference between service classes and traits is that service classes provide a complete implementation of a specific service or functionality, whereas traits provide a set of methods that can be mixed into multiple classes to provide them w...]]></description><link>https://blog.savetchuk.com/the-difference-between-service-classes-and-traits-in-php</link><guid isPermaLink="true">https://blog.savetchuk.com/the-difference-between-service-classes-and-traits-in-php</guid><category><![CDATA[PHP]]></category><category><![CDATA[Laravel]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Mon, 28 Mar 2022 22:30:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676671263509/284fe405-7648-4c59-a1db-1fcb66db1f31.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The main difference between service classes and traits is that <strong>service classes provide a complete implementation of a specific service</strong> or functionality, whereas <strong>traits provide a set of methods that can be mixed into multiple classes</strong> to provide them with additional functionality.</p>
<p>Both service classes and traits can be reused throughout an application and service classes can utilize traits.</p>
<h2 id="heading-service-classes">Service Classes​</h2>
<p>We can think of a service class like a PHP object that performs some sort of a "global" task. Service classes are often used to encapsulate complex business logic or to provide a unified interface to interact with external services, such as databases or web services.</p>
<p>For example, there may be a <strong>mailing service</strong> or a <strong>user creation</strong> service. These are tasks that need to be repeated over and over again in different places. This makes them good candidates for a service class.</p>
<p>Some ideas for service classes:</p>
<ul>
<li><p>Service class responsible for sending SMS via Twilio.</p>
</li>
<li><p>Service class responsible for sending Emails via Mailgun (Newsletter Service).</p>
</li>
<li><p>Service class responsible for working with UptimeRobot APIs.</p>
</li>
<li><p>Service class responsible for storing and deleting images on the cloud.</p>
</li>
</ul>
<h3 id="heading-example-of-a-service-class-in-laravel">Example of a Service Class in Laravel​</h3>
<p>Here is an example of the <code>App\Services\UptimeRobotAPI.php</code> service class that is responsible for connecting to the UptimeRobot API and retrieving data:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Services</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">GuzzleHttp</span>\<span class="hljs-title">Client</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UptimeRobotAPI</span>
</span>{
  <span class="hljs-keyword">protected</span> <span class="hljs-keyword">string</span> $url;
  <span class="hljs-keyword">protected</span> <span class="hljs-keyword">string</span> $http;
  <span class="hljs-keyword">protected</span> <span class="hljs-keyword">array</span> $headers;

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">Client $client</span>)
  </span>{
    <span class="hljs-keyword">$this</span>-&gt;url = <span class="hljs-string">'https://api.uptimerobot.com/v2/'</span>;
    <span class="hljs-keyword">$this</span>-&gt;http = $client;
    <span class="hljs-keyword">$this</span>-&gt;headers = [
      <span class="hljs-string">'cache-control'</span> =&gt; <span class="hljs-string">'no-cache'</span>,
      <span class="hljs-string">'content-type'</span>  =&gt; <span class="hljs-string">'application/x-www-form-urlencoded'</span>,
    ];
  }

  <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getResponse</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $path</span>)
  </span>{
    <span class="hljs-comment">// Making a GET request to UptimeRobot API using GuzzleHttp...</span>
  }

  <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">postResponse</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $path, <span class="hljs-keyword">array</span> $params = []</span>)
  </span>{
    <span class="hljs-comment">// Making a POST request to UptimeRobot API using GuzzleHttp...</span>
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMonitors</span>(<span class="hljs-params"></span>)
  </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;getResponse(<span class="hljs-string">'getMonitors'</span>);
  }
}
</code></pre>
<p>The UptimeRobotAPI service is now can be used like so:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Controllers</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Services</span>\<span class="hljs-title">UptimeRobotAPI</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MonitorsController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span>
</span>{
  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span>(<span class="hljs-params">UptimeRobotAPI $uptimeRobotAPI</span>)
  </span>{
    $monitors = $uptimeRobotAPI-&gt;getMonitors();

    <span class="hljs-keyword">return</span> view(<span class="hljs-string">'monitors.index'</span>, compact(<span class="hljs-string">'monitors'</span>));
  }
}
</code></pre>
<h3 id="heading-more-service-class-examples">More Service Class Examples</h3>
<p>Another example of a service class would be a <code>PaymentService</code> or <code>StripeService</code> - a service class that encapsulates payment-related functionality, such as processing payments, managing payment methods, and handling refunds.</p>
<hr />
<h2 id="heading-traits">Traits</h2>
<p>In PHP, a class can only inherit from a single parent class, which can limit the ability to reuse code. Traits were introduced to solve this problem by providing a way to reuse code across multiple classes without using inheritance. They allow developers to define a set of methods that can be shared among multiple classes, allowing for more flexible and modular code. Traits are particularly useful when building complex applications that require a lot of code reuse.</p>
<h3 id="heading-example-of-a-trait-in-laravel">Example of a Trait in Laravel</h3>
<p>Here is an example of the <code>app/Traits/ApiResponder.php</code> trait I often use when developing Laravel applications:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Traits</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">JsonResponse</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Symfony</span>\<span class="hljs-title">Component</span>\<span class="hljs-title">HttpFoundation</span>\<span class="hljs-title">Response</span>;

<span class="hljs-keyword">trait</span> ApiResponder
{
  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">successResponse</span>(<span class="hljs-params">$data, <span class="hljs-keyword">int</span> $code = Response::HTTP_OK</span>): <span class="hljs-title">JsonResponse</span> </span>{
    <span class="hljs-keyword">return</span> response()-&gt;json([
      <span class="hljs-string">'data'</span> =&gt; $data,
      <span class="hljs-string">'code'</span> =&gt; $code,
    ], $code)-&gt;header(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'application/json'</span>);
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">errorResponse</span>(<span class="hljs-params">$error, <span class="hljs-keyword">int</span> $code</span>): <span class="hljs-title">JsonResponse</span>
  </span>{
    <span class="hljs-keyword">return</span> response()-&gt;json([
      <span class="hljs-string">'error'</span> =&gt; $error,
      <span class="hljs-string">'code'</span>  =&gt; $code,
    ], $code)-&gt;header(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'application/json'</span>);
  }
}
</code></pre>
<p>Once the trait is created, you can import it as follows:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Controllers</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Traits</span>\<span class="hljs-title">ApiResponder</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Foundation</span>\<span class="hljs-title">Auth</span>\<span class="hljs-title">Access</span>\<span class="hljs-title">AuthorizesRequests</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Foundation</span>\<span class="hljs-title">Bus</span>\<span class="hljs-title">DispatchesJobs</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Foundation</span>\<span class="hljs-title">Validation</span>\<span class="hljs-title">ValidatesRequests</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Routing</span>\<span class="hljs-title">Controller</span> <span class="hljs-title">as</span> <span class="hljs-title">BaseController</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Controller</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">BaseController</span>
</span>{
  <span class="hljs-keyword">use</span> <span class="hljs-title">AuthorizesRequests</span>, <span class="hljs-title">DispatchesJobs</span>, <span class="hljs-title">ValidatesRequests</span>, <span class="hljs-title">ApiResponder</span>;

  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Once the trait is imported it is ready to use:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Controllers</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">JsonResponse</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TwilioSettingsController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span>
</span>{
  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchSettings</span>(<span class="hljs-params"></span>): <span class="hljs-title">JsonResponse</span>
  </span>{
    $response = TwilioSettings::getSettings();

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;successResponse($response);
  }
}
</code></pre>
<h3 id="heading-more-trait-examples">More Trait Examples</h3>
<p>Another example of a trait would be a <code>LoggableTrait</code> - a trait that adds logging functionality to a class, allowing it to log messages to a log file or other logging system. This trait can be used by multiple PHP classes, including Service Classes.</p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
]]></content:encoded></item><item><title><![CDATA[Overview of the Active Record Pattern]]></title><description><![CDATA[Definition
The active record design pattern (considered an architectural pattern) is an approach that connects the application's business logic to a database table, allowing developers to work with the database using an object-oriented paradigm.
The ...]]></description><link>https://blog.savetchuk.com/overview-of-the-active-record-pattern</link><guid isPermaLink="true">https://blog.savetchuk.com/overview-of-the-active-record-pattern</guid><category><![CDATA[design patterns]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Sat, 19 Mar 2022 21:09:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676609619057/dcdc499e-6e32-43bf-8440-1f3f37a29bc2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-definition">Definition</h2>
<p><strong>The active record design pattern</strong> (considered an architectural pattern) is an approach that connects the application's business logic to a database table, allowing developers to work with the database using an object-oriented paradigm.</p>
<p><strong>The active record</strong> is an object that wraps a row in the database table, encapsulates the database access and provides an interface to query, insert, update and delete data from the database, making it easier to work with databases in an application.</p>
<p>In addition to query, insert, update and delete functions, the interface on an object conforming to this pattern would also include properties that correspond more or less directly to the columns in the underlying database table.</p>
<p>After the creation of an object, a new row is added to the table upon saving. Any object loaded gets its information from the database. When an object is updated, the corresponding row in the table is also updated. The wrapper class implements accessor methods or properties for each column in the table or view.</p>
<p>The active record pattern is commonly used by many programming frameworks that store in-memory object data in relational databases, such as Django and Laravel.</p>
<h2 id="heading-name-origin">Name origin</h2>
<p>The pattern was named by Martin Fowler in his book <a target="_blank" href="https://amzn.to/3uawkEy">Patterns of Enterprise Application Architecture</a> (2003).</p>
<h2 id="heading-implementation">Implementation</h2>
<p>This pattern is intended to make simple CRUD (Create, Read, Update, Delete) tasks quicker to achieve. For example, instead of writing a lot of SQL queries to insert or update many common and simple data objects, it allows us to simply assign values to the data object and run a command to save it, e.g. <code>$object-&gt;save()</code>. The SQL for inserting/updating data will be compiled and executed for us.</p>
<p>For example, if there is a table <code>users</code> in a database with columns <code>name</code> (string type) and <code>age</code> (number type), and the Active Record pattern is implemented in the class <code>User</code>, the pseudo-code will create a new row in the <code>users</code> table with the given values:</p>
<pre><code class="lang-php">$user = <span class="hljs-keyword">new</span> User();
$user-&gt;name = <span class="hljs-string">'John Doe'</span>;
$user-&gt;age = <span class="hljs-number">25</span>;
$user-&gt;save();
</code></pre>
<p>The pseudo-code above is roughly equivalent to the SQL command:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-keyword">users</span> (<span class="hljs-keyword">name</span>, age) <span class="hljs-keyword">VALUES</span> (<span class="hljs-string">'John Doe'</span>, <span class="hljs-number">25</span>);
</code></pre>
<p>Conversely, the class can be used to query the database:</p>
<pre><code class="lang-php">$user = User::where(<span class="hljs-string">'name'</span>, <span class="hljs-string">'John Doe'</span>)-&gt;first();
</code></pre>
<p>This will find a new <code>User</code> object based on the first matching row from the <code>users</code> table whose <code>name</code> column has the value "John Doe". The SQL command used might be similar to the following, depending on the SQL implementation details of the database:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">users</span> <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">name</span> = <span class="hljs-string">'John Doe'</span> <span class="hljs-keyword">LIMIT</span> <span class="hljs-number">1</span>;
</code></pre>
<p>Most frameworks also implement data relationships within their respective Active Record models which can greatly simplify accessing data related to our object. For example, in Laravel, if we specified that a <code>Category</code> "has many" <code>Product</code>`s then after loading the <code>Category</code> object from the database, we can list its child <code>Product</code>`s with a simple line of code:</p>
<pre><code class="lang-php"><span class="hljs-keyword">foreach</span> ($category-&gt;products <span class="hljs-keyword">as</span> $product) {
  <span class="hljs-keyword">echo</span> $product-&gt;name;
}
</code></pre>
<h2 id="heading-when-to-use-it">When to use it</h2>
<p>Active Record is a good choice for domain logic that is not too complex, such as creates, reads, updates, and deletes. Derivations and validations based on a single record work well in this structure.</p>
<h2 id="heading-criticism">Criticism</h2>
<h4 id="heading-mapping-issues">Mapping issues</h4>
<p>Active Record has the primary advantage of simplicity. It is easy to build Active Records, and they are easy to understand. Their primary problem is that they work well only if the Active Record objects correspond directly to the database tables: an isomorphic schema.</p>
<p>If your business logic is complex, you will soon want to use your object's direct relationships, collections, inheritance, and so forth. These do not map easily onto Active Record, and adding them piecemeal gets very messy. That is what will lead you to use Data Mapper instead.</p>
<h4 id="heading-testability">Testability</h4>
<p>Due to the coupling of database interaction and application logic when using the active record pattern, unit testing an active record object without a database becomes difficult. These negative effects on the testability of the active record pattern can be reduced by using mocking or dependency injection frameworks to substitute the real data tier with a simulated one.</p>
<h4 id="heading-distributed-systems">Distributed systems</h4>
<p>Record-based patterns work poorly in distributed systems, especially where concurrency is impossible (e.g. offline). i.e. two updates both may have one field that is correct but only one of the two records can win.</p>
<h4 id="heading-single-responsibility-principle-and-separation-of-concerns">Single responsibility principle and separation of concerns</h4>
<p>Due to the strong coupling of database interaction and application logic, an active record object does not follow the single responsibility principle and separation of concerns as opposed to multitier architecture which properly addresses these practices.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Active Record is good for quick CRUD-based applications where the Model is relatively flat (as in, not a lot of class hierarchies). However, for applications with complex OO hierarchies, a DataMapper is probably a better solution.</p>
<hr />
<p>I hope you found this information helpful, stay tuned for more content! :)</p>
<hr />
<h2 id="heading-source">Source</h2>
<ol>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Active_record_pattern">Active record pattern - Wikipedia</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/1404405/what-is-the-purpose-of-active-records">What is the purpose of Active Records? - StackOverflow</a></p>
</li>
<li><p><a target="_blank" href="https://amzn.to/3uawkEy">Patterns of Enterprise Application Architecture (2003)</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The Complete Guide to Installing and Configuring a Next.js Project in 2022]]></title><description><![CDATA[In this article, we will install and configure a Next.js project, including:

Adding SASS / SCSS support

Setting up Eslint and Prettier

Setting up Eslint to run automatically before every commit (via a Git hook)

Setting up Semantic Commits (via a ...]]></description><link>https://blog.savetchuk.com/the-complete-guide-to-installing-and-configuring-a-nextjs-project-in-2022</link><guid isPermaLink="true">https://blog.savetchuk.com/the-complete-guide-to-installing-and-configuring-a-nextjs-project-in-2022</guid><category><![CDATA[Next.js]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Andrew Savetchuk]]></dc:creator><pubDate>Sat, 27 Nov 2021 22:39:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676577527152/8470170c-0867-478b-bbfb-2bd1113bb7cc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we will install and configure a Next.js project, including:</p>
<ul>
<li><p>Adding SASS / SCSS support</p>
</li>
<li><p>Setting up Eslint and Prettier</p>
</li>
<li><p>Setting up Eslint to run automatically before every commit (via a Git hook)</p>
</li>
<li><p>Setting up Semantic Commits (via a Git hook)</p>
</li>
</ul>
<p><strong>Any of the above items are optional and can be skipped during the process.</strong><br />For example, if you are not familiar with Semantic Commits or do not plan to use it, you can skip that part and move on to another.</p>
<blockquote>
<p>You may want to bookmark this article and use it as a reference when creating your projects. I will try to keep it up to date, and when I discover a new useful feature, I will include it here.</p>
</blockquote>
<p>Let's get started.</p>
<h2 id="heading-1-install-nodejs-and-npm">1. Install Node.js and NPM</h2>
<p>We need Node.js 12.22.0 or later in order to install and use Next.js.</p>
<p>To see if you already have Node.js and NPM installed on your machine, run the following commands:</p>
<pre><code class="lang-bash">node -v
npm -v
</code></pre>
<p>You should see the installed version printed for each command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638040756170/XFzKydMUlA.png" alt="Screenshot 2021-11-27 at 21.17.45.png" /></p>
<p>If you do not have this output and instead see <code>command not found</code> or a similar error, download and install Node.js from the official website: https://nodejs.org/en/download/</p>
<h2 id="heading-2-install-nextjs">2. Install Next.js</h2>
<p>Open your terminal, navigate to the folder where you want to create a new project, and run the following command:</p>
<pre><code class="lang-bash">npx create-next-app@latest
</code></pre>
<p>During installation, you will be prompted to name the project, enter the most appropriate name, and press Enter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638041526686/LUZ2CmZYBU.png" alt="Screenshot 2021-11-27 at 21.31.55.png" /></p>
<p>Congratulations! You have installed Next.js.</p>
<p>You can stop here and work with your application already by running the following command in the directory we just created (you named it during the installation).</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>However, if you want to add some configuration, open the project in your favorite code editor and follow the next steps. Each of the steps is optional, you can choose ones that suit you best.</p>
<h2 id="heading-3-configure-gitignore-for-jetbrains-products">3. Configure .gitignore for JetBrains products</h2>
<p><strong>Note: This step is optional.</strong></p>
<p>If you are using any of the JetBrains code editors (such as WebStorm or PHPStorm), it is recommended that you exclude certain folders and files from version control.</p>
<p>You may use the following preset: <a target="_blank" href="https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore">https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore</a></p>
<p>Just copy and paste the content into your <code>.gitignore</code> file.</p>
<h2 id="heading-4-adding-sass-scss-support">4. Adding SASS / SCSS support</h2>
<p><strong>Note: This step is optional.</strong></p>
<p>If you plan on using SASS / SCSS, run the following command:</p>
<pre><code class="lang-bash">npm install sass
</code></pre>
<p>Now go to the <code>styles</code> folder, you should see two <code>.css</code> files there:</p>
<ul>
<li><p>styles/globals.css</p>
</li>
<li><p>styles/Home.module.css</p>
</li>
</ul>
<p>Rename them to <code>.sass</code> or <code>.scss</code> as you prefer.</p>
<p>After you renamed the files, you need to change the paths to them in:</p>
<ul>
<li><p>pages/_app.js</p>
</li>
<li><p>pages/index.js</p>
</li>
</ul>
<p>That is all! The rest will be handled by Next.js. You can now use SASS in your project.</p>
<h2 id="heading-5-setting-up-eslint-and-prettier">5. Setting up Eslint and Prettier</h2>
<p><strong>Note: This step is optional.</strong></p>
<p>Eslint is already installed in your Next.js project by default. The configuration file (<code>.eslintrc.json</code>) can be found in the root directory of your project.</p>
<p>However, it is not automatically called when you run the application in development mode (<code>npm run dev</code>). This is why we are going to set up a Git hook in the next step, but first, let's install and configure Prettier.</p>
<p>Run the following commands to install Prettier:</p>
<pre><code class="lang-bash">npm install --save-dev prettier
</code></pre>
<p>Since Eslint also contains code formatting rules, which can conflict with your existing Prettier setup, installation of <strong>eslint-config-prettier</strong> is recommended.</p>
<p>To install the config, run:</p>
<pre><code class="lang-bash">npm install --save-dev eslint-config-prettier
</code></pre>
<p>After the installation, create a config file for Prettier (<code>.prettierrc.json</code>) in the root directory of your project. Here is a sample configuration.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"singleQuote"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"semi"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"tabWidth"</span>: <span class="hljs-number">2</span>
}
</code></pre>
<p>Now, add <code>prettier</code> to your existing Eslint config (<code>.eslintrc.json</code>): <code>json { "extends": ["next/core-web-vitals", "prettier"] }</code></p>
<p>Done, now you can use Prettier and lint your code by running <code>npm run lint</code>.</p>
<h2 id="heading-6-setting-up-eslint-to-run-automatically-before-every-commit">6. Setting up Eslint to run automatically before every commit</h2>
<p><strong>Note: This step is optional.</strong></p>
<p>To prevent code with Eslint errors or warnings from being pushed to your working repository, you can set up a Git hook that will run the <code>next lint</code> command every time you try to send a commit.</p>
<p>In case of Eslint errors, your commit will not be sent and you will see an info message with error/warning details. See the example below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638047072340/WOzSVnwmQ.png" alt="Screenshot 2021-11-27 at 23.03.57.png" /></p>
<p>In order to set up Git hooks, we need to install Husky (npm package):</p>
<pre><code class="lang-bash">npm install husky --save-dev
</code></pre>
<p>After the installation, add the <code>prepare</code> script to your <code>package.json</code> file:</p>
<pre><code class="lang-json">...
<span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"next dev"</span>,
    <span class="hljs-attr">"build"</span>: <span class="hljs-string">"next build"</span>,
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"next start"</span>,
    <span class="hljs-attr">"lint"</span>: <span class="hljs-string">"next lint"</span>,
    <span class="hljs-attr">"prepare"</span>: <span class="hljs-string">"husky install"</span>
},
...
</code></pre>
<p>Then run it once, it will create a <code>.husky</code> folder with the required configurations.</p>
<pre><code class="lang-bash">npm run prepare
</code></pre>
<p>Husky is installed and it is time to create our first Git hook.</p>
<p>Run the following command:</p>
<pre><code class="lang-bash">npx husky add .husky/pre-commit <span class="hljs-string">"next lint --max-warnings=0"</span>
</code></pre>
<p>This command creates a pre-commit hook that executes <code>next lint</code> command every time you try to send a commit.</p>
<p>The <code>--max-warnings=0</code> flag is optional and can be removed in order to allow pushing the code with Eslint warnings. The info message will only appear in case of errors.</p>
<h2 id="heading-7-setting-up-semantic-commits">7. Setting up Semantic Commits</h2>
<p><strong>Note: This step is optional.</strong></p>
<p>If you are familiar with <a target="_blank" href="https://www.conventionalcommits.org/en/v1.0.0/">Semantic Commits</a>, you may want to add validation to ensure all commis is in the correct format.</p>
<p>To do so you need to have Husky installed (see step 6 in this tutorial).</p>
<p>After Husky installation, we need to install the <a target="_blank" href="https://github.com/conventional-changelog/commitlint">@commitlint</a> npm package:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install commitlint cli and conventional config</span>
npm install --save-dev @commitlint/{config-conventional,cli}

<span class="hljs-comment"># For Windows:</span>
npm install --save-dev @commitlint/config-conventional @commitlint/cli
</code></pre>
<p>Then we need to configure commitlint to use conventional config:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"module.exports = {extends: ['@commitlint/config-conventional']}"</span> &gt; commitlint.config.js
</code></pre>
<p>And finally, add a hook that will check the validity of commit messages:</p>
<pre><code class="lang-bash">npx husky add .husky/commit-msg <span class="hljs-string">'npx --no -- commitlint --edit "$1"'</span>
</code></pre>
<p>Now, if you try to send a commit that does not follow the Conventional Commits rules, you will see the following error:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638050744897/fVxrGQrEU.png" alt="Screenshot 2021-11-28 at 00.04.47.png" /></p>
<hr />
<p>If you would like to see the final results of the project described in this article please take a look at the Github repository: <a target="_blank" href="https://github.com/AndrewSavetchuk/next-js-project-starter">https://github.com/AndrewSavetchuk/next-js-project-starter</a></p>
<hr />
<p>The end. I hope you found this information helpful, stay tuned for more content! :)</p>
]]></content:encoded></item></channel></rss>