<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maroje Macola</title>
    <description>The latest articles on DEV Community by Maroje Macola (@wnbsmart).</description>
    <link>https://dev.to/wnbsmart</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F345747%2F3b91e3da-aaa6-4b7f-8630-676176926532.jpeg</url>
      <title>DEV Community: Maroje Macola</title>
      <link>https://dev.to/wnbsmart</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wnbsmart"/>
    <language>en</language>
    <item>
      <title>Beware of PHP’s strcmp() function when sorting</title>
      <dc:creator>Maroje Macola</dc:creator>
      <pubDate>Mon, 16 Aug 2021 12:15:46 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/beware-of-php-s-strcmp-function-when-sorting-3ogb</link>
      <guid>https://dev.to/bornfightcompany/beware-of-php-s-strcmp-function-when-sorting-3ogb</guid>
      <description>&lt;p&gt;I was looking for a way to sort an array of objects via multiple properties, which are calculated on the fly. As usual, quick googling navigated me to the Stack Overflow, where I found the same &lt;a href="https://stackoverflow.com/questions/4282413/sort-array-of-objects-by-object-fields" rel="noopener noreferrer"&gt;question&lt;/a&gt; and, most importantly, answers for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggested solution from SO
&lt;/h2&gt;

&lt;p&gt;If we take a look at the suggested solutions from SO, it is a combination of &lt;a href="https://www.php.net/manual/en/function.usort.php" rel="noopener noreferrer"&gt;usort()&lt;/a&gt; and &lt;a href="https://www.php.net/manual/en/function.strcmp" rel="noopener noreferrer"&gt;strcmp()&lt;/a&gt; functions. At first, they seem like a good combo, since &lt;code&gt;usort&lt;/code&gt; &lt;em&gt;accepts&lt;/em&gt; callback function which needs to return  an integer number. &lt;code&gt;strcmp&lt;/code&gt; returns exactly that, based on comparison it does, where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;negative integers imply that the value of the first argument is &lt;strong&gt;lower&lt;/strong&gt; than the second's&lt;/li&gt;
&lt;li&gt;0 implies equal values&lt;/li&gt;
&lt;li&gt;positive integers imply that the value of the first argument is &lt;strong&gt;bigger&lt;/strong&gt; than the second's&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'7'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -4&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'9'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'9'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problem with suggested solution
&lt;/h2&gt;

&lt;p&gt;Even though everything seems good at first when comparing one-digit numbers, it doesn't go well when multi-digit numbers come into play:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'7'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'111'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 6 (expected -104)&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'18'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'9'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -8 (expected 9)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happened here? Numbers are not being compared as a whole.&lt;br&gt;
In the first example, number 7 is compared with the first digit of the value 111, and their difference is 6.&lt;br&gt;
In the second example, first digit of the number 18 is compared with number 9, and their difference is -8.&lt;/p&gt;

&lt;p&gt;To be precise, a binary comparison is being done in the background. &lt;code&gt;strcmp&lt;/code&gt; is one of many functions which are &lt;a href="https://www.techiedelight.com/implement-strcmp-function-c/" rel="noopener noreferrer"&gt;taken&lt;/a&gt; from the C language.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implemented solution
&lt;/h2&gt;

&lt;p&gt;To solve this problem, we don't need &lt;code&gt;strcmp&lt;/code&gt; or any other helper function. If we are sure that compared arguments will be integers, we can simply use good ol' subtraction to get the needed result (negative, 0 or positive):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nb"&gt;usort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arrayOfElements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$firstElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$secondElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$firstElement&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$secondElement&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, if you need to sort values in a descending order, just swap the subtrahend and minuend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$secondElement&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$firstElement&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finrr3qwc91ws3x1dxdqw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finrr3qwc91ws3x1dxdqw.jpeg" alt="Stack Overflow c/p"&gt;&lt;/a&gt;&lt;br&gt;
Copy-pasting solutions from Stack Overflow without enough research can result in big damage.&lt;br&gt;
In my case, the problem was not visible for a few days because of the values being used for testing.&lt;/p&gt;

&lt;p&gt;Make sure to check the documentation and spend more time testing solutions.&lt;/p&gt;

&lt;p&gt;If you have encountered similar problems by doing c/p from SO, let us know in the comments :)&lt;/p&gt;

</description>
      <category>php</category>
      <category>programming</category>
      <category>engineeringmonday</category>
    </item>
    <item>
      <title>Transferring files between local machine and AWS instance</title>
      <dc:creator>Maroje Macola</dc:creator>
      <pubDate>Mon, 22 Mar 2021 15:35:44 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/transferring-files-between-local-machine-and-aws-instance-4efg</link>
      <guid>https://dev.to/bornfightcompany/transferring-files-between-local-machine-and-aws-instance-4efg</guid>
      <description>&lt;p&gt;Hello fellow dev.to readers!&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Recently, I needed to transfer files from local machine to the remote AWS instance. Since I haven't done this before, after a quick googling, I stumbled upon a cool bash command &lt;code&gt;scp&lt;/code&gt; (secure copy). After seeing &lt;em&gt;secure&lt;/em&gt; keyword in its name, I didn't waste time on looking for other solutions, although I believe there are many. Therefore, let's take a look at how can we use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;scp&lt;/code&gt; command
&lt;/h2&gt;

&lt;p&gt;Generally, with this command, we are able to do 3 types of file transfers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;from local to remote machine&lt;/li&gt;
&lt;li&gt;from remote to local machine&lt;/li&gt;
&lt;li&gt;between two remote machines, by using local machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, we will cover first 2 cases.&lt;/p&gt;

&lt;p&gt;To get a list of available options for &lt;code&gt;scp&lt;/code&gt; command, we can run &lt;code&gt;scp help&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;scp &lt;span class="nb"&gt;help
&lt;/span&gt;usage: scp &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-346BCpqrv&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-c&lt;/span&gt; cipher] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-F&lt;/span&gt; ssh_config] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-i&lt;/span&gt; identity_file] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-l&lt;/span&gt; limit] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-o&lt;/span&gt; ssh_option] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-P&lt;/span&gt; port] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-S&lt;/span&gt; program] &lt;span class="nb"&gt;source&lt;/span&gt; ... target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A comprehensive list with detailed explanations can be found &lt;a href="https://ss64.com/bash/scp.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[-i identity_file]&lt;/code&gt; parameter will be of use for our case of communicating with AWS instances, since we need to use private key which is also used for &lt;code&gt;ssh&lt;/code&gt; connection with the server.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[-r Recursively copy entire directories]&lt;/code&gt; parameter will be of help to transfer whole directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local -&amp;gt; remote file transfer
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt; - transferring an image from the local machine's Downloads folder to AWS server, which has &lt;code&gt;ec2-user&lt;/code&gt; and IP address &lt;code&gt;192.168.1.1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/key ~/Downloads/image.png ec2-user@192.168.1.1:~/deployment/current/public 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's segment command for easier understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-i ~/.ssh/key&lt;/code&gt; specifying path to the identity_file, key which you also use for ssh connection with your AWS instance&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/Downloads/image.png&lt;/code&gt; specifying path to the file which we want to transfer from local machine&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ec2-user@192.168.1.1&lt;/code&gt; specifying AWS user and IP address of the remote instance&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/deployment/current/public&lt;/code&gt; specifying path to the destination directory on the remote instance (where transferred file will exist after execution)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remote -&amp;gt; local file transfer
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt; - transferring &lt;em&gt;src&lt;/em&gt; directory from AWS server, to the local Downloads folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/key &lt;span class="nt"&gt;-r&lt;/span&gt; ec2-user@192.168.1.1:~/deployment/current/src ~/Downloads
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's segment command for easier understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-i ~/.ssh/key&lt;/code&gt; specifying path to the identity_file, key which you also use for ssh connection with your AWS instance&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-r ec2-user@192.168.1.1&lt;/code&gt; specifying AWS user and IP address of the remote instance, this time with &lt;code&gt;-r&lt;/code&gt; option we say that we want to transfer directory recursively&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/deployment/current/src&lt;/code&gt; specifying path to the directory which we want to transfer to from AWS server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/Downloads&lt;/code&gt; specifying path to the destination directory on the local machine (where transferred file will exist after execution)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;code&gt;scp&lt;/code&gt; is a very powerful command which allows us to easily transfer files between local and remote AWS server. As mentioned in one of the paragraphs, it has many additional options to be used, but we only need a few of them to be able to do a basic data transfer.&lt;/p&gt;

&lt;p&gt;How do you transfer files between your servers? 🙃&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sauves.com/wp-content/uploads/2019/07/data-transfer-16x9.jpg"&gt;Cover image source&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bash</category>
      <category>tutorial</category>
      <category>aws</category>
      <category>engineeringmonday</category>
    </item>
    <item>
      <title>Consequences of updating cron jobs within Ansible's playbook</title>
      <dc:creator>Maroje Macola</dc:creator>
      <pubDate>Mon, 14 Dec 2020 13:20:53 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/consequences-of-updating-cron-jobs-within-ansible-s-playbook-2hjk</link>
      <guid>https://dev.to/bornfightcompany/consequences-of-updating-cron-jobs-within-ansible-s-playbook-2hjk</guid>
      <description>&lt;p&gt;Hello fellow dev.to readers!&lt;/p&gt;

&lt;h3&gt;
  
  
  Should you read this?
&lt;/h3&gt;

&lt;p&gt;Today, I am writing about a smaller issue which occurred to us recently. More precisely, I will show you the pitfall and how we dealt with it.&lt;br&gt;
If you have written a cron job within Ansible's playbook, but have never updated its values afterwards, you are a perfect reader for this post. Other than that, if you are interested in Ansible and want to learn something new, read on!&lt;/p&gt;
&lt;h3&gt;
  
  
  Cron job example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send emails about expiry dates&lt;/span&gt;
      &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;expiry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(runs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;each&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;day,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;15&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;midnight)"&lt;/span&gt;
        &lt;span class="na"&gt;minute&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15"&lt;/span&gt;
        &lt;span class="na"&gt;hour&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0"&lt;/span&gt;
        &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;php&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;path/to/console&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;email-expiry-dates/send-email"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So, what do we have here?&lt;br&gt;
It's a simple job which runs every day at 00:15 per server's time and executes a command which sends some emails.&lt;/p&gt;

&lt;p&gt;If we would want to get a list of all cron's on the server, we could execute &lt;code&gt;crontab -l&lt;/code&gt; on the server, and get something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight)&lt;/span&gt;
15 0 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; php path/to/console email-expiry-dates/send-email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating cron job
&lt;/h3&gt;

&lt;p&gt;Let's say that server's current time zone is UTC+00:00, and a change request comes up for the existing cron job, something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Emails should be delivered right after midnight in &lt;strong&gt;New York's time zone&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What did we do to implement necessary changes? Updated cron job's execution &lt;strong&gt;time&lt;/strong&gt;, but also its &lt;strong&gt;name&lt;/strong&gt; (or we can say, the &lt;a href="https://docs.ansible.com/ansible/latest/collections/ansible/builtin/cron_module.html#parameter-name"&gt;description&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send emails about expiry dates&lt;/span&gt;
      &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;expiry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(runs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;each&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;day,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;15&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;midnight&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;New&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;York's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;zone)"&lt;/span&gt;
        &lt;span class="na"&gt;minute&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15"&lt;/span&gt;
        &lt;span class="na"&gt;hour&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5"&lt;/span&gt;
        &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;php&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;path/to/console&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;email-expiry-dates/send-email"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deploying and listing server's cron jobs, we expected to have a single job as before, but with updated values, respectively. This was the actual result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight)&lt;/span&gt;
15 0 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; php path/to/console email-expiry-dates/send-email

&lt;span class="c"&gt;#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight in New York's time zone)"&lt;/span&gt;
15 5 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; php path/to/console email-expiry-dates/send-email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What happened after update?
&lt;/h3&gt;

&lt;p&gt;The result was 2 cron jobs. The old one stayed as is and the new one, with different parameters, was added to the list. Therefore, the same command was being executed 2 times a day, which definitely was not part of the acceptance criteria.&lt;/p&gt;

&lt;p&gt;Since the &lt;em&gt;name&lt;/em&gt; was changed, Ansible recognised this as a new cron job. This resulted in an unsynchronised state between server's and playbook's cron jobs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing the unexpected problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Old (Send emails about expiry dates)&lt;/span&gt;
      &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;expiry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(runs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;each&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;day,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;15&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;midnight)"&lt;/span&gt;
        &lt;span class="na"&gt;minute&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15"&lt;/span&gt;
        &lt;span class="na"&gt;hour&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0"&lt;/span&gt;
        &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;php&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;path/to/console&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;email-expiry-dates/send-email"&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;absent&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send emails about expiry dates&lt;/span&gt;
      &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;expiry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(runs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;each&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;day,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;15&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;midnight&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;New&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;York's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;zone)"&lt;/span&gt;
        &lt;span class="na"&gt;minute&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15"&lt;/span&gt;
        &lt;span class="na"&gt;hour&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5"&lt;/span&gt;
        &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;php&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;path/to/console&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;email-expiry-dates/send-email"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As visible above, we tried to be in sync with the server, by adding another cron job (with old values). Besides that, we added an additional parameter to the old cron job - &lt;code&gt;state: absent&lt;/code&gt;, which disabled its execution by removing it from the list of cron jobs on the server.&lt;/p&gt;

&lt;p&gt;After deploying this fix to the server, this was a final result after listing cron jobs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight in New York's time zone)"&lt;/span&gt;
15 5 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; php path/to/console email-expiry-dates/send-email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yaay! A single cron job with all parameters set correctly 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Changing a cron job's &lt;em&gt;name&lt;/em&gt; will not result in an update of the existing cron job. Its &lt;em&gt;name&lt;/em&gt; is some sort of an ID, and therefore should not be changed (in most cases). But, what we can do, is play around with &lt;strong&gt;tasks' name&lt;/strong&gt; property, since it will not lead to the problem we occurred :)&lt;/p&gt;

&lt;p&gt;Do you have any tips regarding this topic? I would be glad to hear them!&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>tutorial</category>
      <category>cron</category>
      <category>engineeringmonday</category>
    </item>
    <item>
      <title>Journey from Junior to Mid Software Developer</title>
      <dc:creator>Maroje Macola</dc:creator>
      <pubDate>Mon, 09 Nov 2020 20:27:53 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/journey-from-junior-to-mid-software-developer-3clm</link>
      <guid>https://dev.to/bornfightcompany/journey-from-junior-to-mid-software-developer-3clm</guid>
      <description>&lt;p&gt;Hello fellow dev.to readers!&lt;/p&gt;

&lt;h3&gt;
  
  
  Motivation &amp;amp; inspiration
&lt;/h3&gt;

&lt;p&gt;I was inspired by my colleague &lt;a href="https://dev.to/shockwavee"&gt;@shockwavee&lt;/a&gt;, who wrote a great post about his &lt;a href="https://dev.to/bornfightcompany/my-journey-to-mastering-react-82n"&gt;journey to mastering React&lt;/a&gt;. Since I was recently promoted to (mid) Software Developer position, I wanted to reflect on some of the most important parts of the journey from junior position to the new one, &lt;em&gt;&lt;a href="https://bornfight.com/resources/bornfight-seniority-positions-advancements-and-expectations?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=seniority_2020&amp;amp;utm_term=Maroje_seniority&amp;amp;utm_content=personalprofile_Maroje" rel="noopener noreferrer"&gt;in Bornfight&lt;/a&gt;&lt;/em&gt;. Why am I explicitly saying "in Bornfight"? Because every company has its own understanding &amp;amp; vision of seniority levels. This is just one of many things I’ve learned, and which I want to share with others, who might find it helpful, motivational or just interesting to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prior experience / background
&lt;/h2&gt;

&lt;p&gt;Before coming to Bornfight, as a student in my final year, I worked full-time for 6 months in a small company (there were 2 of us, me and the boss). Projects were both interesting and more complex (e.g. enterprise softwares for banks). This opportunity allowed me to get hands-on experience with a PHP framework I’ve been learning in my free time - Laravel. I look at that period as a great start for someone new in the industry.&lt;/p&gt;

&lt;p&gt;Since both of us in the company were not very experienced developers, I quickly realised that my growth could not be fast as I wanted to.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I was longing for experienced surroundings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For a moment, I even thought that getting a raise could fill that gap, but it couldn’t.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changing job
&lt;/h3&gt;

&lt;p&gt;Naturally, I started to look for another job. Knowledge and confidence gained here helped me in the interviews, technical questions and job assignments, which ended in getting 2 job offers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Working on a custom software products with Symfony framework, &lt;strong&gt;lower salary&lt;/strong&gt; than current, 50+ sized &lt;strong&gt;local&lt;/strong&gt; agency (out of which are 15+ people in development department)&lt;/li&gt;
&lt;li&gt;Working with Drupal (CMS) on a websites, much &lt;strong&gt;better salary&lt;/strong&gt; than current, 20+ sized &lt;strong&gt;international&lt;/strong&gt; agency with only 1 person in the local country with whom I would be working with&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To be honest, the second offer (or “higher salary &amp;amp; international company”) sounded amazing, at first. After some rethinking and discussion with others, everything was pointing to the question of why did I even start to look for other opportunities? It definitely wasn’t about the money. Even though the second option had some great perks, it didn’t offer the most important one. I wanted to be surrounded with a bigger development team, with much more experience than me.&lt;/p&gt;

&lt;h2&gt;
  
  
  An overwhelming feeling
&lt;/h2&gt;

&lt;p&gt;In late April of 2019, I started to work at Bornfight.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun fact: it was exactly one day after my birthday, so it increased that “new chapter in life” feeling, which I usually have after birthdays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first month was quite incredible. So many new things, modern working place, new faces (and forgotten names), a lot of meetings in different rooms, various departments and colleagues with different energies, new technologies and tools to work with… yes, it was overwhelming. To sum it up, it was a professional environment which included a lot of new working aspects all at once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project challenges
&lt;/h3&gt;

&lt;p&gt;Less than 2 weeks later, I was put on a completely new project. That challenge brought a lot of smaller ones with itself. To name a few:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;working in a team hierarchy with different responsibilities&lt;/li&gt;
&lt;li&gt;collaborating with different departments (frontend, design &amp;amp; PM)&lt;/li&gt;
&lt;li&gt;separating backend’s tasks &amp;amp; responsibilities in my mindset from frontend ones (since I previously did everything)&lt;/li&gt;
&lt;li&gt;communicating with clients in foreign language&lt;/li&gt;
&lt;li&gt;giving estimates for tasks, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Giving extra and comparing with others
&lt;/h2&gt;

&lt;p&gt;Depending on the person, moments in life like this one can go in different directions. In order to feel more comfortable in day-to-day tasks, a junior &lt;em&gt;should&lt;/em&gt; spend some of the free time to learn more about the vast number of challenges in front of him/her. Especially if your goal is to distinguish yourself from the others or to get a promotion quicker.&lt;/p&gt;

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

&lt;p&gt;But, do you need to? It took me longer than I would want, to realise that &lt;strong&gt;everyone has a different path&lt;/strong&gt; (and therefore different speed of getting to specific outcome). It's normal to compare yourself with your peers, and I'm not saying that everything will always be fair, but try to be as objective as possible when comparing. Bear in mind that you might not even have a clear picture of how good or bad someone is, or that the seniors might not be aware of some of the good things you've done. After all that, even after doing your best, promotion might come just because your colleague(s) left the company and a spot with new responsibilities opens up!&lt;/p&gt;

&lt;h2&gt;
  
  
  Burnout
&lt;/h2&gt;

&lt;p&gt;I believe that most (if not all) developers get to this point in their career, at least once.&lt;/p&gt;

&lt;p&gt;This happened to me a few times so far. Mostly, it was because I've created an unnecessary burden for myself with a few misconceptions and bad practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;giving an estimate which PM wants to hear, instead of the one which is correct (i.e. higher estimate)&lt;/li&gt;
&lt;li&gt;giving a wrong estimate means that I need to work overtime for free, just so I could continue the next day without being late with my tasks&lt;/li&gt;
&lt;li&gt;delivered code needs to be the best possible, without taking into matter the effort and value behind each solution&lt;/li&gt;
&lt;li&gt;being wrong is bad (it isn't, just communicate it on time and be careful not to repeat it again)&lt;/li&gt;
&lt;li&gt;expecting that every process in the workflow is already set and it's working smoothly&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A combination of things mentioned throughout the whole post and bad organisational skills in terms of balancing work &amp;amp; private life, led to losing focus and worse health. When that happens, things can go down even faster. Company was also in the process of rearranging many processes and responsible people at the moment. To be honest, I felt so bad mentally, not only that I wanted to leave my job, but not to work at all for some time...&lt;/p&gt;

&lt;p&gt;In that state, quitting wouldn't be a bad call. In the meantime, the actual pandemic started and changing jobs wasn't an easy option as it might be earlier. Circumstances were changing often, I started to work remotely (which I discovered to be great for me), had more time to be in nature and have quality time with others... and I've managed to get through it all! 💪🏻 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Focus on what's important
&lt;/h3&gt;

&lt;p&gt;Even though it seems like a unique experience, I've realised that I've learned a lot in between, and that learning part was actually the key. When I got to the state that I feel confident in my knowledge and that I'm able to solve most of the tasks by myself, my focus improved. When focus came back, I could finally involve myself in some other things than just writing code, and use other abilities as well. Sooner than later, others started to recognise it, and step by step, things fell into place.&lt;br&gt;
So, in the beginning, maybe I just needed to focus mostly on bettering my core skills needed in the job, instead of focusing on many aspects just a little bit?&lt;/p&gt;

&lt;h3&gt;
  
  
  Take care of your health
&lt;/h3&gt;

&lt;p&gt;Additional personal advice for avoiding burnout would also be to stay both physically and mentally in shape. Our job requires our focus to be in a very good condition, and we often forget that accumulated stress should be thrown out of the system through different kinds of activities &amp;amp; good habits, based on personal preferences (e.g. sport, meditation, socialising/having fun, good sleep, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Since the post is already long enough, and I could write about this 1.5 year journey in the company much longer, I've decided to sum it up, with possibility to extend it through new post(s).&lt;/p&gt;

&lt;p&gt;I cannot think of any life experience from which I grew personally, that did not include both good &amp;amp; bad moments. If you find yourself in some of the situations above, embrace them, focus on the most important things you need to do (and are expected from you), and take care of your health. Then, everything will fall into place. And &lt;strong&gt;be patient&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Thanks again for reading my story. If you have any questions or would like to read more about it, let me know in the comments below. I really like to hear others' stories and experiences as well. Any additional advice for everyone would be greatly appreciated. Cheers!&lt;/p&gt;

</description>
      <category>career</category>
      <category>motivation</category>
      <category>beginners</category>
      <category>engineeringmonday</category>
    </item>
    <item>
      <title>How to improve your code quality with Psalm — a static analysis tool</title>
      <dc:creator>Maroje Macola</dc:creator>
      <pubDate>Mon, 29 Jun 2020 11:43:37 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/how-to-improve-your-code-quality-with-psalm-a-static-analysis-tool-419d</link>
      <guid>https://dev.to/bornfightcompany/how-to-improve-your-code-quality-with-psalm-a-static-analysis-tool-419d</guid>
      <description>&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;Before going into the main topic, let’s clarify some things. “Psalm” might be hinting at something religious, but it’s just a tool name, which is short for &lt;strong&gt;PHP Static Analysis Linting Machine&lt;/strong&gt;. It is meant for PHP developers — and it was made by the crew from &lt;a href="https://github.com/vimeo/psalm"&gt;Vimeo&lt;/a&gt;, who have &lt;a href="https://psalm.dev/articles/fixing-code-that-aint-broken"&gt;realised some 5 years ago&lt;/a&gt; that they could really use a tool which will help them find unspotted bugs and/or errors before releasing their code to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code quality tools
&lt;/h2&gt;

&lt;p&gt;Any tool which improves our code can be classified as a code quality tool. At Bornfight, we use several of them when developing with PHP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/FriendsOfPHP/PHP-CS-Fixer"&gt;PHPCSFixer&lt;/a&gt; — coding standards fixer, for enforcing single coding standard throughout the project&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sebastianbergmann/phpcpd"&gt;PHPCPD&lt;/a&gt; — copy/paste detector, for detecting duplicate code&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/phpmd/phpmd"&gt;PHPMD&lt;/a&gt; — mess detector, for enforcing rules in areas like clean code, code size, naming etc.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/phpstan/phpstan"&gt;PHPStan&lt;/a&gt; — static analysis tool, similar to Psalm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After reading the last bullet from the list, you may be asking yourself why is this post talking about Psalm, a static analysis tool that we don’t use (since it’s not on the list), and not about a similar tool, PHPStan, which we actually use. Well, my dear reader, I find that the best way to force yourself to research a topic is by writing a post or holding an education for someone. More so, if the tool proves itself useful, it can be a great addition to the existing CI pipeline or maybe even a replacement for PHPStan. Anyway, let’s go deeper into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static… what?!
&lt;/h2&gt;

&lt;p&gt;So, “Static Analysis Linting Machine”? Those are some quite powerful words. Static analysis obviously means that it analyses something, in this case our code, but without executing it. Word “lint” has multiple definitions online, and one of the non-software-related ones I found is “&lt;strong&gt;&lt;em&gt;clinging fuzzy fluff that accumulates in one's pockets or navel&lt;/em&gt;&lt;/strong&gt;”. Okay, it doesn’t feel like it’s helping in explanation, but I will try to use it anyway. While writing code, we (should) try our best not to make bugs. Still, no matter how hard we try, over time, before releasing it to the production, &lt;strong&gt;codebase&lt;/strong&gt; (pocket) &lt;strong&gt;accumulates unspotted bugs&lt;/strong&gt; (clinging fuzzy fluff). And we should strive to have both our codebase and pockets clean. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's where Psalm steps in and helps us in achieving so&lt;/strong&gt; (at least for codebase, we still have to clean pockets ourselves).&lt;/p&gt;

&lt;h3&gt;
  
  
  Give me some features
&lt;/h3&gt;

&lt;p&gt;After cleaning up some questions around Psalm and static analysis tools, we are still asking ourselves, what kind of bugs or possible errors does it discover? Well, even though development with PHP can be enjoyable, it is important to be aware of its pros and cons. Since it’s an interpreted language, rather than compiled, it does not enforce type safety. &lt;/p&gt;

&lt;p&gt;Here’s a simple example of working code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doubleTheNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;doubleTheNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, it can also be written with type hints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doubleTheNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;doubleTheNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second way is much safer because, with type hints, we don’t allow passing non-integer values to the function, but also if we need to use the function's return value, we are sure that it will be an integer. &lt;/p&gt;

&lt;p&gt;If we passed an empty array, running Psalm would tell us something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ERROR: InvalidArgument - 8:22 - Argument 1 of doubleTheNumber expects int,
array&amp;lt;empty, empty&amp;gt; provided - https://psalm.dev/004
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool, right? Type-checking is its most important feature. Issues also contain links to the dedicated page (&lt;a href="https://psalm.dev/004"&gt;psalm.dev/004&lt;/a&gt; in this case), with its explanation and help in fixing. By investigating and resolving an error, we are actually &lt;strong&gt;learning how to write better code&lt;/strong&gt; and what are some of the bad practices in PHP and programming in general.&lt;/p&gt;

&lt;p&gt;If you think about adding Psalm to an existing codebase, but feel like it will throw too many type-related errors, there is also a solution. One of the features is called &lt;strong&gt;Psalter&lt;/strong&gt; (nope, we are still not talking about anything religious). It can fix a number of issues it finds, like adding missing type-hints, or even removing &lt;strong&gt;dead code&lt;/strong&gt;, like unused variables or functions.&lt;/p&gt;

&lt;p&gt;Another scenario could be that the codebase is massive and there is no time to fix all of the issues. But that does not mean that you should continue writing buggy code. And that’s where the &lt;strong&gt;Baseline&lt;/strong&gt; feature steps in — it allows you to grandfather-in all the errors found. It stores all the errors in a file and does not mention them ever again, but it will show every new error which is produced with new code written after activating Baseline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RBJAkHen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/ly8qw68tbcb1818a5onl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RBJAkHen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/ly8qw68tbcb1818a5onl.jpg" alt="Alt Text" width="600" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since Psalm checks for many types of errors, depending on the developers knowledge and other factors, it can be overwhelming to deal with all of them. That’s where level strictness comes in handy. There are 8 levels of strictness, where number 1 is the most strict. The stricter the level, the more error types are included, and vice versa.&lt;/p&gt;

&lt;p&gt;Sometimes, there is a need to exclude a whole directory from being analysed, or just a specific type error on a specific method. This can be done by suppressing the errors either within the configuration file or via a docblock. &lt;/p&gt;

&lt;p&gt;Here’s an example for the latter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'bar'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getBar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="cd"&gt;/** @psalm-suppress UnusedMethodCall */&lt;/span&gt;
&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any level of strictness would usually throw something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ERROR: UnusedMethodCall - 12:5 - The call to Foo::getBar is not used
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but it will not be mentioned as long as it’s suppressed.&lt;/p&gt;

&lt;p&gt;Since Psalm supports a large number of docblock annotations, it’s important to use them in order to utilize the most out of Psalm’s type-checking feature. It even has its own annotations, called template and assert annotations. Through research so far, I feel like they are a vital part of this tool, and maybe they will deserve their own blog post, after I manage to test them out more.&lt;/p&gt;

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

&lt;p&gt;Having non-typed code might be working at the moment, but working as a developer means to always think ahead. Writing any new code in such a codebase can be more stressful and scary, especially for a new developer on a project. As codebase gets larger and larger, and unpredicted bugs pop-up more often, introducing a static analysis tool, such as Psalm, can be very helpful in tackling those problems.&lt;/p&gt;

&lt;p&gt;Also, through dealing with Psalms issues and warnings in the codebase, developers are learning how to write better and maintainable code, which is something that every developer should strive for. Don’t forget, less bugs means happier clients, and there’s no need to say how important that is in business!&lt;/p&gt;

&lt;p&gt;If this post was useful to you and you’d like to know more about Psalm, let me know. After having some more practice with Psalm, I think I could write about more in-depth usage of it, or compare it with PHPStan and see where it goes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about you?
&lt;/h3&gt;

&lt;p&gt;What are your thoughts on the subject? If you have experience with Psalm in particular, or with any other static analysis tool, I would be glad to hear your opinion about it, so feel free to leave a comment below :)&lt;/p&gt;

</description>
      <category>php</category>
      <category>productivity</category>
      <category>programming</category>
      <category>engineeringmonday</category>
    </item>
    <item>
      <title>Switching between multiple Node versions with Node Version Manager</title>
      <dc:creator>Maroje Macola</dc:creator>
      <pubDate>Mon, 16 Mar 2020 08:06:25 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/switching-between-multiple-node-versions-with-node-version-manager-1jb6</link>
      <guid>https://dev.to/bornfightcompany/switching-between-multiple-node-versions-with-node-version-manager-1jb6</guid>
      <description>&lt;p&gt;Hello &lt;strong&gt;dev.to&lt;/strong&gt; readers!&lt;/p&gt;

&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;This is my very first post here and hopefully many more will be written. Even though I've worked only on PHP projects, it turned out that my first post here is about switching between Node versions by using the handy tool called &lt;a href="https://github.com/nvm-sh/nvm"&gt;Node Version Manager&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Package usage is intended for MacOS or Linux, but there are some alternatives for Windows, like &lt;a href="https://github.com/coreybutler/nvm-windows"&gt;nvm-windows&lt;/a&gt; and &lt;a href="https://github.com/nullivex/nodist"&gt;nodist&lt;/a&gt;. Those alternatives are created by other developers, so there may be some similarities with features, but carry on with reading at your own risk 😁&lt;/p&gt;

&lt;p&gt;To keep this post shorter and focused more on NVM's features, I will skip steps for installation. Nevertheless, here is a &lt;a href="https://gist.github.com/nijicha/e5615548181676873118df79953cb709"&gt;link for setup&lt;/a&gt;, if you're using &lt;strong&gt;Homebrew&lt;/strong&gt; (it helped me!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool usage
&lt;/h3&gt;

&lt;p&gt;After installation, you can check which Node versions you have installed by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nvm &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There should be none, at first. So, let's install newest Node version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;node
...
Now using node v13.10.0 &lt;span class="o"&gt;(&lt;/span&gt;npm v6.13.7&lt;span class="o"&gt;)&lt;/span&gt;
Creating default &lt;span class="nb"&gt;alias&lt;/span&gt;: default -&amp;gt; node &lt;span class="o"&gt;(&lt;/span&gt;-&amp;gt; v13.10.0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, when installing first Node version, it also automatically creates an alias for &lt;strong&gt;default&lt;/strong&gt; version.&lt;br&gt;
To install specific Node version, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;8.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can change the default Node version for every new terminal session by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nvm &lt;span class="nb"&gt;alias &lt;/span&gt;default 8.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have multiple Node versions installed, we can start switching between them by simply running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nvm use node
Now using node v13.10.1 &lt;span class="o"&gt;(&lt;/span&gt;npm v6.13.7&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;nvm use 8.0.0
Now using node v8.0.0 &lt;span class="o"&gt;(&lt;/span&gt;npm v5.0.0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, right? Do you see some potential benefits from this? Like running &lt;strong&gt;different&lt;/strong&gt; Node &lt;strong&gt;versions&lt;/strong&gt; in multiple terminals at the &lt;strong&gt;same time&lt;/strong&gt;? It's really awesome.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips
&lt;/h3&gt;

&lt;p&gt;For those reading all the way down here, here is a tip regarding &lt;strong&gt;aliases&lt;/strong&gt;: how about &lt;strong&gt;naming&lt;/strong&gt; them after your &lt;strong&gt;project’s name&lt;/strong&gt;? So you don’t need to think of, or search for project’s specific version. For example, here is an example of my alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nvm &lt;span class="nb"&gt;alias &lt;/span&gt;eotg 8.0.0
eotg -&amp;gt; 8.0.0 &lt;span class="o"&gt;(&lt;/span&gt;-&amp;gt; v8.0.0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;nvm use eotg
Now using node v8.0.0 &lt;span class="o"&gt;(&lt;/span&gt;npm v5.0.0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another extra tip/warning if you're using &lt;strong&gt;PHPStorm&lt;/strong&gt; (or probably any other IDE):&lt;br&gt;
If you need to run &lt;code&gt;npm install&lt;/code&gt; while running specific Node version, it's not enough to just set Node version with &lt;code&gt;nvm use 10.1.2&lt;/code&gt;. It's also necessary to set the correct Node version in your PHPStorm's &lt;strong&gt;preferences&lt;/strong&gt;, for its &lt;strong&gt;Node interpreter&lt;/strong&gt;. This bugged me longer than expected, so I'm writing it in hope that it might save someone the trouble 😌&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Node Version Manager is a simple, yet powerful tool which can save us a lot of time &amp;amp; trouble. Here are only a number of commands to get you started and make you see the value behind it.&lt;/p&gt;

&lt;p&gt;If you have some other tips, suggestions and/or experiences to share about Node Version Manager, let everyone else know in the comments below!&lt;/p&gt;

&lt;h6&gt;
  
  
  Cover image source - &lt;a href="https://miro.medium.com/max/1050/0*csTuUtvi1VdLS4le.jpg"&gt;https://miro.medium.com/max/1050/0*csTuUtvi1VdLS4le.jpg&lt;/a&gt;
&lt;/h6&gt;

</description>
      <category>engineeringmonday</category>
      <category>nvm</category>
      <category>node</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
