Skip to content

Instantly share code, notes, and snippets.

@rashedInt32
Created September 17, 2021 19:55
Show Gist options
  • Save rashedInt32/84fe56994ffa086fb40fdde57559bc30 to your computer and use it in GitHub Desktop.
Save rashedInt32/84fe56994ffa086fb40fdde57559bc30 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:georss="http://www.georss.org/georss"
xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
<channel>
<title><![CDATA[ Adeva ]]></title>
<atom:link href="https://adevait.com/feed" rel="self" type="application/rss+xml" />
<link><![CDATA[ https://adevait.com/feed ]]></link>
<description><![CDATA[ Work without Boundaries ]]></description>
<language>en-US</language>
<item>
<title><![CDATA[ Step-By-Step Guide to Deploying Laravel Applications on Virtual Private Servers ]]></title>
<link><![CDATA[ https://adevait.com/laravel/deploying-laravel-applications-virtual-private-servers ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Developing modern full-stack web applications has become much easier thanks to Laravel but deploying them on a real server is another story. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There are just so many options. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>PaaS like Heroku or AWS Elastic Beanstalk, unmanaged virtual private servers, shared hosting, and so on.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Deploying a Laravel app on a shared server using cPanel is as easy as zipping up the source code along with all the dependencies and uploading it to the server. But on shared hosting, you don't have much control over the server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>PaaS like Heroku or AWS Elastic Beanstalk strikes a good balance between ease of usage and control, but they can be expensive at times. A standard 1x dyno from Heroku, for example, costs $25 per month and comes with only 512MB of RAM.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Unmanaged virtual private servers are affordable and provide a lot of control on the server. You can avail a server with 2GB of RAM, 20GB of SSD space, and 2TB of transfer bandwidth, costing only $15 per month.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now the problem with unmanaged virtual private servers is that they are unmanaged. You'll be responsible for installing all necessary software, configuring them, and keeping them updated.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this article, I'll guide you step-by-step in the process of how to deploy a Laravel project on an unmanaged virtual private server (we'll refer to it as VPS from now on). If you want to check out the benefits of the framework first, go ahead and get an answer to the question of <a href="https://adevait.com/laravel/pros-of-laravel-framework" target="_blank" rel="noreferrer noopener">why use the Laravel framework</a>. If you are ready, without any further ado, let's jump in.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Prerequisites</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The article assumes that you have previous experience with working with the Linux command-line. The server will use Ubuntu as its operating system, and you'll have to perform all the necessary tasks from the terminal. The article also expects you to understand basic concepts like Sudo, file permissions, differences between a root and non-root user, and git.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Project Code and Deployment Plan</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I've built a dummy project for this article. It's a simple question board application where users can post a question, and others can answer that question. You can consider this a dumbed-down version of StackOverflow.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4930,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/09/deploying-laravel-1.jpeg" alt="Deploying Laravel Applications on Virtual Private Servers" class="wp-image-4930"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The project source code is available on <a href="https://github.com/fhsinchy/guide-to-deploying-laravel-on-vps" target="_blank" rel="noreferrer noopener">https://github.com/fhsinchy/guide-to-deploying-laravel-on-vps</a> repository. Make a fork of this repository and clone it on your local computer.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once you have a copy of the project on your computer, you're ready to start the Laravel deployment process. You'll start by provisioning a new VPS and setting up a way for pushing the source from your local computer to the server.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Provisioning a New Ubuntu Server</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are several VPS providers out there, such as DigitalOcean, Vultr, Linode, and Hetzner. Although working with an unmanaged VPS is more or less the same across providers, they don't provide the same kind of services.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>DigitalOcean, for example, provides managed database services. Linode and Vultr, on the other hand, don't have such services. You don't have to worry about these differences. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I'll demonstrate only the unmanaged way of doing things. So regardless of the provider, you're using, the steps should be identical. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Before provisioning a new server, you’ll have to generate SSH keys.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Generating New SSH Keys</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>According to Wikipedia - "Secure Shell (SSH) is a cryptographic network protocol for operating network services securely over an unsecured network." It allows you to connect to a remote server using a password or a key-pair.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you're already familiar with SSH and have previously generated SSH key-pairs on your computer, you may skip this subsection. To generate a new key-pair on macOS, Linux, or Windows 10 machines, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">ssh-keygen -t rsa</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You'll see several prompts on the terminal. You can go through them by pressing enter. You don't have to put any password either. Once you've generated the key-pair, you'll find a file named id_rsa.pub inside the ~/.ssh/ directory. You'll need this file when provisioning a new VPS.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Provisioning a New VPS</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I've already said there are some differences between the VPS service providers, so if you want to be absolutely in line with this article, use DigitalOcean.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A single virtual private server on DigitalOcean is known as a droplet. On Vultr, it's called an instance, and on Linode, it's called a linode. Log into your provider of choice and create a new VPS. Use Ubuntu 20.04 LTS as the operating system.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For size, pick the one with 1GB of RAM and 25GB of SSD storage. It should cost you around $5 per month. For the region, choose the one closest to your users. I live in Bangladesh, and most of my users are from here, so I deploy my applications in the Singapore region.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Under the SSH section, create a new SSH key. Copy the content from the ~/.ssh/id_rsa.pub file and paste it as the content. Put a descriptive name for the key and save.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can leave the rest of the options untouched. Most of the providers come with an automatic backup service. For this demonstration, keep that option disabled. But in a real scenario, it can be a lifesaver. After the process finishes, you'll be ready to connect to your new server using SSH.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Performing Basic Setup</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that your new server is up and running, it's time to do some basic setup. First, use SSH with the server IP address to log in as the root user.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">ssh root@104.248.157.172</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You can find the server's IP address on the dashboard or inside the server details. Once you're inside the server, the first thing to do is create a new non-root user.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>By default, every server comes with the root user only. The root user, as you may already know, is very mighty. If someone manages to hack your server and logs in as the root user, the hacker can wreak havoc. Disabling login for the root user can prevent such mishaps.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Also, logging in using a key-pair is more secure than logging in using a password. So, disabling logging in using a password should be disabled for all users.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To create a new user from the terminal, execute the following command inside your server:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">adduser nonroot</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The name nonroot can be anything you want. I used nonroot as the name to make the fact clear that this is a non-root user. The adduser program will ask for a password and several other information. Put a strong password and leave the others empty.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After creating the user, you'll have to add this new user to the sudo group. Otherwise, the nonroot user will be unable to execute commands using sudo.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">usermod -aG sudo nonroot</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In this command, sudo is the group name, and nonroot is the username. Now, if you try to log into this account, you'll face a permission denied error.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4932,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/09/deploying-laravel-2.png" alt="Deploying Laravel Applications on Virtual Private Servers" class="wp-image-4932"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>It happens because most of the VPS providers disable login using a password when you add an SSH key to the server, and you haven't configured the new user to use SSH key-pairs. One easy way to fix this is to copy the content of /root/.ssh directory to the /home/nonroot/.ssh directory. You can use the rsync program to do this.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">rsync --archive --chown=nonroot:nonroot /root/.ssh /home/nonroot</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The --archive option for rsync copies directories recursively preserving symbolic links, user and group ownership, and timestamps. The --chown option sets the nonroot user as the owner in the destination. Now you should be able to log in as the new user using SSH.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After logging in as a non-root user, you should update the operating system, including all the installed programs on the server. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt update &amp;&amp; sudo apt upgrade -y &amp;&amp; sudo apt dist-upgrade -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Downloading and installing the updates will take a few minutes. During this process, if you see a screen titled "Configuring openssh-server" asking about some file changes, select the "keep the local version currently installed" option and press enter.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4933,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/09/deploying-laravel-3.png" alt="Deploying Laravel Applications on Virtual Private Servers" class="wp-image-4933"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>After the update process finishes, reboot the server by executing the sudo reboot command. Wait a few minutes for the server to boot again and log back in as a non-root user.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Deploying Code on the Server</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>After completing the basic setups, the next thing you'll tackle is deploying code on the server. I've seen people cloning the repository somewhere on the production server and logging into the server to perform a pull whenever there are some new changes to the code.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There is a much better way of doing this. Instead of logging into the server to perform a pull, you can use the server itself as a repository and push code directly to the server. You can also automate the post-deployment steps like installing dependencies, running the migrations, and so on, which will make the Laravel deploy to server an effortless action. But before doing all these, you'll first have to install PHP and Composer on the server.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Installing PHP</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You can find a list of PHP packages required by Laravel on the official <a href="https://laravel.com/docs/8.x/deployment#server-requirements" target="_blank" rel="noreferrer noopener">docs</a>. To install all these packages, execute the following command on your server:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt install php7.4-fpm php7.4-bcmath php7.4-json php7.4-mbstring php7.4-xml -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Depending on whether you're using MySQL or PostgreSQL, or SQLite in your project, you'll have to install one of the following packages:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt install php7.4-mysql php7.4-pgsql php7.4-sqlite3 -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The following package provides support for the Redis in-memory databases:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt install php7.4-redis</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Apart from these packages, you'll also need php-curl, php-zip, zip, unzip, and curl utilities.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt install zip unzip php7.4-zip curl php7.4-curl -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The question bank project uses MySQL as its database system and Redis for caching and running queues, so you'll have to install the php7.4-mysql and the php7.4-redis packages.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Depending on the project, you may have to install more PHP packages. Projects that work images, for example, usually depend on the php-gd package. Also, you don't have to mention the PHP version with every package name. If you don't specify a version number, APT will automatically install whatever is the latest.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>At the writing of this article, PHP 7.4 is the latest one on Ubuntu's package repositories but considering that the question board project requires PHP 7.4 and PHP 8 may become the default in the future, I've specified the version number in this article.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Installing Composer</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>After installing PHP and all the required packages on the server, now you're ready to install Composer. To do so, navigate to the official composer download <a href="https://getcomposer.org/download/" target="_blank" rel="noreferrer noopener">page</a> and follow the command-line installation instructions or execute the following commands:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
sudo php composer-setup.php --install-dir /usr/local/bin --filename composer
php -r "unlink('composer-setup.php');"</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now that you've installed both PHP and Composer on your server, you're ready to configure the automated deployment of your code.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Deploying Code Using Git</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>For automating code deployment on the server, log in as a non-root user and create a new directory under the <strong>/home/nonroot</strong> directory. You'll use this directory as the repository and push production code to it.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">mkdir -p /home/nonroot/repo/question-board.git</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The -p option to the mkdir command will create any nonexistent parent repository. Next, cd into the newly created directory and initialize a new bare git repository.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">cd /home/nonroot/repo/question-board.git
git init --bare</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>A bare is the same as a regular git repository, except it doesn't have a working tree. The practical usage of such a git repository is as a remote origin. Don't worry if you don't understand what I said just now. Things will become lucid as you keep going.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Assuming you're still inside the <strong>/home/nonroot/repo/question-board.git</strong> directory, cd inside the hooks subdirectory and create a new file called post-receive.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">cd hooks
touch post-receive</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Files inside this directory are regular shell scripts that git invokes when some major event happens on a repository. Whenever you push some code, git will wait until all the code has been received and then call the post-receive script.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Assuming you're still inside the hooks directory, open the post-receive script by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">nano post-receive</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now update the script's content as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">#!/bin/sh
sudo /sbin/deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>As you may have already guessed, <strong>/sbin/deploy</strong> is another script you'll have to create. The <strong>/sbin</strong> directory is mainly responsible for storing scripts that perform administrative tasks. Go ahead and touch the <strong>/sbin/deploy</strong> script and open it using the nano text editor.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo touch /sbin/deploy
sudo nano /sbin/deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now update the script's content as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">#!/bin/sh
git --work-tree=/srv/question-board --git-dir=/home/nonroot/repo/question-board.git checkout -f</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Evident by the <strong>#!/bin/sh</strong> line, this is a shell script. After that line, the only line of code in this script copies the content of the <strong>/home/nonroot/repo/question-board.git</strong> repository to the&nbsp; <strong>/srv/question-board </strong>directory.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here, the <strong>--work-tree</strong> option specifies the destination directory, and the <strong>--git-dir</strong> option specifies the source repository. I like to use the <strong>/srv</strong> directory for storing files served by this server. If you want to use the <strong>/var/www</strong> directory, go ahead.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Save the file by hitting Ctrl + O and exit nano by hitting Ctrl + X key combination. Make sure that the script has executable permission by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo chmod +x post-receive</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The last step to make this process functional is creating the work tree or the destination directory. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo mkdir /srv/question-board</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now you have a proper work tree directory, a bare repository, and a post-hook that in turn calls the <strong>/sbin/deploy</strong> script with sudo. But, how would the post-receive hook invoke the /sbin/deploy script using sudo without a password?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open the <strong>/etc/sudoers</strong> file on your server using the nano text editor and append the following line of code at the end of the file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">nonroot ALL=NOPASSWD: /sbin/deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This line of code means that the nonroot user will be able to execute the <strong>/sbin/deploy</strong> script with sudo on <strong>ALL</strong> hosts with <strong>NOPASSWD</strong> or no password. Save the file by pressing Ctrl + O and exit nano by pressing the Ctrl + K key combination.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Finally, you're ready to push the project source code. Assuming that you've already forked and cloned the <a href="https://github.com/fhsinchy/guide-to-deploying-laravel-on-vps" target="_blank" rel="noreferrer noopener">https://github.com/fhsinchy/guide-to-deploying-laravel-on-vps</a> repository on your local system, open up your terminal on the project root and execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">git remote add production ssh://nonroot@104.248.157.172/home/nonroot/repo/question-board.git</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Make sure to replace my IP address with the IP address from your server. Now assuming that the stable code is no the master branch, you can push code to the server by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">git push production master</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After sending the code to the server, log back in as a non-root user and cd into the <strong>/srv/question-board</strong> directory. Use the ls command to list out the content, and you should see that git has successfully checked out your project code.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Automating Post Deployment Steps</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Congratulations on you being able to deploy Laravel project on the server directly but, is that enough? What about the post-deployment steps? Tasks like installing or updating dependencies, migrating the database, caching the views, configs, and routes, restarting workers, and so on.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Honestly, automating these tasks is much easier than you may think. All you've to do is create a script that does all these for you, set some permissions, and call that script from inside the post-receive hook.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Create another script called post-deploy inside the <strong>/sbin</strong> directory. After creating the file, open it inside the nano text editor.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo touch /sbin/post-deploy
sudo nano /sbin/post-deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Update the content of the post-deploy script as follows. Don't worry if you don't clearly understand everything. I'll explain each line in detail.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">#!/bin/sh
cd /srv/question-board
cp -n ./.env.example ./.env
COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --optimize-autoloader
COMPOSER_ALLOW_SUPERUSER=1 composer update --no-dev --optimize-autoloader</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The first line changes the working directory to the <strong>/srv/question-board</strong> directory. The second line makes a copy of the <strong>.env.example</strong> file. The -n option makes sure that the cp command doesn't override a previously existing file.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The third and fourth commands will install all the necessary dependencies and update them if necessary. The <strong>COMPOSER_ALLOW_SUPERUSER</strong> environment variable disables a warning about running the composer binary as root.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Save the file by pressing Ctrl + O and exit nano by pressing Ctrl + X key combination. Make sure that the script has executable permission by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo chmod +x /sbin/post-deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Open the <strong>/home/nonroot/repo/question-board.git/hooks/post-receive</strong> script with nano and append the following line after the sudo /sbin/deploy script call:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo /sbin/post-deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Make sure that you call the post-deploy script after calling the deploy script. Save the file by pressing Ctrl + O and exit nano by pressing the Ctrl + K key combination.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open the <strong>/etc/sudoers</strong> file on your server using the nano text editor once again and update the previously added line as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">nonroot ALL=NOPASSWD: /sbin/deploy, /sbin/post-deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Save the file by pressing Ctrl + O and exit nano by pressing the Ctrl + K key combination. You can add more post deploy steps to this script if necessary.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To test the new post-deploy script, make some changes to your code, commit the changes and push to the production master branch. This time you'll see composer packages installation progress on the terminal and outputs from other artisan calls.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once the deployment process finishes, log back into the server, cd into the /srv/question-board directory, and list the content by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">ls -la</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Among other files and folders, you'll see a newly created vendor directory and an env file. At this point, you can generate the application encryption key required by Laravel. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo php artisan key:generate</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you look at the content of the .env file using the nano text editor, you'll see the APP_KEY value populated with a long string.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Installing and Configuring NGINX</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that you've successfully pushed the source code to the server, the next step is to install a web server and configure it to serve your application. I'll use NGINX in the article. If you want to use something else like Apache, you'll be on your own.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This article will strictly focus on configuring the webserver for serving a Laravel application and will not discuss NGINX-related stuff in detail. NGINX itself is a very complex software, and if you wish to learn NGINX from the ground up, <a href="https://www.freecodecamp.org/news/the-nginx-handbook/" target="_blank" rel="noreferrer noopener">The NGINX Handbook</a> is a solid resource.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To install NGINX on your Ubuntu server, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt install nginx -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This command should install NGINX and should also register as a systemd service. To verify, you can execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo systemctl status nginx</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You should see something as follows in the output:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4934,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/09/deploying-laravel-4.png" alt="Deploying Laravel Applications on Virtual Private Servers" class="wp-image-4934"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>You can regain control of the terminal by hitting q on your keyboard. Now that NGINX is running, you should see the default welcome page of NGINX if you visit the server IP address.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4935,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/09/deploying-laravel-5.png" alt="Deploying Laravel Applications on Virtual Private Servers" class="wp-image-4935"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>You'll have to change the NGINX configuration to serve your Laravel application instead. To do so, create a new file <strong>/etc/nginx/sites-available/question-board</strong> and open the file using the nano text editor.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo touch /etc/nginx/sites-available/question-board
sudo nano /etc/nginx/sites-available/question-board</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This file will contain the NGINX configuration code for serving the question board application. Configuring NGINX from scratch can be difficult, but the official Laravel <a href="https://laravel.com/docs/8.x/deployment#nginx" target="_blank" rel="noreferrer noopener">docs</a> have a pretty good configuration. Follows is the code copied from the docs:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">server {
listen 80;
server_name 104.248.157.172;
root /srv/question-board/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
&nbsp; &nbsp; try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt&nbsp; { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
&nbsp; &nbsp; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
&nbsp; &nbsp; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
&nbsp; &nbsp; include fastcgi_params;
}
location ~ /\.(?!well-known).* {
&nbsp; &nbsp; deny all;
}
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You don't have to make any changes to this code except the first two lines. Make sure you're using the IP address from your server as the <strong>server_name</strong> , and the <strong>root</strong> is pointing to the correct directory. You'll replace this IP address with a domain name in a later section.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Also, inside the <strong>location ~ \.php$ { }</strong> block, make sure that the <strong>fastcgi_pass</strong> directive is pointing to the correct PHP version. In this demonstration, I'm using PHP 7.4, so this configuration is correct. If you're using a different version, like 8.0 or 8.1, update the code accordingly.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you cd into the <strong>/etc/nginx</strong> directory and list out the content using the ls command, you'll see two folders named <strong>sites-available</strong> and <strong>sites-enabled</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The <strong>sites-available</strong> folder holds all the different configuration files serving applications (yes, there can be multiple) from this server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The <strong>sites-enabled</strong> folder, on the other hand, contains symbolic links to the active configuration files. So if you do not make a symbolic link of the <strong>/etc/nginx/sites-available/question-board</strong> file inside the <strong>sites-enabled</strong> folder, it'll not work. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo ln -s /etc/nginx/sites-available/question-board /etc/nginx/sites-enabled/question-board
sudo rm /etc/nginx/sites-enabled/default</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The second command gets rid of the default configuration file to avoid any unintended conflict. To test if the configuration code is okay or not, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo nginx -t</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If everything's alright, reload the NGINX configuration by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo nginx -s reload</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you visit your server IP address, you'll see that NGINX is serving your application correctly but the application is throwing a 500 internal server error.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4936,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/09/deploying-laravel-6.png" alt="Deploying Laravel Applications on Virtual Private Servers" class="wp-image-4936"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see, the application is trying to write to the logs folder but fails. It happens because the root user owns the /srv/question-board directory, and the www-data user owns the NGINX process. To make the /srv/question-board/storage directory writable by the application, you'll have to alter the directory permissions.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Configuring Directory Permissions</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are different ways of configuring directory permissions in a Laravel project but, I'll show you the one I use. First, you'll have to assign the <strong>www-data</strong> user that owns the NGINX process as the owner of the <strong>/srv/question-board</strong> directory as well. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo chown -R :www-data /srv/question-board</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Then, set the permission of the /srv/question-board/storage to 755, which means read and execute access for all users and write access for the owner by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo chmod -R 775 /srv/question-board/storage</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Finally, there is one more subdirectory that you have to make writable. That is the <strong>/srv/question-board/bootstrap/cache</strong> directory. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo chmod -R 775 /srv/question-board/bootstrap/cache</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you go back to the server IP address now and refresh, you should see that the application is working fine.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Installing and Configuring MySQL</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that you've successfully installed and configured the NGINX web server, it's time for you to install and configure MySQL. To do so, install the MySQL server by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt install mysql-server -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After the installation process finishes, execute the following command to make your MySQL installation more secure:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo mysql_secure_installation</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>First, the script will ask if you want to use the validate password component or not. Input "Y" as the answer and hit enter. Then, you'll have to set the desired level of password difficulty. I recommend setting it as high. Although picking a hard-to-guess password every time you want to create a new user can be annoying, but for the sake of security, roll with it. In the next step, set a secure password for the root user. You can put "Y" as the answer for the rest of the questions. Give the questions a read if you want to.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now, before you can log into your database server as root, you'll have to switch to the root user. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo su</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Log into your database server as root by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">mysql -u root</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Once you're in, create a new database for the question board application by executing the following SQL code:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">CREATE DATABASE question_board;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Next, create a new database user by executing the following SQL code:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">CREATE USER 'nonroot'@'localhost' IDENTIFIED BY 'password';</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Again, I used the name nonroot to clarify that this is a non-root user. You can use whatever you want as the name. Also, replace the word password with something more secure.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After that, provide the user full privilege of the question_board database to the newly created user by executing the following SQL code:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">GRANT ALL PRIVILEGES ON question_board . * TO 'nonroot'@'localhost';</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In this code, <strong>question_board.*</strong> means all the tables of the <strong>question_board</strong> database. Finally, quit the MySQL client by executing the <strong>\q</strong> command and exit the root shell by invoking the exit command.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now, try logging in as the nonroot user by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">mysql -u nonroot -p</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The MySQL client will ask for the password. Use the password you put in when creating the nonroot user. If you manage to log in successfully, exit the MySQL client by executing the \q command.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now that you have a working database server, it's time to configure the question board project to make use of it. First, cd into the /srv/question-board directory and open the env file using the nano text editor:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">cd /srv/question-board
sudo nano .env</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Update the database configuration as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=question_board
DB_USERNAME=nonroot
DB_PASSWORD=password</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Make sure to replace the username and password with yours. Save the file by pressing Ctrl + O and exit nano by pressing Ctrl + X key combination. To test out the database connection, try migrating the database by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">php artisan migrate --force</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If everything goes fine, that means the database connection is working. The project comes with two seeder classes, one for seeding the admin user and another for the categories. Execute the following commands to run them:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">php artisan db:seed --class=AdminUserSeeder
php artisan db:seed --class=CategoriesSeeder</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now, if you visit the server IP address and navigate to the /questions route, you'll see the list of categories. You'll also be log in as the admin user using the following credentials:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">email: farhan@questionboard.test
password: password</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you've been working with Laravel for a while, you may already know that it is common practice to add new migration files when there is a database change. To automate the process of running the migrations on every deployment, open the /sbin/post-deploy script using nano once again and append the following line at the end of the file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">php artisan migrate --force</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The <strong>--force</strong> option will suppress an artisan warning about running migrations on a production environment. Unlike migrations, seeders should run only once. If you add new seeders on later deployments, you'll have to run them manually.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Configure Laravel Horizon</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The question board project comes with Laravel Horizon pre-installed and pre-configured. Now that you have Redis up and running, you're ready to start processing jobs.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The official docs suggest using the supervisor program for running Laravel Horizon on a production server. To install the program, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo apt install supervisor -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Supervisor configuration files live within your server's /etc/supervisor/conf.d directory. Create a new file /etc/supervisor/conf.d/horizon.conf and open it using the nano text editor:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sudo touch /etc/supervisor/conf.d/horizon.conf
sudo /etc/supervisor/conf.d/horizon.conf</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Update the file's content as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">&#91;program:horizon]
process_name=%(program_name)s
command=php /srv/question-board/artisan horizon
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile=/var/log/horizon.log
stopwaitsecs=3600</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Save the file by pressing Ctrl + O and exit nano by pressing the Ctrl + X key combination. Now, execute the following commands to update the supervisor configuration and starting the horizon process:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>To test out if Laravel Horizon is running or not, visit your server's IP address and navigate to the /login page. Log in as the admin user and navigate to the /horizon route. You'll see Laravel Horizon in the active state.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I've configured Laravel Horizon to only let the admin user in, so if you log in with some other user credential, you'll see a 403 forbidden error message on the /horizon route.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One thing that catches many people off guard is that if you make changes to your jobs, you'll have to restart Laravel Horizon to read those changes. I recommend adding a line to the /sbin/post-deploy script to reinitiate the Laravel Horizon process on every deployment.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To do so, open the /sbin/post-deploy using the nano text editor and append the following line at the end of the file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo supervisorctl restart horizon</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This command will stop and restart the Laravel Horizon process on every deployment.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Configuring a Domain Name With HTTPS</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>For this step to work, you'll have to own a custom domain name of your own. I'll use the <strong>questionboard.farhan.dev</strong> domain name for this demonstration.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Log into your domain name provider of choice and go to the DNS settings for your domain name. Whenever you want a domain name to point to a server's IP address, you need to create a DNS record of type A.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To do so, add a new DNS record with the following attributes:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Type: A Record</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Host: questionboard</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Value: 104.248.157.172</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Make sure to replace my IP address with yours. If you want your top-level domain to point to an IP address instead of a subdomain, just put a @ as the host.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now go back to your server and open the /etc/nginx/sites-available/questionboard config file using the nano text editor. Remove the IP address from the server_name directive and write your domain name. Do not put HTTP or HTTPS at the beginning.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can put multiple domain names such as the top-level domain and the www subdomain separated by spaces. Save the configuration file by pressing Ctrl + O and Ctrl + X key combination. Reload NGINX configuration by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo nginx -s reload</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now you can visit your application using your domain name instead of the server's IP address. To enable HTTPS on your application, you can use the certbot program.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To do so, install certbot by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo snap install --classic certbot</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>It is a python program that allows you to use free SSL certificates very easily. After installing the program, execute the following command to get a new certificate:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo certbot --nginx</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>First, the program will ask for your email address. Next, it'll ask if you agree with the terms and agreements or not.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Then, It'll ask you about sharing your email address with the Electronic Frontier Foundation.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the third step, the program will read the NGINX configuration file and extract the domain names from the <strong>server_name</strong> directive. Look at the domain names it shows and press enter if they are all correct. After deploying the new certificate, the program will congratulate you, and now you've got free HTTPS protection for 90 days.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After 90 days, the program will attempt to renew the certificate automatically. To test the auto-renew feature, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo certbot renew --dry-run</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If the simulation succeeds, you're good to go.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Configuring a Firewall</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Having a properly configured firewall is very important for the security of your server. In this article, I'll show you how you can configure the popular UFW program.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>UFW stands for uncomplicated firewall, and it comes by default in Ubuntu. You'll configure UFW to, by default, allow all outgoing traffic from the server and deny all incoming traffic to the server. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo ufw default deny incoming
sudo ufw default allow outgoing</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Denying all incoming traffic means that no one, including you, will be able to access your server in any way. The next step is to allow incoming requests in three specific ports. They are as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Port 80, used for HTTP traffic.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Port 443, used for HTTPS traffic.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Port 22, used for SSH traffic.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To do so, execute the following commands:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo ufw allow http
sudo ufw allow https
sudo ufw allow ssh</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Finally, enable UFW by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sudo ufw enable</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>That's pretty much it. Your server now only allows HTTP, HTTPS, and SSH traffic coming from the outside, making your server a bit more secure.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Laravel Post-deployment Optimizations</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Your application is now almost ready to accept requests from all over the world. One last step that I would like to suggest is caching the Laravel configuration, views, and routes for better performance.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To do so, open the <strong>/sbin/post-deploy</strong> script using the nano text editor and append the following lines at the end of the file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">php artisan config:cache
php artisan route:cache
php artisan view:cache</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now, on every deployment, the caches will be cleared and renewed automatically. Also, make sure to set the <strong>APP_ENV</strong> to <strong>production</strong> and <strong>APP_DEBUG</strong> to <strong>false</strong> inside the env file. Otherwise, you may unintentionally compromise sensitive information regarding your server.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I would like to thank all <a href="https://adevait.com/laravel" target="_blank" rel="noreferrer noopener">Laravel developers</a> for the time they've spent reading this article. I hope you've enjoyed it and have learned some handy stuff regarding application deployment. If you want to learn more about NGINX, consider checking out my open-source <a href="https://www.freecodecamp.org/news/the-nginx-handbook/" target="_blank" rel="noreferrer noopener">NGINX Handbook</a> with tons of fun content and examples.<br><br>Also, if you want to broaden your knowledge of Laravel, you can check the <a href="https://adevait.com/laravel/laravel-vs-symfony-comparison" target="_blank" rel="noreferrer noopener">Laravel vs Symfony</a>, the <a href="https://adevait.com/laravel/using-corcel-in-laravel" target="_blank" rel="noreferrer noopener">Laravel Corcel</a>, and <a href="https://adevait.com/laravel/developing-an-ico-using-laravel" target="_blank" rel="noreferrer noopener">Laravel Blockhain</a> articles.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>If you have any questions or confusion, feel free to reach out to me. I'm available on <a href="https://twitter.com/frhnhsin" target="_blank" rel="noreferrer noopener">Twitter</a> and <a href="https://www.linkedin.com/in/farhanhasin/" target="_blank" rel="noreferrer noopener">LinkedIn</a> and always happy to help. Till the next one, stay safe and keep on learning.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Laravel</category>
<author>Farhan Hasin Chowdhury</author>
<pubDate>Thu, 16 Sep 2021 20:02:28 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Deploying Laravel API on AWS Lambda ]]></title>
<link><![CDATA[ https://adevait.com/laravel/deploying-laravel-api-on-aws-lambda ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>AWS Lambda brought the term "serverless" into reality and shook the world of software development. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It gained a lot of popularity in the last few years and is one of the fastest-growing technologies provided by Amazon. One of its strengths is the ability to pay only for the amount of time it takes to run the code and pay nothing while the code isn't running. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To accomplish this business model, AWS made Lambda scalable by default. You only provide the amount of memory your process needs and the cloud provider will be responsible for provisioning as much hardware as necessary every time your source code needs to be executed. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I have been working with AWS for 4 years and AWS Lambda in particular for 2 years. In this post, I want to share hands-on experience on deploying a Laravel API service on AWS Lambda.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Requirements</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To follow along, you'll need a few ingredients:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- AWS Account</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- IAM Access Key / Secret Key</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- PHP</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- [Composer](https://getcomposer.org/download/)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- [NPM](https://nodejs.org/en/download/)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- [Serverless](https://goserverless.com)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- [Bref](https://bref.sh)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- [Laravel](https://laravel.com)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>- [Optional] Docker</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you have an AWS Account already, everything else is manageable. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's get started!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>IAM Access</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let's first start by generating programmatic access to AWS. We'll need it so that we can provide the Serverless Framework with the ability to provision/deploy AWS lambda into our AWS account.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Log into your AWS account and go to IAM → Users → Add User. Choose a username for your account, check the <strong>Programmatic Access</strong> checkbox, and hit <strong>Next: Permission</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Under&nbsp;<strong>Attach existing policies directly</strong>, select the <strong>AdministratorAccess</strong> policy. We can now proceed to <strong>Next: Tags</strong> and subsequently <strong>Next: Review</strong> (Tags are optional). </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Take this opportunity to double-check the configuration. Once you click <strong>Create User</strong>, AWS will show you the <strong>Access Key</strong> and <strong>Secret Key</strong>. The Secret Key is unrecoverable, so make sure to save it.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>PHP, Composer, NPM, and Severless</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>If you have these tools installed in your environment, you may skip this step. Otherwise, I'll show you how I install these tools inside a docker container.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><strong>#!/usr/bin/env sh
docker run --rm -v $(pwd):/app -w /app -it alpine:3.14 sh
</strong>
apk add php8 php8-phar php8-curl php8-openssl php8-dom php8-xml php8-xmlwriter php8-xmlreader php8-tokenizer php8-mbstring php8-fileinfo php8-simplexml
apk add composer npm
cp /usr/bin/php8 /usr/bin/php
npm install -g serverless</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This sequence of commands will start an Alpine Linux container and install PHP 8, Composer, NPM, and Serverless. Keep this container open because we'll continue using it for the next steps.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Laravel and Bref</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let's start a new Laravel project and install Bref using Composer.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><strong><em>#!/usr/bin/env sh
</em></strong><em>
composer create-project laravel/laravel my-api
cd my-api
composer require bref/bref
./vendor/bin/bref init
0
rm index.php</em></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The <em>0</em> above is to automatically select the option <em>[0] Web application</em>. Bref will then create <em>serverless.yml</em> and <em>index.php</em>. Since we're using Laravel, we can remove the <em>index.php</em> and just keep the <em>serverless.yml</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Before we move on to Serverless, let's add a sample routing for our API by editing the <em>routes/api.php</em> file.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><strong>&lt;?php</strong>
Route::get('/hello', fn () =&gt; response(&#91;'data' =&gt; 'Hello from Laravel!']));</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Remember that by default the <em>api.php</em> folder is configured with the <em>/api</em> prefix, so our route will actually be <em>/api/hello</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Serverless</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Before we dive into the <em>serverless.yml</em> template, let's configure the Serverless Framework. We can do that in two ways:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><em>export AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY_HERE
export AWS_SECRET_ACCESS_KEY=YUR_SECRET_KEY_HERE</em></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The framework will automatically pick up the credentials from the environment variable and perform deployments into your account.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The 2nd approach is to use <em>serverless config credentials</em>:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><em>serverless config credentials --provider aws --key YOUR_ACCESS_KEY_HERE --secret YOUR_SECRET_KEY_HERE</em></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After configuring the credentials for your AWS account, let's tweak the <em>serverless.yml</em> template generated by Bref:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">service: app
provider:
&nbsp; name: aws
&nbsp; region: us-east-1
&nbsp; runtime: provided.al2
plugins:
&nbsp; - ./vendor/bref/bref
functions:
&nbsp; api:
&nbsp; &nbsp; handler: public/index.php
&nbsp; &nbsp; environment:
&nbsp; &nbsp; &nbsp; &nbsp; LOG_CHANNEL: stderr
&nbsp; &nbsp; &nbsp; &nbsp; SESSION_DRIVER: array
&nbsp; &nbsp; &nbsp; &nbsp; CACHE_DRIVER: array
&nbsp; &nbsp; description: ''
&nbsp; &nbsp; timeout: 28 <em># in seconds (API Gateway has a timeout of 29 seconds)</em>
&nbsp; &nbsp; layers:
&nbsp; &nbsp; &nbsp; - ${bref:layer.php-80-fpm}
&nbsp; &nbsp; events:
&nbsp; &nbsp; &nbsp; - httpApi: '*'
<em># Exclude files from deployment</em>
package:
&nbsp; patterns:
&nbsp; &nbsp; - '!node_modules/**'
&nbsp; &nbsp; - '!tests/**'</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>We change the <em>handler</em> from <em>index.php</em> to <em>public/index.php</em> as that's the entry point for a Laravel application. There are also 3 important environment variables: <em>LOG_CHANNEL</em>, SESSION_DRIVER, and <em>CACHE_DRIVER</em>. The <em>stderr</em> driver will automatically drive log messages into CloudWatch and the <em>array</em> driver will essentially disable Session and Cache.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Deployment</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To deploy the project, let's issue the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">sls deploy</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The output should look like this:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">/app/my-api <em># sls deploy</em>
Serverless: Deprecation warning: Detected ".env" files. In the next major release variables from ".env" files will be automatically loaded into the serverless build process. Set "useDotenv: true" to adopt that behavior now.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; More Info: https://www.serverless.com/framework/docs/deprecations/<em>#LOAD_VARIABLES_FROM_ENV_FILES</em>
Serverless: Deprecation warning: Resolution of lambda version hashes was improved with better algorithm, which will be used <strong>in</strong> next major release.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Switch to it now by setting "provider.lambdaHashingVersion" to "20201221"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; More Info: https://www.serverless.com/framework/docs/deprecations/<em>#LAMBDA_HASHING_VERSION_V2</em>
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Service files not changed. Skipping deployment...
Service Information
service: app
stage: dev
region: us-east-1
stack: app-dev
resources: 11
api keys:
&nbsp; None
endpoints:
&nbsp; ANY - https://0000000000.execute-api.us-east-1.amazonaws.com
functions:
&nbsp; api: app-dev-api
layers:
&nbsp; None</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You can use your endpoint to test the API. It should look like this:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">https://your_api_gateway_id.execute-api.us-east-1.amazonaws.com/api/hello</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This is pretty much it! Your source code is now available behind API Gateway and Lambda and you'll only pay for the time it takes for your code to execute.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Enforcing JSON Response</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>If we try to load an invalid route, say <em>https://your_api_gateway_id.execute-api.us-east-1.amazonaws.com/whatever</em>, we'll get a fatal error because Laravel will try to write the compiled php files for Blade. We can fix that by adjusting the <em>VIEW_COMPILED_PATH</em> environment variable. But since the focus is to deploy API-based projects, we can also add a nice little middleware to enforce that every HTTP Response will be JSON.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><strong>&lt;?php</strong>
<strong>namespace</strong> <strong>App</strong>\<strong>Http</strong>\<strong>Middleware</strong>;
<strong>use</strong> <strong>Closure</strong>;
<strong>class</strong> <strong>EnforceJsonResponse</strong>
{
&nbsp; &nbsp; <strong>public</strong> <strong>function</strong> <strong>handle</strong>($request, Closure $next)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; $request-&gt;headers-&gt;set('Accept', 'application/json');
&nbsp; &nbsp; &nbsp; &nbsp; <strong>return</strong> $next($request);
&nbsp; &nbsp; }
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Then we can register it inside <em>Kernel.php</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This introduction to Serverless with Laravel gives an overview of the foundation behind treating AWS Lambda as a hosting provider that only charges for execution time. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Although it is important to consider the aspect of running code on a read-only environment (with limited disk space under <em>/tmp</em>) and how two requests may not share the same live "container", this approach doesn't have a strong impact on the development practices and day-to-day operation of developers. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Providing APIs behind AWS Lambda makes them highly scalable and cheap if you have little to no usage at night or weekends, for instance.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Laravel</category>
<author>Marco Aurélio Deleu</author>
<pubDate>Tue, 24 Aug 2021 20:03:21 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Understanding the Aggregation Pipeline in MongoDB for Building Applications ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/aggregation-pipeline-mongodb-building-applications ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>The word '<a target="_blank" href="https://docs.mongodb.com/manual/core/aggregation-pipeline/" rel="noreferrer noopener">Aggregation Pipeline</a>' was coined from the word 'Aggregation' and Aggregation simply means the formation of several things into a cluster. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In simple terms, Aggregation in MongoDB can process data in a <a target="_blank" href="https://docs.mongodb.com/manual/core/databases-and-collections/" rel="noreferrer noopener">MongoDB Collection</a> and produce results. This article will give a detailed explanation with examples of the Aggregation Pipeline in MongoDB and illustrations showing how the Aggregation Pipeline works!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>I will also include real-life examples of the use cases of the Aggregation Pipeline, describing the use of <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/" rel="noreferrer noopener">Aggregation Stages</a> with examples. I will show you how these Aggregation Stages work in an actual code example using Nodejs and a MongoDB Collection to build a simple application.&nbsp;<br></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With this introduction, let’s see what the Aggregation Pipeline is!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>What Is an Aggregation Timeline? </h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You need to understand what the Aggregation Framework is in MongoDB before jumping into the Aggregation Pipeline.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The Aggregation Framework is simply a framework like any other framework such as the React and Vue.js frameworks for JavaScript applications.&nbsp;Although, the Aggregation Framework has its unique purpose, that is, what it is used for.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>The Aggregation Framework in MongoDB is used for running various analyses on several MongoDB Collections.&nbsp;Analyses like filtering some data from a given Collection in the database and performing operations on the data like getting the data based on some conditions that may be defined in Stages called <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/" rel="noreferrer noopener">Aggregation Stages</a>.&nbsp;The Aggregation Framework performs these analyses via the Aggregation Pipeline.&nbsp;<br></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Look at the illustration below, which shows a typical representation of the Aggregation Pipeline.</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626281607748_aggregation+pipeline+illustration.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>From the illustration above, you can see that the Aggregation Pipeline works with MongoDB Collections by accepting a single MongoDB Collection and passing this Collection through some or multiple stages. With these stages, you can perform operations on the Collection. As the Pipeline name implies, the document from the collection is taken as an input from one stage and is passed into the next stage in the Pipeline as an input.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>At the end of the Pipeline, there will be just one output which is then transformed or Aggregated data!<br></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One of the functionalities of the Aggregation Pipeline is the ability to process the data from a given MongoDB Collection and not necessarily save the result in the Collection but perform more processes/analysis on the data and return the desired result (Aggregated data).</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Real World Use Cases Of the Aggregation Pipeline</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are many areas where the Aggregation Pipeline can be applied. These areas of application are what I refer to as the use cases of the Aggregation Pipeline. An application area or use case of the Aggregation Pipeline is in a real-world application that involves Users’ Transactions.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>In building this real-world application, there may be a challenge with data fetching. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For instance, this application is built with a database, and let’s assume MongoDB is the database that is used to store data for this application. MongoDB deals with Collections, and so for this application, we have two Collections. One Collection is for the Users and the second Collection is for the Transactions performed on the application by the Users.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>If this application is been built by you, you will need to keep track of which of the Users perform Transactions on your application! To be able to keep track of the Transaction processes done by Users on your application, you will have the documents in your Transaction Collection linked to the Users in the Users Collection, by the User ID.<br></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Next, you have the User Collection in your application’s database, which is an independent Collection. Then, you have the Transaction Collection which is a dependent Collection that is dependent on the User Collection. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you have a view on the frontend of your application that will show the Transactions as well as the Users that performed the Transactions, with the Users’ information and not only the Users’ ID, you will need to be able to pull Transactions. Then, those Transactions will pull the Users’ information!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>In this case, you will need to create an Aggregation Pipeline that will analyze the data in your database and return your desired result or Aggregated data.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>First, you will create an Aggregation Pipeline that pulls the Transaction. Then, the Aggregation Pipeline created will pull the Users that performed those Transactions while appending the Users’ details to the Transaction Collection.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>Now that you have a fully modified document with all the details of the data that you need, you do not need to call Transaction first, or to begin a search for the Users in the Users Collection one by one. So, the Aggregation Pipeline does everything for you, that is, it gets the Transaction and the Users’ information from the Collection. Then, you can get that Aggregated data result to the front-end of your application!<br></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s get more practical and write some code!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>The Syntax of the Aggregation Pipeline </strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this section, you will learn how to work with the Aggregation Pipeline; the Aggregation Stages, and with MongoDB Collections. To follow along with this tutorial, ensure you have the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Nodejs, Express, and Git (Install<a target="_blank" href="https://nodejs.org/en/download/" rel="noreferrer noopener"> </a><a target="_blank" href="https://nodejs.org/en/download/" rel="noreferrer noopener"><u>Nodejs</u></a>,<a target="_blank" href="https://github.com/git-guides/install-git" rel="noreferrer noopener"> </a><a target="_blank" href="https://github.com/git-guides/install-git" rel="noreferrer noopener"><u>Git</u></a>)</li><li>Visual Studio Code editor (Install<a target="_blank" href="https://code.visualstudio.com/download" rel="noreferrer noopener"> </a><a target="_blank" href="https://code.visualstudio.com/download" rel="noreferrer noopener"><u>here</u></a>)</li><li>Postman account (Install<a target="_blank" href="https://www.postman.com/downloads/" rel="noreferrer noopener"> </a><a target="_blank" href="https://www.postman.com/downloads/" rel="noreferrer noopener"><u>here</u></a>)</li><li>MongoDB (Download<a target="_blank" href="https://docs.mongodb.com/manual/installation/" rel="noreferrer noopener"> </a><a target="_blank" href="https://docs.mongodb.com/manual/installation/" rel="noreferrer noopener"><u>here</u></a>)</li><li>MongoDB Compass (Download<a target="_blank" href="https://www.mongodb.com/try/download/compass" rel="noreferrer noopener"> </a><a target="_blank" href="https://www.mongodb.com/try/download/compass" rel="noreferrer noopener"><u>here</u></a>)</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Let’s Begin!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>We are going to create a simple application with Nodejs and use MongoDB as the database with the following steps:</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Setting up the File Structure</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let’s start with setting up the working directory for this application:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>In your terminal, type the following command with the name of the folder ‘TransactionApp’:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>mkdir TransactionApp</code></code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Next, change the directory into the ‘TransactionApp` working directory with the following command:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>cd TransactionApp</code></code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Inside the directory, run the following command to open this folder in your Code editor:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>code .</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The following window will be opened as shown below:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626423657831_TA+VScode.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>With your VS code opened, create a file <code>server.js</code> in the TransactionApp directory as shown below:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626425106371_TA+empty+server.js+file.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>In your VS Code, at the top of the editor, click on Terminal &gt; New Terminal, and a terminal window will be opened in VS Code:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626425744772_TA+terminal+open.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Next, initialize your application with the following command that creates the <code>package.json</code> file, which will contain information about your application:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>npm init</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After running this command, you will be prompted to enter basic information for your application, like this:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626426448528_TA+npm+init+asking+name.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>At the prompt, type <code>transaction</code> as the name of your application. Then, click enter for the other prompts, but when you are prompted for the author’s name, type your name as the owner of the application. Then, click ‘Enter’ and your package.json file will be created as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626426769754_TA+package.json+file+created.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Next, you need to install some npm packages as dependencies for your application:<ul><li>To install the <code>express, morgan, body-parser, and mongoose</code> packages for your application, run the following command in your terminal:</li></ul></li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>npm install express mongoose morgan body-parser</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Then, you can check the uses of these packages by clicking on these links: <a target="_blank" href="https://expressjs.com/" rel="noreferrer noopener">express</a>, <a target="_blank" href="https://mongoosejs.com/" rel="noreferrer noopener">mongoose</a>, <a target="_blank" href="https://www.npmjs.com/package/morgan" rel="noreferrer noopener">morgan</a>, <a target="_blank" href="https://www.npmjs.com/package/body-parser" rel="noreferrer noopener">body-parser</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>Once this command runs successfully, open your package.json file, you will see the packages installed as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626427318828_TA+package.json+file+with+dependencies.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>To use the packages that you just installed in your application, you need to require them in your ‘server.js’ file. In your ‘server.js’ file, include the following code:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>const express = require('express');const mongoose = require('mongoose');const morgan = require('morgan');const bodyParser = require('bodyParser');</code></code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>After requiring the packages, you need to connect to your database with the mongoose package that you required.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>To choose your connection string to use to connect to your database, using MongoDB Compass, sign in to your account <a target="_blank" href="https://account.mongodb.com/account/login" rel="noreferrer noopener">here</a>. Once, you’ve signed in, your dashboard window will be opened as follows:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626429687303_TA+mongodb+Atlas.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Then once your MongoDB Dashboard is opened, click on the Connect button showing on your screen to choose your connection method. For this tutorial, we are using the MongoDB Compass connection method as shown below:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626429844839_TA+mongodb+compass+connection+method.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>With that window opened, click the <code>Connect using MongoDB Compass</code> connection method, the following window will then be opened:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626429979089_TA+I+have+mongoDB+compass.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Ensure that you have MongoDB Compass installed, then choose the highlighted green<code> I have MongoDB Compass</code> option.&nbsp;In <code>2</code> where you can see <code>Copy the connection string, then open MongoDB Compass</code>, below that you will see your database connection string. Copy that connection string to your clipboard, as you will be using it in your application.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>Then, click on the close button to close the window.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Open your MongoDB Compass and paste the connection string you copied to where you see <code>Paste your connection string</code> as seen below:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626430385142_TA+Mongdb+compass+window.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Paste the connection string and ensure you put the right password, which you can set <a target="_blank" href="https://cloud.mongodb.com/v2/60ace9365982a22a20abee1a#security/database/users" rel="noreferrer noopener">here</a> and click the <code>Connect</code> green button. This window will be opened showing a list of your Databases:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626430787873_TA+Mongodb+Compass+Database.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>For connecting to your database, in your Code editor open the <code>server.js</code> file and type the following code:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>mongoose.connect('mongodb+srv://&lt;your password&gt;:&lt;password&gt;@cluster0.sagwd.mongodb.net/&lt;database Name&gt;', {useNewUrlParser: true, useUnifiedTopology: true})</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Replacing ‘&lt;your password&gt;’ with your password and ‘&lt;database Name&gt;’ with the name of your database in MongoDB as follows:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>db.on('error', (err) =&gt; {&nbsp; console.log(err);});
db.once('open', () =&gt; {&nbsp; console.log('Database Connection Established')});</code></code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Next, we need to instantiate the application with express and use the morgan and body-parser module we installed. Then, declare the PORT that the application will listen to and run on 3000. Type the following code:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>const app = express();
app.use(morgan('dev'));app.use(bodyParser.urlencoded({extended: true}));app.use(bodyParser.json());
const PORT = process.env.PORT || 3000
app.listen(PORT, () =&gt; {&nbsp; console.log(`Server is running on port ${PORT}`)});</code></code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>To ensure that your application is running, type the following command in your terminal from VS Code editor as follows:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>npm start</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>When you run the command, you will see the following output in your terminal:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626726817017_TA+app+running.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>To enable any changes made to the code to reflect immediately and run, let’s install another module called ‘<a target="_blank" href="https://www.npmjs.com/package/nodemon" rel="noreferrer noopener">nodemon</a>’. So, end the process in the terminal with <code>CTRL C </code>and paste this command in your terminal:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>npm install nodemon --save</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After installation, check your package.json file to confirm that the nodemon module has been installed.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Next, open your package.json file and replace the start script with the following code:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>nodemon server.js</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>See the following screenshot of the start script in the package.json file below:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626727683182_TA+package.json+file+with+start+script+nodemon.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Run the <code>npm start</code> command in your terminal, to ensure that the application is still running and you will see the following ouput in your terminal:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626727848259_TA+nodemon+starting+the+app.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Now that you have successfully set up your application to run on PORT 3000 and connected your application to your database via mongoose with MongoDB Compass, we can move forward to write some code to get the application working fully!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Setting up the Controllers, Models, and Routes for the Application</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Here, we are going to build the routes, controllers, and models for the application with the following steps:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>In your VS Code, create these three folders within your working directory with the names:<ul><li>Controllers</li><li>models</li><li>routes</li></ul></li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>Open your newly created folder ‘models’ and create a file ‘Data.js’ within the directory and type the following code in it:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String
},
designation: {
type: String
},
email: {
type: String
},
phone: {
type: String
},
age: {
type: Number
}
}, {timeStamps: true})
const User = mongoose.model('User', userSchema)
model.exports = User</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Your ‘Data.js’ file should look like this in your code editor:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626820296613_TA+Models+data.js+.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Navigate to the ‘controllers’ folder you created and create a file ‘UserController.js’ and type the following code in it:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const User = require('../models/Data');
// Fetches all Users
const users = (req, res, next) =&gt; {
User.find()
.then(response =&gt; {
res.json({
response
})
})
.catch(error =&gt; {
res.json({
message: 'An error occured!'
})
})
}
//Fetches a Single User
const one_user = (req, res, next) =&gt; {
let userID = req.body.userID
User.findById(userID)
.then(response =&gt; {
res.json({
response
})
})
.catch(error =&gt; {
res.json({
message: 'An error occured!'
})
})
}
// Saves user to the database
const store = (req, res, next) =&gt; {
let user = new User({
name: req.body.name,
designation: req.body.designation,
email: req.body.email,
phone: req.body.phone,
age: req.body.age
})
user.save()
.then(response =&gt; {
res.json({
message: 'User added successfully!'
})
})
.catch(error =&gt; {
res.json({
message: 'An error occured!'
})
})
}
// Updates user
const update = (req, res, next) =&gt; {
let userID = req.body.userID
let updatedData = {
name: req.body.name,
designation: req.body.designation,
email: req.body.email,
phone: req.body.phone,
age: req.body.age
}
User.findByIdAndUpdate(userID, {$set: updatedData})
.then(() =&gt; {
res.json({
message: 'User updated Successfully!'
})
})
.catch(error =&gt; {
res.json({
message: 'An error occured!'
})
})
}
// Deletes a user
const destroy = (req, res, next) =&gt; {
let userID = req.body.userID
User.findByIdAndRemove(userID)
.then(() =&gt; {
req.json({
message: 'User deleted Successfully!'
})
})
.catch(error =&gt; {
req.json({
message: 'An error occured!'
})
})
}
module.exports = {
users, one_user, store, update, destroy
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Your ‘UserController.js’ file should look like the code in these screenshots below in your code editor:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626820433500_TA+UserController+1.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626820515770_TA+User+Controller+2.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626820747602_TA+User+Controller+3.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626820861277_TA+User+Controller+4.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Next, navigate to the ‘routes’ folder and create a file ‘user.js’ within it and type the following code in the ‘user.js’ file:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const express = require('express');
const router = express.Router()
const UserController = require('../controllers/UserController');
router.get('/', UserController.users);
router.post('/one_user', UserController.one_user);
router.post('/store', UserController.store);
router.post('/update', UserController.update);
router.post('/delete', UserController.destroy);
module.exports = router</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Your ‘user.js’ file should look like this in your code editor:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626821127625_TA+user.js.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Import the route in the ‘user.js’ file into your ‘server.js’ file. Immediately after your required statements of your installed packages/modules before the line of code connecting to your database with mongoose, enter the following code:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const UserRoute = require('./routes/user');</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Still, in the ‘server.js’ file, after the line of code that listens for the PORT the application is running on, type the following code:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>app.use('/api/user', UserRoute)</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Your ‘server.js’ file should look like the code in these screenshots below in your code editor:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626821191408_TA+Server.js+modified+1.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626821247395_TA+Serverjs+modified+2.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Now, run your application and ensure that your application is connected to the database by typing the following command in your terminal:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm start</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You should see the following output in your terminal:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626821623154_TA+new+npm+start.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>Testing the Application’s Routes and Endpoints</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Here, we will use the <a target="_blank" href="https://www.postman.com/" rel="noreferrer noopener">postman</a> tool to test the application. To ensure that the routes and endpoints work, do the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Open your postman tool and create a Collection with the name ‘Aggregation Tutorial’.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>Within this Collection, create a ‘POST’ request and paste the following URL:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>http://localhost:3000/api/user/store</code></code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>In raw and application/JSON data format for the request body, type the following JSON data:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
"name": "Fred Loly",
"designation": "Software Developer",
"email": "myname@gmail.com",
"phone": "2366494049630",
"age": 23
}</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Next, click the ‘Send’ button and you should see the message ‘User added successfully’ in the response body as follows:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626823030889_TA+saving+user+again.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Repeat the process and add more Users with different names as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
"name": "Anita Bells",
"designation": "Mechanical Engineer",
"email": "anitabells@gmail.com",
"phone": "258909275388",
"age": 30
}</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
"name": "Emma Bostain",
"designation": "Lawyer",
"email": "emmabostain@gmail.com",
"phone": "2589093573388",
"age": 30
}</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
"name": "Cray Selton",
"designation": "Lawyer",
"email": "crayselton@gmail.com",
"phone": "385208573388",
"age": 40
}</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
"name": "Hilton Motly",
"designation": "Mechanical Engineer",
"email": "hiltonmotly@gmail.com",
"phone": "2573950975388",
"age": 36
}</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Open your MongoDB Compass and you will notice that the users have been saved in the database as follows:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626824018318_TA+new+users+database+1.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626824018272_TA+new+users+database+2.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Let’s test another endpoint for getting all the users in the application that have been saved to the database by creating another request in the ‘Aggregation Tutorial’ collection.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Create a ‘GET’ request with the following URL:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>http:&#47;&#47;localhost:3000/api/user</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You’d get the following response:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1626824375696_TA+gets+users.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->
<!-- wp:paragraph -->
<p>Now that we have successfully built our simple application with nodejs, express, and MongoDB, I will use this application to demonstrate how the Aggregation Pipeline works in MongoDB!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Using the Application to Illustrate How Aggregation Pipeline Works</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In the database, we want to access the ‘users’ collection and aggregate the data.&nbsp;We are going to use stages in the aggregation pipeline, we will match all documents inside the ‘users’ collection with ‘designation’ set to ‘Mechanical Engineer’ as the first stage.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>Then the second stage is going to take the aggregated result from the previous stage as input. In this second stage, we will sort by ‘name’ in descending order. Where ‘name’ is a field inside a single document in the ‘users’ collection.&nbsp;<br>We are only going to project the ‘name’ field in the ‘users’ collection, specifying in the project stage that we do not want the ‘_id’ shown but the ‘name’ field only.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>So, we are creating an aggregation pipeline that uses the following stages:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation/match/" rel="noreferrer noopener">$match</a></li><li><a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation/sort/" rel="noreferrer noopener">$sort</a></li><li><a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation/project/" rel="noreferrer noopener">$project</a></li></ul>
<!-- /wp:list -->
<!-- wp:list {"ordered":true} -->
<ol><li>Create a new route in the controller file ‘UserController.js’ with the following code:</li></ol>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const getUserData = (req, res, next) =&gt; {}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here, you are creating a new function in your controller file to be used to handle the route for the Aggregated data that will be produced.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true,"start":2} -->
<ol start="2"><li>In the function, we will use the ‘Data.js’ model to access the ‘User’ collection and we will use the aggregate() method on it as follows:</li></ol>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>User.aggregate();</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The Aggregation Pipeline is a MongoDB feature but mongoose gives us access to it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>Note that, the Aggregation Pipeline is like a regular <a target="_blank" href="https://docs.mongodb.com/manual/tutorial/query-documents/" rel="noreferrer noopener">MongoDB query</a>, and the only difference with Aggregation is that you can manipulate the data in different steps.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>3. To define these stages, we’ll pass in an array of stages in the aggregate() method as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>User.aggregate(&#91;
{ $match : { designation : 'Mechanical Engineer' } },
{ $sort : {name:-1} },
{ $project : { _id : 0, name : 1 } }
])</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In our Aggregation Pipeline, we used the <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation/match/" rel="noreferrer noopener">$match</a>, <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation/sort/" rel="noreferrer noopener">$sort</a>, and <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation/project/" rel="noreferrer noopener">$project</a> stages as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>First Stage</strong>: The $match stage is used to select or filter certain documents, it acts as the filter() object in MongoDB. We are using the $match stage in our Aggregation Pipeline to match the ‘designation’ field in the User Collection when it is equal to ‘Mechanical Engineer’. That is, we are going to match all Documents inside the User Collection with ‘designation’ set to ‘Mechanical Engineer’.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li><strong>Second Stage</strong>: The second stage which is the $sort stage is going to take the Aggregated result from the first stage as input. In this stage, we are sorting by the ‘name’ field in the Documents in the User Collection in descending order.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>Note that, ‘name’ refers to a field in a single Document inside the User MongoDB Collection.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li><strong>Third Stage</strong>: In the $project stage, we only want to project the name field. By setting <code>_id : 0</code> and <code>name: 1</code>, we only want to show the name field and not the <code>id</code> field.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The Documents in your MongoDB Collection will pass through these Aggregation Stages in the defined sequence and each of the stages is an object containing the name of the Stage. There are many<a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/" rel="noreferrer noopener"> Aggregation Stages</a> you can choose from.Check out the MongoDB Documentation to see the <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/query/" rel="noreferrer noopener">Query Operators</a> that MongoDB has made available for your use.&nbsp;<br></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The Documentation is an easy go-to for any stages you decide to use to manipulate any data in your application!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>4. Next, you need to return the Aggregated data by using the <code>.then()</code> method to handle the promise and respond with the JSON (JavaScript Object Notation) Aggregated data. Then we also need to handle the errors by using the <code>.catch()</code> method that responds with a JSON message as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>.then(response =&gt; {
res.json({
response
})
})
.catch(error =&gt; {
res.json({
message: 'An error occured!'
})
})</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Take a look at the complete code in the Aggregation Pipeline here:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const getUserData = (req, res, next) =&gt; {
User.aggregate(&#91;
{ $match : { designation : 'Mechanical Engineer' } },
{ $sort : {name:-1} },
{ $project : { _id : 0, name : 1 } }
])
.then(response =&gt; {
res.json({
response
})
})
.catch(error =&gt; {
res.json({
message: 'An error occured!'
})
})
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>5. Now that you have your Aggregated data function in your Controller file, you need to add the function <code>getUserData</code> to the list of functions you are exporting from this ‘UserController.js’ file as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>module.exports = {
users, one_user, store, update, destroy, getUserData
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>6. You need to create a route that will handle this Controller function. So, open your ‘User.js’ file and add the following line of code:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><meta charset="utf-8"><code>router.get('/getUserData', UserController.getUserData);</code></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>7. Next, open your terminal and type the following command to run the application:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><code>npm start</code></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Once you run this command, ensure that you can see the server running on PORT 3000 and Database Connection Established as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1627164209854_TA+last+terminal.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>Testing Our Aggregation Pipeline With Postman </h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that you have your application up and running, the next thing you need to do is test it with Postman as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Open your Postman tool, create a GET request and paste the following URL:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>http:&#47;&#47;localhost:3000/api/user/getUserData</code></pre>
<!-- /wp:code -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1627164714120_TA+getUserData+URL.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li>Click the highlighted ‘Send’ button on the right and watch the response. Your response should be the Aggregated data as follows:</li></ul>
<!-- /wp:list -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://paper-attachments.dropbox.com/s_C232C2C34C8B32A4F5A400298A54785DBC9665DE2E66ED73DB6E7935C8D46FAC_1627164844194_TA+getUserData+response.png" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The <a target="_blank" href="https://docs.mongodb.com/manual/core/aggregation-pipeline/" rel="noreferrer noopener">Aggregation Pipeline</a> is a great tool for processing and analyzing data in MongoDB Collections and with an easily accessible <a target="_blank" href="https://docs.mongodb.com/manual/core/aggregation-pipeline/" rel="noreferrer noopener">documentation</a> and reference section to work with <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/" rel="noreferrer noopener">Aggregation Pipeline Stages</a> and <a target="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation/" rel="noreferrer noopener">Aggregation Pipeline Operators</a> in your application.&nbsp;<br>In this tutorial, we covered an illustration and explanation of the Aggregation Pipeline, real-world use cases of the Aggregation Pipeline, an explanation of the syntax of the Aggregation Pipeline with code example, using an application built with nodejs and MongoDB to illustrate how the Aggregation Pipeline works and testing the Aggregation Pipeline with Postman.&nbsp;<br>With the information you learned in this tutorial, you can set up your own Aggregation Pipeline for your own business or application needs.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Node.js</category>
<author>Deborah Emeni</author>
<pubDate>Tue, 24 Aug 2021 19:03:36 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Transcoding of HTTP/JSON to gRPC Using Go ]]></title>
<link><![CDATA[ https://adevait.com/go/transcoding-of-http-json-to-grpc-using-go ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>GRPC is a modern, open-source, high-performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking, and authentication. It is also applicable in the last mile of distributed computing to connect devices, mobile applications, and browsers to backend services.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this document, our focus is on trying to explain gRPC as best as we can, based on the things that we have touched and things we have done while using gRPC as our main technology.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The project is open source and anybody is free to use, study, modify and distribute for any non-commercial purpose.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can find it under my gRPC GitHub repository: <a href="https://github.com/flakrimjusufi/grpc-with-rest" target="_blank" rel="noreferrer noopener"><strong>https://github.com/flakrimjusufi/grpc-with-rest</strong></a></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We are going to split our Proof of Concept into three different chapters:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><em>Installing gRPC in our local environment</em></li><li><em>Using gRPC with Go as language</em></li><li><em>Conclusions</em></li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2><strong>Installing gRPC in Our Local Environment</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I’m running on Linux (Ubuntu 20.04) and all the installation instructions are for <strong>Linux</strong>, with no coverage for <strong>Windows</strong> or <strong>Mac</strong>. For more details, check gRPC’s official blog:<a href="https://grpc.io/blog/installation/" target="_blank" rel="noreferrer noopener"> gRPC - now with easy installation</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There are some prerequisites for installing gRPC in your environment:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Where to use gRPC i.e. choosing a language in which you want to use gRPC - there are lots of supported languages (<img width="15" height="15" src="https://lh4.googleusercontent.com/gwCfXnm2Tc_-q65Ug-9l0Bq5btV_uC7F6zKibJv7J5szw603mQfyu3q4uMhbFz_vIR9hVH_CC4bMnUW5HIiNAE3p95Fp9vjEWIhczXih-e7f_FSidoszdpolpaCSpgsw_QzjXbvb"><a href="https://grpc.io/docs/languages/" target="_blank" rel="noreferrer noopener">Supported languages</a> ).<ul><li>I’ve chosen <a href="https://golang.org/doc/install" target="_blank" rel="noreferrer noopener"><strong>GO</strong></a> language and I’ve used version <strong>1.16.5.</strong></li></ul></li><li>Protocol buffer compiler <em>protoc</em> [version 3] - For installation instructions, please refer to this link: <a href="https://grpc.io/docs/protoc-installation/" target="_blank" rel="noreferrer noopener">Protocol Buffer Compiler Installation</a><ul><li>The following command was used to install <em>protoc</em>:</li></ul></li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">apt install -y protobuf-compiler</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>After that, the following command was used to ensure that <em>protoc</em> was successfully installed:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">protoc --version</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Your chosen language plugin for protocol compiler - Since I’m using Go, I’ll stick with Go plugins for protocol compiler.<br><ul><li>To complete the installation, we need to use the following commands:</li></ul></li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>After that, we just need to update the <em>GO</em> <em>PATH</em> so that <em>protoc</em> compiler can find the plugins:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">export PATH="$PATH:$(go env GOPATH)/bin"</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>Using gRPC With Go as Language</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>After completing the installation of all the prerequisites, I started developing. My goal was to Investigate <strong>gRPC vs REST</strong> and to help the team decide which one is better for our new platform. I have tried to touch different features of gRPC with some key points in mind which we will discuss in the below sections:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Integration of gRPC / easiness of use&nbsp;</li><li>Advantages / Disadvantages</li><li>gRPC vs HTTP</li><li>Integrating two or more gRPC services</li><li>gRPC Worthiness</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The initial idea was to create a project in which we are going to see all the benefits from <strong>gRPC</strong>, specifically to explore the possibilities with <strong>gRPC-gateway</strong>, which is a plugin of the Google protocol buffers compiler <strong><em>protoc</em></strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This plugin reads protobuf service definitions and generates a <strong>reverse-proxy server </strong>which translates a <strong>RESTful HTTP API </strong>into <strong>gRPC</strong>. The server is generated according to the <strong>google.api.http</strong> annotations in our service definitions under the proto file, something that we are going to cover later. With grpc-gateway, we wanted to have a system in which both <strong>gRPC</strong> and <strong>RESTful</strong> style are integrated.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Basically, what we wanted to achieve is described in the picture below:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4900,"width":677,"height":459,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/go-1.jpeg" alt="Transcoding of HTTP/JSON to gRPC Using Go" class="wp-image-4900" width="677" height="459"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>According to the architecture diagram, we have:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><meta charset="utf-8"></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>A proto file in which we define the entire data structure</li><li>Protoc to generate stubs (client interface)</li><li>gRPC-gateway to generate proxy</li><li>API client - RESTful API</li><li>PostgreSQL database</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>And this is how our project structure looks like:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4901,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-2.png" alt="Installing gRPC" class="wp-image-4901"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We are going to start with the <strong>proto directory, </strong>which is the most important one and deserves more attention.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is the place where we define our <strong>gRPC services</strong> and all <strong>data structures</strong>.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Trying to implement the best practices, we decided to have a unique directory in which we will have all the proto files. For this purpose, we have created a <strong>proto </strong>directory under which the user.proto file is located. In the user.proto<strong> </strong>file we can find the entire gRPC services and data structures that we are going to use for our project.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4902,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-3.png" alt="Installing gRPC" class="wp-image-4902"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This is how <strong>user.proto </strong>file in our project looks like: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4903,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-4.png" alt="Installing gRPC" class="wp-image-4903"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We will go line by line explaining what each one does.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">syntax = "proto3";</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the first line, we define the syntax which should match the version of <strong><em>protoc</em></strong>. In my case, it is “<em>proto3</em>” since I’m using the latest one (version 3 currently).</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">package helloworld;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After the syntax, there’s the package that needs to be defined. This should be a unique identifier in order to prevent duplication.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">option go_package = "/proto";</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Going further to the next line, it’s important to highlight that since version 3, <strong><em>protoc</em></strong> made <strong>option go_package</strong> a required parameter and without defining this parameter your proto file will not be compiled.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is the parameter in which you define the <strong>directory</strong> in which your proto file is located. In my case, it is “<strong>/proto</strong>”.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you don’t define this parameter, you will get an error like the one below once you try to compile your proto file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">Please specify either:
&nbsp; &nbsp; &nbsp; &nbsp; • a "go_package" option in the .proto source file, or
&nbsp; &nbsp; &nbsp; &nbsp; • a "M" argument on the command line.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.
--go_out: protoc-gen-go: Plugin failed with status code 1.</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Moving to the next line, we are importing an important module for our services.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The first one is <strong>google/api/annotations.proto </strong>and the second is <strong>google/protobuf/timestamp.proto</strong>. We will explain both of them in more detail since I consider this part as a pain point that took most of my time while working on this project.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>→ <strong>google/api/annotations.proto </strong><em>is a required third party protobuf file for the protoc compiler</em>. If you don’t have this dependency inside your project, you can’t define your <strong>API calls </strong>(<em>GET, POST, PUT, PATCH, DELETE</em>) inside your services and you won’t be able to <a href="https://cloud.google.com/endpoints/docs/grpc/transcoding" target="_blank" rel="noreferrer noopener"><strong>Transcode HTTP/JSON to gRPC.</strong></a></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Interesting enough, there’s currently no standard way to import this dependency. Even if you add the above lines inside your proto file, <strong>the protoc compiler won’t import this dependency for you because you have to do this manually.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To my surprise, this way of importing third-party dependencies is also<strong> encouraged </strong>by the grpc-gateway plugin.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After wasting a few days to find a proper solution, I felt tired and overwhelmed by this issue and I decided to import the dependencies manually.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>So, what I did was the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>I went into <em>googleapis github repo</em> in which <strong>annotations.proto </strong>and <strong>http.proto </strong>files<strong> </strong>are defined [<a href="https://github.com/googleapis/googleapis/blob/master/google/api" target="_blank" rel="noreferrer noopener">https://github.com/googleapis/googleapis/blob/master/google/api</a>]</li><li>I copied the files [<strong>annotations.proto</strong> and <strong>http.proto</strong>]</li><li>I created a directory named <strong>google</strong> and I added another folder inside this directory named <strong>api </strong>so the path would match the required import in my proto file → <strong>google/api/annotations.proto</strong></li><li>I pasted the files inside the directory</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>After completing the above steps, the project structure in the defined directory looked like this: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4904,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-5.png" alt="Installing gRPC" class="wp-image-4904"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Now I was able to add <a href="https://cloud.google.com/endpoints/docs/grpc/transcoding" target="_blank" rel="noreferrer noopener"><strong>HTTP calls</strong></a> and to compile my <strong>user.proto</strong> file.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving to the next import:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">import "google/protobuf/timestamp.proto";</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>→<strong> google/protobuf/timestamp.proto - </strong>a third-party dependency designed for timestamps. Google encourages the use of timestamps for better handling across machines. This module is independent of any calendar and concepts like “day” or “month”. It is related to Timestamp in that the difference between two Timestamp values is a Duration and it can be added or subtracted from a Timestamp.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving to the next lines, we have defined two services in our <strong>user.proto</strong> file.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>UserService</strong></li><li><strong>CreditCardService</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Like many RPC systems, gRPC is based around the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types. <strong><em>UserService</em></strong> and <strong><em>CreditCardService</em></strong>, even if they are different from each other and each one has its own logic and data structure, they use the same pattern. We will take two examples from both of them and we’ll try to explain in a bit more detail what they do.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The idea behind <strong>UserService</strong> was to create a server-client cycle in which we will use <a href="https://cloud.google.com/endpoints/docs/grpc/transcoding" target="_blank" rel="noreferrer noopener"><strong>HTTP calls</strong></a> (<em>Transcoding HTTP/JSON to gRPC</em>) to interact with a <strong>PostgreSQL</strong> database that has a table named <strong>users</strong>. This table has <strong>100k</strong> records that contain the user’s personal information. To interact with the database, we have used the GORM<strong> </strong><a href="https://gorm.io/" target="_blank" rel="noreferrer noopener"><strong>framework</strong></a><strong>.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s start explaining in more detail what <strong>UserService</strong> does. This is how the code looks like:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">service UserService {
&nbsp; rpc CreateUser (User) returns (User) {
&nbsp; &nbsp; option (google.api.http) = {
&nbsp; &nbsp; &nbsp; post: "/user/create"
&nbsp; &nbsp; &nbsp; body: "*"
&nbsp; &nbsp; };
&nbsp; }
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The keyword <strong>service</strong> is for defining a unique identifier for the services that you will define in your proto file, in my case it’s <strong>UserService</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Inside <strong>UserService</strong>, we have defined an <strong>rpc </strong>(reserved keyword for RPC) call <strong>CreateUser </strong>which takes (<em>User</em>) as input and returns (<em>User</em>) as output.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now, what does this all mean? We will explain more in the section below.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>User</strong> is a data structure (called <strong>message</strong> in <strong>gRPC</strong>) in which you can specify your field types, their naming and their positions inside the struct. Let’s dive into the code explaining line by line what this means:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">message User {
&nbsp; uint32 id = 1;
&nbsp; string name = 2;
&nbsp; string email = 3;
&nbsp; string phoneNumber = 4;
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p><strong>message </strong>is again a reserved keyword that you use for defining your data structure, in my case <strong>User.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Inside <strong>User</strong> data structure, we have defined:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td><strong>Data type&nbsp;</strong></td><td><strong>Name</strong></td><td><strong>Position</strong></td></tr><tr><td>uint32</td><td>id</td><td>1</td></tr><tr><td>string</td><td>name</td><td>2</td></tr><tr><td>string</td><td>email</td><td>3</td></tr><tr><td>string</td><td>phoneNumber</td><td>4</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:paragraph -->
<p>This is the data structure we are using as input and also as output in our <strong>rpc</strong> call <strong>CreateUser </strong>which belongs to <strong>UserService.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Going further in the next few lines inside our <strong>UserService</strong>:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">option (google.api.http) = {
&nbsp; &nbsp; &nbsp; post: "/user/create"
&nbsp; &nbsp; &nbsp; body: "*"
&nbsp; &nbsp; };</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This is the part where we are telling our service that we are going to use <strong>HTTP</strong> as our <em>transcoding</em> to <strong>gRPC</strong> and this <strong>option</strong> requires two parameters inside the body:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>post</strong> - which refers to the <strong>POST</strong> request and after the “<strong>:</strong>” you have to define the endpoint that you are going to use in order to hit this <strong>rpc</strong> call.</li><li><strong>body</strong> - which refers to the input that you are willing to accept for this endpoint, in my case it’s “<strong>*</strong>” which refers to “<em>accepting</em> <em>everything which comes as input” (JSON, XML, YAML, Plain Text, etc)</em>.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>After we are done with the definition of <strong>UserService</strong>, we will go briefly just for the sake of clarity to explain what <strong>CreditCardService</strong> does.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">service CreditCardService{
rpc GetCreditCardByUserName (CreditCard) returns (CreditCard) {
&nbsp; &nbsp; option (google.api.http) = {
&nbsp; &nbsp; &nbsp; get: "/card/findByUserName/{name}"
&nbsp; &nbsp; };
&nbsp; }
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Inside <strong>CreditCardService</strong> we have defined an <strong>rpc</strong> call <strong>GetCreditCardByUserName </strong>which takes a <em>CreditCard</em> as input and returns a <em>CreditCard</em> as output.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>CreditCard</em> is again a data structure (message) which contains <strong>data types, naming and positions</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is how the CreditCard looks like:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">message CreditCard {
&nbsp; uint32 id = 1;
&nbsp; string name = 2;
&nbsp; string email = 3;
&nbsp; string phoneNumber = 4;
&nbsp; string address = 5;
&nbsp; string country = 6;
&nbsp; string city = 7;
&nbsp; string zip = 8;
&nbsp; string cvv = 9;
&nbsp; google.protobuf.Timestamp created_at = 10;
&nbsp; google.protobuf.Timestamp updated_at = 11;
&nbsp; google.protobuf.Timestamp deleted_at = 12;
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In this data structure, we have defined more fields and we have added <strong>Timestamp</strong> data type for <strong>created_at</strong>, <strong>updated_at</strong> and <strong>deleted_at </strong>fields, something that we didn’t do in our previous gRPC example.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Continuing to the next few lines in our <strong>CreditCardService</strong>:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">option (google.api.http) = {
&nbsp; &nbsp; get: "/card/findByUserName/{name}"
&nbsp; };</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here, we are again telling our service that we are going to use <strong>HTTP</strong> as our <em>transcoding</em> to <strong>gRPC</strong> and this <strong>option</strong> requires just one parameter inside the body:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>get</strong> - which refers to <strong>GET</strong> request and will accept a {<em>name</em>} at the end of our defined endpoint, something like this: <strong>/card/findByUserName/Flakrim</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Since this is a <strong>GET</strong> request, we don’t have to define a ‘<strong>body</strong>’ as we did in the above example when we created a <strong>POST</strong> request.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After we are done with the definition of services and we have covered almost everything in our proto file, it’s time for the most interesting part in the gRPC ecosystem - <strong>the compiling.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To compile our proto file we are going to use this command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">protoc --go_out=. --go_opt=paths=source_relative \
&nbsp; &nbsp; --go-grpc_out=. --go-grpc_opt=paths=source_relative \
&nbsp; &nbsp; proto/user.proto</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>It took me a while to figure out and to understand the process of how gRPC works and what goes behind this command but I’ll try to explain it briefly:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>protoc --go_out=. --go_opt=paths=source_relative:<strong> </strong>This is protoc compiler asking for the source relative in which .proto file can be found</li><li>--go-grpc_out=. --go-grpc_opt=paths=source_relative<strong>: </strong>This is the part where we are telling the compiler to store the generated code from source relative</li><li>proto/user.proto<strong>: </strong>This is the part where we are specifying the file which needs to be executed</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>This command will build us all the functions, interfaces, and everything that we need to have a client-server response cycle. It will automatically generate the source code from the description and from the logic that we have defined in our proto file. With this process, we are parsing a stream of bytes that represents the structured data.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After executing this command, I see there are two additional files added in my proto directory:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4906,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-6.png" alt="Installing gRPC" class="wp-image-4906"/></figure></div>
<!-- /wp:image -->
<!-- wp:list -->
<ul><li><strong>user.pb.go: </strong>This is the file which contains the stream of bytes which can be serialized and deserialized.</li><li><strong>user_grpc.pb.go: </strong>This is the file which contains the data structure, functions and interfaces generated from the above command.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>After we have successfully completed this step, it’s time to compile our <strong>grpc-gateway</strong> for our reverse proxy server which we are using to <strong>Transcode HTTP over gRPC</strong>. This can be achieved with this command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">protoc -I . --grpc-gateway_out=logtostderr=true:. proto/user.proto</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This command is telling the compiler the exact location where to find the proto file in which we have defined our endpoints and also the location where to store the generated code.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After successfully executing this command, I’ve completed the protocol buffer part and this is how my proto directory looks like:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4907,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-7.png" alt="Installing gRPC" class="wp-image-4907"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>I’m seeing that the user.pb.gw.go file which contains the <strong><em>grpc-gateway ecosystem</em></strong> was added to my proto directory and now we are ready to use our services.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving on to the next part, we will try to explain briefly how the server works and how the services are being used on the server-side.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We will start with the main function and then we will move on to the most exciting part: Hitting the reverse proxy server and performing a <strong>Transcode of HTTP to gRPC services.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is the main block that we are using in our project:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">func main() {
// Create a listener on TCP port
lis, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalln("Failed to listen:", err)
}
// Create a gRPC server object
s := grpc.NewServer()
// Attach the User service to the server
userpb.RegisterUserServiceServer(s, &amp;userServer{})
userpb.RegisterCreditCardServiceServer(s, &amp;creditCardServer{})
// Serve gRPC server
log.Println("Serving gRPC on 0.0.0.0:8080")
go func() {
log.Fatalln(s.Serve(lis))
}()
maxMsgSize := 1024 * 1024 * 20
// Create a client connection to the gRPC server we just started
// This is where the gRPC-Gateway proxies the requests
conn, err := grpc.DialContext(
context.Background(),
"0.0.0.0:8080",
grpc.WithBlock(),
grpc.WithInsecure(),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize), grpc.MaxCallSendMsgSize(maxMsgSize)),
)
if err != nil {
log.Fatalln("Failed to dial server:", err)
}
gwmux := runtime.NewServeMux()
// Register User Service
err = userpb.RegisterUserServiceHandler(context.Background(), gwmux, conn)
if err != nil {
log.Fatalln("Failed to register gateway:", err)
}
newServer := userpb.RegisterCreditCardServiceHandler(context.Background(), gwmux, conn)
if newServer != nil {
log.Fatalln("Failed to register gateway:", newServer)
}
gwServer := &amp;http.Server{
Addr:&nbsp; &nbsp; fmt.Sprintf(":%s", os.Getenv("server_port")),
Handler: gwmux,
}
log.Println(fmt.Sprintf("Serving gRPC-Gateway on %s:%s", os.Getenv("server_host"), os.Getenv("server_port")))
log.Fatalln(gwServer.ListenAndServe())
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Since this is the main block under which all the services are being implemented and the reverse proxy server is being handled, I consider that this block deserves more attention. That’s why we will dive deeper into the code trying to explain each part accordingly.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We are going to start with the listener:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;// Create a listener on TCP port
lis, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalln("Failed to listen:", err)
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here we are defining a net tcp listener in port <strong>:8080 </strong>under which the <strong>gRPC</strong> server will be served.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving to the next block:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"> &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;// Create a gRPC server object
s := grpc.NewServer()
// Attach the User service to the server
userpb.RegisterUserServiceServer(s, &amp;userServer{})
userpb.RegisterCreditCardServiceServer(s, &amp;creditCardServer{})</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here we are creating a <em>gRPC server object</em> and we are <em>attaching to the server</em> the <strong>UserService</strong> and <strong>CreditService </strong>which we defined in our <strong>proto/user.proto</strong> file.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving to the next block:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"> &nbsp; &nbsp;// Serve gRPC server
log.Println("Serving gRPC on 0.0.0.0:8080")
go func() {
log.Fatalln(s.Serve(lis))
}()</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In this block, we are serving <strong>gRPC</strong> server to the host that we have defined, in our case it’s localhost or more precisely in <strong>0.0.0.0:8080.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving further to the next block:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"> maxMsgSize := 1024 * 1024 * 20
// Create a client connection to the gRPC server we just started
// This is where the gRPC-Gateway proxies the requests
conn, err := grpc.DialContext(
context.Background(),
"0.0.0.0:8080",
grpc.WithBlock(),
grpc.WithInsecure(),
&nbsp; grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize),&nbsp; &nbsp; grpc.MaxCallSendMsgSize(maxMsgSize)),
)
if err != nil {
log.Fatalln("Failed to dial server:", err)
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This is the part where we are creating a client connection to the <strong>gRPC</strong> server we just started in the lines above. This is where the<strong> gRPC-Gateway proxies the request</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Note that we are targeting the “<strong>0.0.0.0:8080</strong>” host under which the gRPC server is being served.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>grpc.WithBlock() and grpc.WithInsecure() are being used because we are running this project locally and we don’t have to deal with security or similar stuff.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>grpc.WithDefaultCallOptions(...) is being used just to increase the size of the Messages that are being deserialized when we are transcoding HTTP to gRPC.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving on to the next block:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">&nbsp; &nbsp; &nbsp; gwmux := runtime.NewServeMux()
// Register User Service
err = userpb.RegisterUserServiceHandler(context.Background(), gwmux,&nbsp; &nbsp; &nbsp; conn)
if err != nil {
log.Fatalln("Failed to register gateway:", err)
}
newServer := userpb.RegisterCreditCardServiceHandler(context.Background(), gwmux, conn)
if newServer != nil {
log.Fatalln("Failed to register gateway:", newServer)
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here, we are telling the server that we are dealing with multiple services and this is the place where we are registering our service Handlers.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Notice that both userpb.RegisterUserServiceHandler(...)and userpb.RegisterCreditCardServiceHandler(...) are pointing to<strong> user.pb.gw.go</strong> which is the file that was auto-generated once we executed the compiling command.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Inside these services we passing three parameters:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>context.Background()</strong> → which is a non-nil empty Context, it is never canceled, has no values and has no deadline. It is typically used by the main function, initialization and tests and also as the top-level Context for incoming requests.</li><li><strong>gwmux</strong> → Returns a runtime which is part of <em>grpc-ecosystem</em> under <em>grpc-gateway</em> and a <em>NewServeMux()</em> which returns a new <em>ServeMux</em> whose internal mapping is empty</li><li><strong>conn</strong> → connection which will be used by gRPC-Gateway to proxy the requests.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>And the last part:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">&nbsp; gwServer := &amp;http.Server{
Addr:&nbsp; &nbsp; fmt.Sprintf(":%s", os.Getenv("server_port")),
Handler: gwmux,
}
log.Println(fmt.Sprintf("Serving gRPC-Gateway on %s:%s", os.Getenv("server_host"), os.Getenv("server_port")))
log.Fatalln(gwServer.ListenAndServe())</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here, we are just initiating the gateway Server using<em> </em><strong><em>&amp;http.Server</em> </strong>that contains the Address in which the server will be served and the Handler to handle the <strong>gwmux </strong>defined above.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>That’s all from the main block. Now we will move on to explaining in more detail one very important piece of gRPC and gRPC-gateway: The functions.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One thing that needs to be highlighted and it’s worth mentioning is the <strong><em>naming convention.</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The naming of the functions defined in the server should match the naming of rpc calls defined in the proto file. That’s how gRPC makes the connection and interacts with the services.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We will take the example of <strong><em>CreateUser </em></strong>which is a rpc call that belongs to <strong>UserService<em>. </em></strong>Here we have the code which interacts with the server-side:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">func (as *userServer) CreateUser(ctx context.Context, in *userpb.User) (*userpb.User, error) {
user := models.User{Name: in.Name, Email: in.Email, PhoneNumber: in.PhoneNumber}
database.NewRecord(user)
database.Create(&amp;user)
return &amp;userpb.User{Id: uint32(user.ID), Name: user.Name, Email: user.Email, PhoneNumber: user.PhoneNumber}, nil
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The first thing that needs to be mentioned is the naming convention. Notice that the name (CreateUser) of this function on the server-side is the one that matches the RPC call which is defined inside <strong>UserService </strong>in the proto file.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>More precisely, we are talking about this part of code in our <strong>user.proto</strong> file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">service UserService {
&nbsp; rpc CreateUser (User) returns (User) {
&nbsp; &nbsp; option (google.api.http) = {
&nbsp; &nbsp; &nbsp; post: "/user/create"
&nbsp; &nbsp; &nbsp; body: "*"
&nbsp; &nbsp; };
&nbsp; }</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you decide to use another name (for example <strong>UserCreate</strong>) that is not the same as the one defined in the proto file, you will get a <strong>501 Not Implemented </strong>response when you hit the endpoint.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Grpc</strong> is also <strong>case sensitive</strong> and will return the same response if you name the function <strong>Createuser</strong> instead of <strong>CreateUser</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">{
&nbsp; "code": 12,
&nbsp; "message": "method CreateUser not implemented",
&nbsp; "details": &#91;]
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now we will move forward and we will try to explain the parameters in the CreateUser function.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>func (as *userServer) CreateUser(ctx context.Context, in *userpb.User) (*userpb.User, error)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Inside this function, we are using these parameters:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>(as *UserServer) </strong>[<em>type</em>]<strong> : </strong>as is a pointer to <strong>UserServer</strong> which is a type that implements <em>User Service Server.</em> More precisely, <strong>as</strong> points to:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">type userServer struct {
userpb.UnimplementedUserServiceServer
}</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li><strong>userpb </strong>is the global variable that we use when we are pointing to our proto file</li><li><strong>UnimplementedUserServiceServer</strong> is a built-in function of gRPC that is used for having forward compatible implementations and is located in <strong>user_grpc_pb.go, </strong>the file that was generated after we compiled the proto file.</li><li><strong>ctx context.Context </strong>[<em>input parameter</em>]<strong>: </strong><em>ctx</em> refers to<em> context.Context</em> which is a built in function which is used if we want the method to be called by multiple goroutines simultaneously.</li><li><strong>in *userpb.User</strong> [<em>input parameter</em>]<strong>: </strong><em>in</em> is pointing to <em>userpb.User</em> which is the struct which is located in <strong>user.pb.go</strong>, the file that was generated when we compiled the proto file.</li><li><strong>in *userpb.User </strong>[<em>output parameter</em>]: same as above but in here we are telling the function to return a <strong>*userpb.User</strong> struct as a response</li><li><strong>error </strong>[<em>output parameter]</em>: just a built-in interface for representing an error condition with the nil value representing no error</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Moving to the next line:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">user := models.User{Name: in.Name, Email: in.Email, PhoneNumber: in.PhoneNumber}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here, we are passing by the values we are getting from the <strong>HTTP</strong> <strong>POST</strong> call.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>models.User{}</strong> is a struct that contains Name, Email and PhoneNumber and is used to interact with the database</li><li><strong>in.Name</strong>,<strong> in.Email</strong> and <strong>in.PhoneNumber</strong> are the values that are deserialized from gRPC (<strong>in </strong>is the variable that points to <strong>userpb.User</strong> in <strong>user.pb.go)</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Continuing to the next two lines:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">database.NewRecord(user)
database.Create(&amp;user)</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here, we are interacting with the database using the GORM framework and we are telling<strong> PostgreSQL</strong> to create a new record in the user table.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>database</strong> is a global variable that we are using to connect to the database. More precisely, database is pointing to:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">var database = db.Connect()</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Moving towards the end of this block of code:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">return &amp;userpb.User{Id: uint32(user.ID), Name: user.Name, Email: user.Email, PhoneNumber: user.PhoneNumber}, nil</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This is the place where are telling our function to return a <strong>&amp;userpb.User </strong>data structure instance inside which we are <em>pairing</em> the user information that we received from database.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Since we have covered lots of code already and now we are assuming that we have some knowledge of how things are working, we are going to run the example we just explained.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What we are going to do is basically start the <strong>gRPC</strong> and <strong>gRPC-gateway proxy server</strong> and send a <strong>POST</strong> request to it by hitting the <strong>/user/create</strong> endpoint.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Starting the server with go run server/main.go command and getting the response:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">2021/07/30 14:31:15 Serving gRPC on 0.0.0.0:8080
2021/07/30 14:31:15 Serving gRPC-Gateway on 0.0.0.0:8090</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>I’m using <a href="https://insomnia.rest/" target="_blank" rel="noreferrer noopener"><strong>Insomnia</strong></a> for sending requests to the server: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4908,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-8.png" alt="Installing gRPC" class="wp-image-4908"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We are sending three parameters to the server:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>name</strong> (string)</li><li><strong>email</strong> (string)</li><li><strong>phoneNumber</strong> (string)</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Remember this is the endpoint we have defined in our <strong>user.proto </strong>file: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4909,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-9.png" alt="Installing gRPC" class="wp-image-4909"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>And this is the message (data structure in <strong>user.proto </strong>file) which we are using for this request: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4910,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-10.png" alt="Installing gRPC" class="wp-image-4910"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>After sending a <strong>POST</strong> request to <a href="http://localhost:8090/user/create" target="_blank" rel="noreferrer noopener"><strong>http://localhost:8090/user/create</strong></a>, that’s how the response from the server looks like: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4911,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-11.png" alt="Installing gRPC" class="wp-image-4911"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We’ve got a <strong>200 OK</strong> status code from the server and here we have the <strong>JSON </strong>style<strong> </strong>response:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
&nbsp; "id": 120136,
&nbsp; "name": "Flakrim Jusufi",
&nbsp; "email": "flakrim.jusufi@gmail.com",
&nbsp; "phoneNumber": "+10 34 3444 222"
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Checking the terminal in the server, I’m reading the logs from <strong>PostgreSQL</strong> database:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">&#91;2021-07-30 16:11:59]&nbsp; &#91;3.98ms]&nbsp; INSERT INTO "users" ("created_at","updated_at","deleted_at","name","email","phone_number") VALUES ('2021-07-30 16:11:59','2021-07-30 16:11:59',NULL,'Flakrim Jusufi','flakrim.jusufi@gmail.com','+10 34 3444 222') RETURNING "users"."id"&nbsp;
&#91;1 rows affected or returned ]</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>And yep. We did it<strong>!</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We have successfully created a <strong><em>user</em></strong> in our database with <strong>HTTP REST-ful</strong> style using <strong>gRPC</strong>, <strong>protobuf</strong> and <strong>gRPC-gateway.&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>GRPC vs REST&nbsp;</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We will switch focus now and talk more about the <em>performance of gRPC</em>. I was able to do a comparison between <strong>REST HTTP APIs</strong> and <strong>gRPC</strong> and according to my findings, I’ve seen why gRPC over REST is an often choice of many <a href="//adevait.com/software" target="_blank" rel="noreferrer noopener">software developers</a>. It is pretty fast and the compression of data is enormous compared with traditional REST APIs.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We prepared a data set of <strong>100K</strong> records in <em>PostgreSQL</em> database and we investigated how gRPC and REST are responding when they have to deal with this amount of data. The data set was the same for both gRPC and REST.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The performance of <strong>gRPC</strong>:</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td><strong>Number of records</strong></td><td><strong>Size of data</strong></td><td><strong>Response</strong></td></tr><tr><td>10k</td><td>963.9 KB</td><td>120 ms</td></tr><tr><td>20k</td><td>1916.5 KB</td><td>270 ms</td></tr><tr><td>30k</td><td>3 MB</td><td>270 ms</td></tr><tr><td>40k</td><td>3.9 MB</td><td>500 ms</td></tr><tr><td>50k</td><td>4.7 MB</td><td>700 ms</td></tr><tr><td>60k</td><td>5.7 MB</td><td>750 ms</td></tr><tr><td>70k</td><td>6.9 MB</td><td>850 ms</td></tr><tr><td>80k</td><td>7.9 MB</td><td>950 ms</td></tr><tr><td>90k</td><td>8.8 MB</td><td>1 s</td></tr><tr><td>100k</td><td>9.8 MB</td><td>1.10 s</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:paragraph -->
<p>The performance of <strong>REST</strong>:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td><strong>Number of records</strong></td><td><strong>Size of data</strong></td><td><strong>Response</strong></td></tr><tr><td>10k</td><td>2034.3 KB</td><td>150 ms</td></tr><tr><td>20k</td><td>4 MB</td><td>340 ms</td></tr><tr><td>30k</td><td>6 MB</td><td>500 ms</td></tr><tr><td>40k</td><td>8 MB</td><td>600 ms</td></tr><tr><td>50k</td><td>10 MB</td><td>750 ms</td></tr><tr><td>60k</td><td>12 MB</td><td>850 ms</td></tr><tr><td>70k</td><td>14 MB</td><td>1 s</td></tr><tr><td>80k</td><td>16 MB</td><td>1.30 s</td></tr><tr><td>90k</td><td>18 MB</td><td>1.50 s</td></tr><tr><td>100k</td><td>20 MB</td><td>1.70 s</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:paragraph -->
<p>As we can see, <strong>gRPC</strong> is performing slightly better when it comes to speed and is doing tremendously when it comes to the compression of data. When comparing gRPC vs REST speed-wise, we can conclude that:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>gRPC </strong>is around 20-25% faster than <strong>REST</strong></li><li><strong>gRPC</strong> is around 40-50% more efficient (less size of data) compared to <strong>REST</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Let’s finish our assumption with a high-level comparison between <strong>gRPC</strong> and <strong>REST</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td><strong>Topic</strong></td><td><strong>gRPC</strong></td><td><strong>REST</strong></td></tr><tr><td>Performance</td><td>Around 20-25% faster</td><td>Around 20-25% slower</td></tr><tr><td>Efficiency</td><td>Around 40-50% more efficient</td><td>Around 40-50% less efficient</td></tr><tr><td>Protocol</td><td>HTTP/2 (fast)</td><td>HTTP/1.1 (slow)</td></tr><tr><td>Payload</td><td>Protobuf (binary, small)</td><td>JSON (text, large)</td></tr><tr><td>API architecture</td><td>Strict, required (.proto file)</td><td>Loose, optional (OpenAPI)</td></tr><tr><td>Code generation</td><td>Supported with built-in (protoc)</td><td>Third-party tools</td></tr><tr><td>Security</td><td>TSL/SSL</td><td>TSL/SSL</td></tr><tr><td>Streaming</td><td>Client, server, bi-directional</td><td>Client, server</td></tr><tr><td>Client code-generation</td><td>Supported (built-in)</td><td>OpenAPI + third party tooling</td></tr><tr><td>Browser support</td><td>Not supported (requires grpc-web)</td><td>Widely Supported&nbsp;</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":3} -->
<h3><strong>Integrating the Two gRPC Services </strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Moving on to the next topic, we were curious to see how <strong>gRPC</strong> services interact with each other when they are integrated into a client-server response cycle. We wanted to see how they are performing in circumstances where they need to interact with a database and we were interested to know the entire process.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The architecture:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4912,"width":530,"height":360,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/go-12.jpeg" alt="Integrating the Two gRPC Services " class="wp-image-4912" width="530" height="360"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We have a client-server system in which the client-side interacts with the server-side and the response cycle goes back and forth creating a<em> Remote Procedure Call.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As we can see in the architecture diagram:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Server contains all the gRPC services and proto generated files.</li><li>Client server contains two different services that will interact with each other.</li><li><strong>UserService</strong> is a gRPC service that interacts with <em>users</em> table in our <em>PostgreSQL</em> database.</li><li><strong>CreditCardService</strong> is another gRPC service that interacts with the credit_cards table in our <em>PostgreSQL</em> database.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>We will go first in our <strong>user.proto</strong> file to see how <strong>UserService</strong> looks like, more precisely, the rpc call <strong>GetUserByName </strong>which we are going to use when interacting with <strong>CreditCardService</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4913,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-13.png" alt="Integrating the Two gRPC Services " class="wp-image-4913"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The <em>rpc call </em><strong>GetUserByName</strong> accepts <strong>User</strong> message as input and returns again <strong>User</strong> message as output. All of this is achieved while <em>transcoding HTTP in gRPC </em>through API endpoint <strong>GET</strong> [<strong>/user/findByName/{name}</strong>].</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving on to the next service, <strong>CreditCardService</strong>: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4914,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-14.png" alt="Integrating the Two gRPC Services " class="wp-image-4914"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>In here we have two <strong>rpc</strong> calls:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>CreditCards</strong> - which returns a list of CreditCards that belongs to registered users</li><li><strong>GetCreditCardByUserName</strong> - which returns Credit Cards information by user’s name</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>And for the integration between services, we are going to use <strong>GetCreditCardByUserName</strong> rpc call.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now let’s go and see how our client-server directories inside the project look like: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4915,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-15.png" alt="Integrating the Two gRPC Services " class="wp-image-4915"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Under the client directory we have <strong>credit_card_server.go</strong> file which contains all the logic on the client-side, meanwhile in the server directory we have <strong>main.go</strong> file which contains the server logic and all the gRPC services we are going to interact with.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now we are going to explain some important parts of the code in <strong>credit_card_server.go.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Full code in the main block:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure(), &nbsp; grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := userpb.NewCreditCardServiceClient(conn)
u := userpb.NewUserServiceClient(conn)
//user client
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
personName := "Tom Muller"
x, err := u.GetUserByName(ctx, &amp;userpb.User{
Name: personName,
})
if err != nil {
log.Fatalf("could not get person data: %v", err)
}
//credit card client
ctx2, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.GetCreditCardByUserName(ctx2, &amp;userpb.CreditCard{
Name: x.GetName(),
})
if err != nil {
log.Fatalf("could not get person data: %v", err)
}
fmt.Println(colorCyan, r)
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Starting with the setup of the connection to the gRPC server and defining the services that we want to interact with:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>userpb.NewCreditCardServiceClient(conn) → refers to the client side of <strong>CreditCardService</strong></li><li>userpb.NewUserServiceClient(conn) → refers to the client side of <strong>UserService</strong></li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">&nbsp; // Set up a connection to the server.
&nbsp; conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
&nbsp; if err != nil {
&nbsp; &nbsp; &nbsp; log.Fatalf("did not connect: %v", err)
&nbsp; }
&nbsp; defer conn.Close()
&nbsp;&nbsp;&nbsp;c := userpb.NewCreditCardServiceClient(conn)
&nbsp; u := userpb.NewUserServiceClient(conn)</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Moving to the next few lines where we are making use of user client:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">//user client
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
personName := "Tom Muller"
x, err := u.GetUserByName(ctx, &amp;userpb.User{
&nbsp; Name: personName,
})
if err != nil {
&nbsp; log.Fatalf("could not get person data: %v", err)
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Here, after we set up the context we are defining a personName := "Tom Muller" which is the name of the person we want to get the information from.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">x, err := u.GetUserByName(ctx, &amp;userpb.User{
&nbsp; Name: personName,
})</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li><strong>u</strong> → points to userpb.NewUserServiceClient(conn)</li><li><strong>GetUserByName</strong> → the remote procedure call which is part of <strong>UserService</strong> that we are using to get the user's name.</li><li><strong>&amp;userpb.User</strong> <strong>{ Name : personName } </strong>→ passing the personName to <strong>UserService</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>And the last part, the credit card client:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">//credit card client
ctx2, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.GetCreditCardByUserName(ctx2, &amp;userpb.CreditCard{
&nbsp; Name: x.GetName(),
})
if err != nil {
&nbsp; log.Fatalf("could not get person data: %v", err)
}
fmt.Println(colorCyan, r)</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In this block of code, after we set up the context we are interacting with <strong>GetCreditCardByUserName</strong> rpc call which belongs to <strong>CreditCardService</strong> and we are passing <strong>x.GetName():</strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>x → is pointing to <strong>UserService</strong> we defined above</li><li>x.GetName() → is the response we have received from the service above (rpc call <em>GetUserByName</em>)</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Now we are going to run the servers in two different terminals and we will see the responses.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Starting up the server-side first: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4916,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-16.png" alt="Integrating the Two gRPC Services " class="wp-image-4916"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Starting the client-server: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4917,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/go-17.png" alt="Integrating the Two gRPC Services " class="wp-image-4917"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Now from the client side, we are going to send the person's name to <strong>UserService</strong> and we will communicate with the rpc call <strong>GetUserByName</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">2021/08/03 12:13:37.534210 Sending person name &#91;Tom Muller] to &#91;UserService] | communicating with rpc call &#91;GetUserByName] |</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Switching the terminal to the server side and checking the response:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"><strong>2021/08/03 12:13:37.535027 &#91;userService] - &#91;rpc GetUserByName] -&gt; Received person's name: Tom Muller</strong></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now checking the terminal in client side:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">2021/08/03 12:13:37.584432 Successfully received person data from Server Side &#91;UserService] | rpc call &#91;GetUserByName] |
___________________________________________________________________________
2021/08/03 12:13:37.584450 Response from the server side &#91;userService] - &#91;rpc GetUserByName]:
___________________________________________________________________________id:120035 name:"Tom Muller" email:"tom.muller@gmail.com" phoneNumber:"4785576361"</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now we will again interact with the server by sending the received data to <strong>CreditCardService</strong> in order to interact with the rpc call <strong>GetCreditCardByUserName</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The output in client-side:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">2021/08/03 12:13:37.584499 Now sending the retrieved data to &#91;CreditCardService] in order interact with rpc call &#91;GetCreditCardByUserName] and to receive person's credit card information</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The response in server side:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">2021/08/03 12:13:37.587228 &#91;creditCardService] - &#91;rpc GetCreditCardByUserName] -&gt; Now sending the response (credit card of selected user) to client side...</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>And here we have the response in client-side:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">2021/08/03 12:13:37.587402 Successfully received Credit Card information of selected user from &#91;CreditCardService] by interacting with rpc call &#91;GetUserByName] which belongs to &#91;userService]
____________________________________________________________________________
2021/08/03 12:13:37.587411 Response from the server side &#91;creditCardService] - &#91;rpc GetCreditCardByUserName] :
____________________________________________________________________________
id:99 name:"Tom Muller" email:"ronaldoraynor@bergstrom.org" phoneNumber:"4785576361" address:"37026 Cape borough, West Jones, Utah 17459" country:"Malaysia" city:"Fredmouth" zip:"86850" cvv:"301" created_at:{seconds:1625574830 nanos:191972000}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In such a scenario, we have made the output of <strong>UserService</strong> the input of <strong>CreditCardService</strong> and we have successfully completed the integration of two different gRPC services.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Note that with a few lines of code we were able to integrate two gRPC services that are doing completely different tasks. The first one is interacting with the users table in the database and the other one is interacting with the credit_cards table.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And check the response time. The difference is just a few <em>milliseconds</em>!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Conclusion</strong>s</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Since we have covered a bit of everything in our experience with gRPC using Go as a language, we have come down to the last part in which we will draw our conclusions. It’s been a long journey and in this document, we have tried to explain only the most important topics.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Coming down to the conclusions, I want to emphasize that <em>they are not intended to shape or change anyone’s opinion of gRPC</em>. My conclusions are based solely <strong>on my <em>experience</em></strong> and the things that I’ve touched while working on this project. Everyone can have different experiences and can form their own opinion about this technology.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We will start first with <strong>gRPC</strong> <strong>strengths</strong> and the things that have impressed me the most.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Advantages of gRPC</strong></h3>
<!-- /wp:heading -->
<!-- wp:heading {"level":4} -->
<h4><strong>Architecture</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I’m a fan of strongly typed languages and I love when things are designed in a strict way following a strict specification of rules. I was impressed by how simple and straightforward the architecture of gRPC was. You can create a robust and lightweight client-server application in just a matter of seconds.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You just have to define your services and the data structure (messages) in the proto file. Everything else is auto-generated when you compile your proto file. No need for further changes or any other additions. Code generation eliminates duplication of messages on the client and server and creates a strongly typed client for you.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Not having to write a client saves significant development time in applications with many services. Grpc is also consistent across platforms and implementations. You can simply build it once in whatever language you want and use it in any other language that gRPC supports. You can build service in Go for example and use it in your Java program.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><strong>Performance</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the things that impressed me the most was the performance of gRPC. I was able to retrieve the entire database (more than <strong>100k</strong> records) for something more than<strong> 1 (one) second</strong> and I was surprised how small the chunk of data was: just <strong>9.8 MB.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this chunk of data, I was having the user's personal information such as <em>ID, Name, Email, and PhoneNumber </em>and all the users were having real data, not dummy ones with some sort of test strings.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is huge when you are dealing with a lot of data and a more populated data structure. I was also able to fetch users from the database using <strong>Id</strong> with a response time of just <strong>1.3 milliseconds</strong>. That’s enormous.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The small message payloads that are serialized by protobuf can help you in limited bandwidth scenarios like mobile apps. Since gRPC uses HTTP/2 you can also send multiple requests without having in mind if the requests will block each other.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><strong>Streaming</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Streaming is one of the strongest points of gRPC. I was fascinated by the way streaming was implemented in gRPC. HTTP/2 provides a foundation for long-lived, real-time communication streams. All the way around, it’s first-class support which is provided.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A gRPC service supports all streaming combinations and will allow you to use different types of streaming:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Unary (no streaming)</li><li>Server to client streaming</li><li>Client to server streaming</li><li>Bi-directional streaming</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>As described in the above section, we were able to do a Client to server streaming and the response cycle is in milliseconds. Never seen that before anywhere else. And the good thing about it is that you can have a streaming service with just a few lines of code.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Disadvantages of gRPC</strong></h3>
<!-- /wp:heading -->
<!-- wp:heading {"level":4} -->
<h4><strong>Lack of maturity</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the things that concerned me the most while using gRPC was the lack of maturity. It seems to me this technology is still too young and still in the first years of development. With minimal developer support outside of Google and not many tools created for HTTP/2 and protocol buffers, the community lacks information about best practices, workarounds, and successful stories.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I was facing some basic issues while developing this project and I had to research all over the place seeking solutions. The ones that wasted most of my time were importing some third-party dependencies which I had to import manually inside my project. There was no other solution. And the solution was found while reading comments of developers that faced the same issue inside the community because neither I nor them couldn’t find any documentation or something similar to solve this problem.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another issue that I had was to find the proper command in order to compile the grpc-gateway proto file. You may miss a dependency in your project, you can have a syntax error or something similar but almost never get to know what exactly is going on because the error messages are missing some important details. And there’s no official documentation that explains in detail what each value in the command does. At least I couldn’t find any.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The last one that I faced was also a basic one. Since gRPC uses only <em>timestamps</em>, I had to convert timestamps to <em>Time</em> in <em>Go</em>. And I had to go all over the place again just to find a proper solution because all the solutions that I found were already deprecated. Then I found out that in the last update of the package that you have to use to do this conversion, the naming of the package itself was changed from <em>pbtype</em> to <em>timestamppb. </em>And the syntax was no longer the same.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The maturity of specific technology can be a big hurdle to its adoption. That’s apparent with gRPC too. But this is likely to change soon. I prefer to keep the good feelings that I had with gRPC and to remain positive. As with many open-source technologies backed by big corporations, the community will keep growing and will attract more developers.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><strong>Limited browser support</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This is also one major concern when you’re about to decide if you want to use this technology. Since gRPC heavily uses HTTP/2 features and no browser provides the level of control required over web requests to support a gRPC client, as of now that we are writing, it’s impossible to directly call a gRPC service from a browser.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>No browser today allows a caller to require that HTTP/2 be used or provide access to underlying HTTP/2 frames. To achieve something like this, you need to use a proxy, which has its own limitations. There are currently two implementations:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><a href="https://grpc.io/docs/tutorials/basic/web.html" target="_blank" rel="noreferrer noopener"><strong>gRPC web client</strong> <strong>by Google</strong></a> - a technology developed by Google team that provides gRPC support in the browser. It allows browser apps to benefit from the high-performance and low network usage of gRPC but unfortunately not all features are supported. Client and bi-directional streaming isn’t supported and there is limited support for server streaming.</li><li><a href="https://www.improbable.io/blog/grpc-web-moving-past-restjson-towards-type-safe-web-apis" target="_blank" rel="noreferrer noopener"><strong>gRPC web client by the team from The Improbable</strong></a> - a TypeScript gRPC-web client library for browsers that abstracts away the networking (Fetch API or XHR) from users and code generated classes.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>They both share the same logic: A web client sends a normal HTTP request to the proxy, which translates it and forwards it to the gRPC server.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><strong>Steeper learning curve</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I think we all agree that every new technology that shines and tries to revolutionize the way we build software takes time to learn and to adapt.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Compared to REST or GraphQL for example, which primarily use JSON, it will take some time to get acquainted with protocol buffers and find tools for dealing with HTTP/2 friction. It doesn’t even matter how many years of experience you have or how many applications you have built until now. You will <em>struggle.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And that’s why so many teams will choose to rely on REST for as long as possible because finding a gRPC expert is hard. To be honest, I don’t even think there’s any because it’s still a new technology and I have the feeling that everyone who has tried it, it’s still taking the learning steps and not using it in a production environment.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>And..That’s all from gRPC!</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I hope this documentation helped you to understand this technology and now you do have a basic knowledge about gRPC.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We are all still all new to this technology and we are still taking the learning steps. I don’t think there’s someone outside who can state that he is an expert on gRPC because there are lots of things you need to learn.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I would say it’s a good experience and definitely, I would encourage everyone to give it a try.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can take my project as an initial step:<a href="https://github.com/flakrimjusufi/grpc-with-rest" target="_blank" rel="noreferrer noopener"> <strong>https://github.com/flakrimjusufi/grpc-with-rest</strong></a></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong><em>Thank you for coming all the way down!</em></strong></p>
<!-- /wp:paragraph --> ]]></description>
<category>Go</category>
<author>Flakrim Jusufi</author>
<pubDate>Tue, 24 Aug 2021 18:50:50 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Building A Motivating Discord Bot In Node.js ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/building-motivating-discord-bot-nodejs ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Teams making it their own, gamers living there online, friends doing their online hangouts. Yes, we're talking about Discord, the communication tool with more than a quarter-billion users.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>No wonder you see many people talking about it, making tools work with it, and notice integrations pop up everywhere.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And we're going to be a part of that because today, we'll learn how to make our very first Discord bot!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And not any bot, a motivating bot for when we feel down. Because developer happiness is very important ❤️.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Prerequisites</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To get started with this project, you will need the following knowledge and tools.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Using the command line</li><li>Discord client setup and ready to go</li><li>Basic knowledge of Node.js applications</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Don't worry, it's not too technical and explained step-by-step for you.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Setting Up a Discord Bot</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let's start with the configuration side. We'll be setting up a Discord bot, but let's make our test server for our new bot before we get there.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open your Discord client and click the plus icon:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4857,"width":687,"height":556,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/discord-bot-1.png" alt="Adding new discord channel" class="wp-image-4857" width="687" height="556"/><figcaption><meta charset="utf-8"><em>Adding new Discord channel</em></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Please fill out the details as to what server you'll be creating. For this article, it doesn't matter what you choose.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once that is done, and your server is up and running. Then we can head over to the <a href="https://discord.com/developers/applications" target="_blank" rel="noreferrer noopener">Discord Developer Portal</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Click on the New application button on the top right of the screen:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4859,"width":646,"height":421,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/discord-bot-2.png" alt="New Discord application" class="wp-image-4859" width="646" height="421"/><figcaption><meta charset="utf-8"><em>New Discord application</em></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>On the pop-up, fill out whatever your app should be named. I used <code>discord-test-bot</code>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the left menu, click on the <code>Bot</code> item, and click the <code>Add Bot</code> button:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4860,"width":745,"height":485,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/discord-bot-3.png" alt="Discord new bot" class="wp-image-4860" width="745" height="485"/><figcaption><meta charset="utf-8"><em>Discord new bot</em></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>You can then give this bot an image and name, making it friendly and personal!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another critical step is to make sure we give the app and our bot the correct rights.<br>To manage the rights, head over to the Oauth2 section.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For scopes, turn on the <code>Bot</code> scope. Then scroll down and select <code>Send Messages</code> and <code>Read Message History</code>:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4861,"width":696,"height":498,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/discord-bot-4.png" alt="Bot access rights" class="wp-image-4861" width="696" height="498"/><figcaption><meta charset="utf-8"><em>Bot access rights</em></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Then we need to add this bot to the server we just created. We can do this by copying the link under the scopes section and opening that in a separate window.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It will pop up a select, where you can choose what server you like to add the bot to:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4862,"width":583,"height":674,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/discord-bot-5.png" alt="Add bot to discord channel" class="wp-image-4862" width="583" height="674"/><figcaption><meta charset="utf-8"><em>Add bot to Discord channel</em></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The last thing we need from the developer portal is the token. We can head back to the Bot menu item and click the copy button on the token part:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4863,"width":643,"height":460,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/discord-bot-6.png" alt="Copy Discord bot token" class="wp-image-4863" width="643" height="460"/><figcaption><meta charset="utf-8"><em>Copy Discord bot token</em></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We'll use this token to give our bot access to do something.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Creating the Node.js Discord Script</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Alright, now that this admin part is done, let's start on our Node.js script.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open your favorite terminal and create a new project directory and initialize node.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">mkdir discord-bot &amp;&amp; cd discord-bot
npm init -y</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p><em>Note: The -y parameter answers all questions of the CLI with yes (saves us some enters)</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Next, we'll be using a couple of NPM packages, so let's install those using our terminal.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">npm install axios discord.js dotenv</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This will install the following packages, which we'll use for:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><code>axios</code>: Making http requests to the quotes API</li><li><code>discord.js</code>: The Discord NPM package</li><li><code>dotenv</code>: Enables environmental config files</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>With this in place, let's create our <code>.env</code> file first. This file will hold the Discord bot token we just copied.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">TOKEN=YOUR_TOKEN</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p><em>Note: Replace YOUR_TOKEN with the actual token you got from the bot setup.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now, create an <code>index.js</code> file in your editor. The first thing we'll add is all our config.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>require('dotenv').config();
const Discord = require('discord.js');
const axios = require('axios');
const TOKEN = process.env.TOKEN;
const bot = new Discord.Client();</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>As mentioned, we won't make an ordinary bot. Our bot will be responding to people who seem to be sad on Discord.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For this, we'll create an array of words that sound sad. You can, of course, enhance this list to your wish.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const targets = &#91;'sad', 'angry', 'unhappy', 'miserable', 'down'];</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The idea is that when a user uses any of those words, we lift them with a quote.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The next part will be to log in to the bot. This is something the Discord NPM package handles for us, so we have to call the following line of code.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this line, we call the login function of the bot and pass our token to it.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>bot.login(TOKEN);
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Then we can also see if our bot is connected by executing the following script.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>bot.on('ready', () =&gt; {
console.info(`Logged in as ${bot.user.tag}`);
});</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>But more importantly, we want to listen to messages being sent on the Discord server and react to those.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To listen to messages, we use the following function.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>bot.on('message', (msg) =&gt; {
// Execute code
});</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>We want to add a check to see if the message was not by any bot. Else we might create an infinite loop 👀.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>if (msg.author.bot) return;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>That line will stop the function when a bot posts a message.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The next part will be to see if the user used any of our target words.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const foundWord = targets.find((target) =&gt; msg.content.includes(target));
if (foundWord) {
console.log(`Found the word ${foundWord}`);
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>A quick recap for what's going on, we use the JavaScript array method “<code>find</code>“ to loop over each of our target words. When the message includes that word, it breaks the find method and will return that word.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Example:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>User types message: "I'm angry and sad at the same time"</li><li>We'll loop over our targets</li><li>The first hit is sad</li><li>We found the word sad</li><li>Console logs: "Found the word sad"</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>That is enough for now, we could check the other way around, but this is the more efficient solution.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The next step is to query a quotes API and return a random quote to uplift the person.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>axios.get('https://type.fit/api/quotes').then((response) =&gt; {
// API response inside response object
});</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This is an array, so let's try and get a random item from this array.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">const randomQuote = response.data&#91;Math.floor(Math.random() * response.data.length)];</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Bear with me here. We define a new variable and call the response.data array, we then pass the number of the item we want to retrieve.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As the variable, we send the Math where we get a random number with a max of all items in the object.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The last thing we need to do is respond to this user with a nice message:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>msg.channel.send(`Don't be ${foundWord}\n${randomQuote.author}once said:\n${randomQuote.text}`);</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>And now, let's run the script and test it out!</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">node index.js</code></pre>
<!-- /wp:code -->
<!-- wp:image {"align":"center","id":4864,"width":680,"height":550,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/discord-bot-7.png" alt="Discord chatbot responding with uplifting messages" class="wp-image-4864" width="680" height="550"/><figcaption><meta charset="utf-8"><em>Discord chatbot responding with uplifting messages</em></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>And there we go! Our Discord bot is responding with an uplifting message. The message will change every time someone mentions one of our trigger words. If you're looking for the source code, I hosted the code on <a href="https://github.com/rebelchris/node-discord-bot" target="_blank" rel="noreferrer noopener">GitHub</a>.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Node.js</category>
<author>Chris Bongers</author>
<pubDate>Mon, 16 Aug 2021 16:21:27 +0000</pubDate>
</item>
<item>
<title><![CDATA[ A Practical Guide to Containerizing Node.js Applications With Docker ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/containerizing-node-js-applications-with-docker ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Node.js and Docker are probably the most uttered words these days in the web development scene and rightfully so. Both of these technologies have brought about changes so big that they can be considered evolutions. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Yet, so many people struggle to containerize their Node.js application with Docker efficiently. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this article, you’ll not only learn about putting your application inside an image but also optimizing that image to have a very small size and high stability. You’ll also learn about working with networks, volumes, and docker-compose.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's dive in!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Prerequisites</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This article assumes that you have experience working with Node.js and have developed APIs using Express.js in the past. Most of the work throughout this article will be done in a terminal and all the containers will be Linux containers so having familiarity with one of the distros will help.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The focus of this article will be on containerizing Node.js applications and will assume that you already have Docker installed on your system and basic knowledge of working with the tool. If you’re looking for a resource that’ll teach you Docker from the ground up, <a href="https://docker-handbook.farhan.dev/" target="_blank" rel="noreferrer noopener">The Docker Handbook</a> is highly recommended.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Project Code</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This is a project-based article. You’ll work with a simple notes application API powered by Express.js and PostgreSQL. The code can be found on the <a href="https://github.com/fhsinchy/docker-handbook-projects" target="_blank" rel="noreferrer noopener">fhsinchy/docker-handbook-projects</a> GitHub repository. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Just make a fork and clone that on your local system. Make sure you’re on the <strong>master</strong> branch and open the <strong>notes-api</strong> directory from this repository in your favorite code editor. I prefer <a href="https://code.visualstudio.com/" target="_blank" rel="noreferrer noopener">Visual Studio Code</a> with the official <a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker" target="_blank" rel="noreferrer noopener">Docker Extension</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Containerizing a Node.js API</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let me give you an overview of the <strong>notes-api</strong> project. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is a very simple notes application that lets you create, read, update, and delete notes from the database. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There is no hassle of authentication whatsoever. The application is powered by Express.js and uses PostgreSQL as its database system. It uses <a href="https://knexjs.org/" target="_blank" rel="noreferrer noopener">Knex.js</a> as the query builder and <a href="https://vincit.github.io/objection.js/" target="_blank" rel="noreferrer noopener">Objection.js</a> as the object-relational mapper. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The project structure is as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4814,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejs-docket-1.png" alt="Containerizing a Node.js API" class="wp-image-4814"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The <strong>api</strong> subdirectory contains the application source code. The <strong>boot.sh</strong>, <strong>build.sh</strong>, <strong>destroy.sh</strong>, <strong>shutdown.sh,</strong> and <strong>Makefile</strong> will come into action later in this article. For now, just ignore them.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Before you start to write the necessary code for containerizing this application, plan out the individual steps. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In my opinion, the containerization process of this application should have the following steps:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Get a good base image for running JavaScript applications, like <a href="https://hub.docker.com/_/node" target="_blank" rel="noreferrer noopener">node</a>.</li><li>Set a working directory other than the root.</li><li>Copy the package.json file into the image.</li><li>Install necessary dependencies.</li><li>Copy the rest of the project files.</li><li>Start the server by executing the <code>npm run start</code> command.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Let’s implement these steps in code. Create a new file <strong>notes-api/api/Dockerfile</strong> with the following content:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">FROM node:lts
WORKDIR /app
COPY ./package.json .
RUN npm install
COPY . .
CMD &#91;"npm", "run", "start"]</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>A Dockerfile is a collection of instructions that the Docker daemon uses to build a new image. Images are multi-layered self-contained files that act as the template for creating containers and each line of Dockerfile will create a new layer of the resultant image. The explanation for each of these lines are as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>The <code>FROM</code> instruction sets the official <code>node:lts</code> image as the base for the resultant image granting it all the capabilities necessary for running any JavaScript application out there.</li><li>The <code>WORKDIR</code> instruction sets <code>/app</code> as the working directory for this image. By default, all the images use the root as their working directory. If you do not set it to something else, in the beginning, then all the project files will be sprayed all over the container root, which is not a good thing.</li><li>The first <code>COPY</code> instruction of this file copies the <strong>package.json</strong> file from the local directory to the image’s working directory.</li><li>The <code>RUN</code> instruction executes the <code>npm install</code> command inside the image working directory and installs all the necessary dependencies.</li><li>The second COPY instruction copies everything from the local project directory to the image’s working directory. </li><li>Finally, the <code>CMD</code> instruction sets the default command for this image to be <code>npm run start</code> so that when you start a container using this image, it starts the application server automatically.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>To create a new image from this Dockerfile, open your terminal inside the <strong>notes-api/api</strong> directory and execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">docker image build --tag notes-api .</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The <code>docker image build</code> command is used for creating new images from a Dockerfile. The <code>--tag</code> option assigns a human-readable name to the image. If you do not tag the image manually Docker will assign a random string as the name. The <code>.</code> at the end of the command sets the current directory as the context of this build.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>During the build process, the Docker daemon will have access to the files within the build context. All the files that should be included in the image along with the Dockerfile must exist in the build context.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There is also a file <code>notes-api/api/.dockerignore</code> that contains the list of files and directories that should not be included in the image. The syntax of the file is identical to the <code>.gitignore</code> files:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">.git
*Dockerfile*
*docker-compose*
node<em>_modules</em></code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Depending on your internet connection and computer, the build process should finish within a few minutes. The output from the command should look as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4815,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocket-2.jpeg" alt="Containerizing a Node.js API" class="wp-image-4815"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see, a new image has been built. The image can be identified using the image id <strong>a969313c3d51</strong> or the image tag <strong>notes-api:latest</strong>. The image id will be different on your machine but the tag will be the same as mine. To start a new container using this image, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>docker container run --rm --name notes-api --publish 3000:3000 notes-api:latest
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The <code>docker container run</code> command is used for creating and starting a new container from an image. The <code>--rm </code>option indicates that the container should be removed when stopped. The <code>--name</code> option allows you to set a custom name for this container. If you omit this option, Docker will assign a randomly generated name to the container.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The <code>--publish</code> option allows you to map a port from the container to a port on your local system. The application inside the container runs on port 3000 by default. So by writing <code>--publish 3000:3000</code>, you’re mapping port 3000 inside the container to port 3000 on your local system, where the left one is the host system port and the right one is the container port. If you write <code>--publish 3030:3000</code> then port 3000 from the container will be mapped to port 3030 on the local system.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The <code>notes-api:latest</code> is the image name and it has to come as the last argument of this command. Output from this command should be as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4816,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocker-3.png" alt="Containerizing a Node.js API" class="wp-image-4816"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>You should be able to access the API on <a href="http://127.0.0.1:3000" target="_blank" rel="noreferrer noopener">http://127.0.0.1:3000</a> from your browser:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4817,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocker-4.jpeg" alt="Containerizing a Node.js API" class="wp-image-4817"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>But if you navigate to <a href="http://127.0.0.1/notes" target="_blank" rel="noreferrer noopener">http://127.0.0.1/notes</a>, you’ll face the following error:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4818,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocker-5.jpeg" alt="Containerizing a Node.js API" class="wp-image-4818"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This is happening because the API is failing to make a connection with a database. The API is getting an <strong>ECONNREFUSED</strong> or <strong>ERROR CONNECTION REFUSED</strong> on port 5432, the default port for PostgreSQL. In the next section, you’ll learn about cross container connection in Docker using Docker Networks.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Connecting to a Database Container</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The <strong>notes-api</strong> application uses PostgreSQL as its database system. Running a PostgreSQL container using the official <a href="https://hub.docker.com/_/postgres" target="_blank" rel="noreferrer noopener">postgres</a> image is very simple.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>docker container run --rm --detach --name=notes-db --env POSTGRES_DB=notesdb --env POSTGRES_PASSWORD=secret postgres:12</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>That’s all it takes. The detach command will start the container as a background server so that you don’t have to keep the terminal open. The<code> --env</code> option allows you to pass environment variables to the container. The <code>POSTGRES_DB</code> environment variable is optional but the <code>POSTGRES_PASSWORD</code> environment variables are required by the server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now that you have a PostgreSQL server running, you may think that you can publish the PostgreSQL container on port 5432 of the local system and connect to <a href="http://127.0.0.1:5432" target="_blank" rel="noreferrer noopener">http://127.0.0.1:5432</a> from the API but that’s plain wrong.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The problem with containers is that they are completely isolated environments and <a href="http://127.0.0.1" target="_blank" rel="noreferrer noopener">http://127.0.0.1</a> or <a href="http://localhost" target="_blank" rel="noreferrer noopener">http://localhost</a> inside a container refers to the container itself. So if you try to connect to <a href="http://127.0.0.1:5432" target="_blank" rel="noreferrer noopener">http://127.0.0.1:5432</a> from the <strong>notes-api</strong> container, it will not find the <strong>notes-db</strong> container.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The ideal way for connecting two containers in Docker is by using a user-defined bridge network. A network is a logical object just like a container or an image in Docker. To create a new network in Docker, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">docker network create notes-network</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You’ll see a long string printed out on the terminal as output. You can list networks using the <code>docker network ls</code> command remove them by executing the <code>docker network rm NETWORK_NAME</code> command.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To attach the database container to this network, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">docker network connect notes-network notes-db</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The command will not yield any output. To check if the container has been added to the network or not, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">docker network inspect --format='{{range .Containers}} {{.Name}} {{end}}' notes-network</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you see <strong>notes-db</strong> in the output, that means the container has been added to the network. You can use the docker network detach <code>NETWORK_NAME CONTAINER_NAME</code> command to detach a container from a network.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now it’s time to connect the <strong>notes-api</strong> container to this network. To do so, stop the previously running <strong>notes-api</strong> container by hitting <strong>Ctrl + C</strong> twice on the terminal window or closing the terminal window completely.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Create and start a new container by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>docker container run --rm --detach --name notes-api --publish 3000:3000 --network notes-network --env DB_HOST=notes-db --env DB_DATABASE=notesdb --env DB_PASSWORD=secret notes-api:latest</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The<code> --network</code> option lets you attach this container with a network from the beginning. The <code>DB_HOST</code>, <code>DB_DATABASE</code>, and <code>DB_PASSWORD</code> environment variables are required by the API for connecting to the database server. The <code>DB_HOST </code>refers to the database server endpoint.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One of the benefits that a custom bridge network provides in Docker is automatic DNS resolution between containers which means, as long as two containers are on the same network, they can connect to each other by simply using their names. Docker will replace the container name with the proper IP address when needed.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Two things that you have to remember when connecting multiple containers are:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>The containers must have custom names. Randomly generated names by Docker will not work.</li><li>The network has to be a user-defined bridge network. The default bridge network will not provide automatic DNS resolution.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The different types of networks that Docker has are out of the scope of this article. If you want to learn about them, however, I’ll leave links at the end of this article.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now to make sure that both the <strong>notes-api</strong> and <strong>notes-db</strong> containers are indeed attached to the <strong>notes-network</strong> network, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">docker network inspect --format='{{range .Containers}} {{.Name}} {{end}}' notes-network</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you see the names of both containers show up in the output, that means both of them have been attached to the network. The final step to make the database work is running the migrations. To do so, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">docker container exec notes-api npm run db:migrate</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The docker container exec command allows you to execute commands inside a given container. The <code>npm run db:migrate</code> command creates all the tables in the database. If everything goes fine, the output from the command should be as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4819,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocker-6.png" alt="Connecting to a Database Container" class="wp-image-4819"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>If you see any error, that means you may have made some mistake. Recheck all the steps and make sure you haven’t mistyped anything or missed any of the environment variables.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Persisting Data in Volumes</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The work you’ve done so far is solid but there is one problem. If you stop the database container, Docker will remove it from memory along with all the data. This is not expected behavior. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For these kinds of scenarios, you can make use of named volumes. These volumes let you persist container data outside of the container so as long as you don’t delete the volume, the data will persist regardless of whether the container exists or not.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Volumes in Docker are logical objects like Containers or Networks. You can create a new volume by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">docker volume create notes-db-data</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You’ll get the name of the volume as output. You can list all the volumes in your system by executing the <code>docker volume ls</code> command.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can not attach volumes to containers that are already running. First, stop the <strong>notes-db</strong> container by executing the <code>docker container stop notes-db</code> command and then run a new container with a volume by executing the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>docker container run --rm --detach --name=notes-db --env POSTGRES_DB=notesdb --env POSTGRES_PASSWORD=secret --volume notes-db-data:/var/lib/postgresql/data postgres:12</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The data from the database are usually persisted in the<code> /var/lib/postgresql/data</code>&nbsp;directory on the container filesystem. So if you mount this directory to the&nbsp;<strong>notes-db-data</strong>&nbsp;volume, the data will be tucked away inside that volume instead of the container filesystem. If you ever want to get rid of this volume, you can do that by executing the&nbsp;<code>docker volume rm VOLUME_NAME</code>&nbsp;command.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Optimizing Your Image</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You’ve already learned about containers, images, networks, and volumes. In this section, you’ll learn about optimizing your image to have better stability and smaller size.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>First, let’s have a look at the size of the unoptimized <strong>notes-api</strong> image size by executing the<code> docker image ls</code> command.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4825,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/optimizing-your-image-1.png" alt="Optimizing Your Image" class="wp-image-4825"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see, the <strong>notes-api</strong> is <strong>1.01 gigabytes</strong> in size which in my sense is insane for an application so small. The reason behind this gigantic image size is due to all the unnecessary stuff in the image. The <strong>node:lts</strong> image is based on the Debian Stretch image which itself is quite large.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One way to solve this issue is using a smaller base image like <strong>node:lts-slim</strong> or the <strong>node:lts-alpine</strong> image. The slim images are also based on Debian Stretch but have fewer preinstalled programs. The alpine-based images on the other hand are the smallest. Alpine Linux is a lightweight, secure Linux distribution made for containers. Let’s update the Dockerfile to use Alpine Linux instead.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open the<code> notes-api/api/Dockerfile</code> and update its content as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8">FROM node:lts-alpine
# install dependencies for node-gyp
RUN apk add --no-cache python make g++
ENV NODE_ENV=production
USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
COPY ./package.json .
RUN npm install
COPY . .
CMD &#91; "node", "bin/www" ]</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>There are several changes in the updated code. Instead of the <code>node:lts</code> image, you’re now using <code>node:lts-alpine </code>image. A lot of the Node.js packages require a working C++ toolchain and a python installation to be compiled. The first <code>RUN</code> command installs<code> g++</code> and <code>python</code> in the image.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Just like <code>apt</code> in Ubuntu, Alpine uses <code>apk</code> for package installation. The ENV instruction sets the <code>NODE_ENV </code>environment variable to <code>production</code> by default. The <code>USER</code> instruction sets the default user for this image. By default, all Docker containers run as the root user. Using the root user by default is not only insecure but also causes stability issues for Node.js.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The solution to this problem is using a different user. The <code>node</code> user comes by default in the base image. The non-root user doesn’t have write access to any directory except its home directory. The home directory for any user in a Linux-based system is <code>/home/USERNAME</code> and that’s why the <code>WORKDIR</code> instruction now sets the <code>/home/node/app</code> directory as the working directory. The second RUN command simply creates the aforementioned directory using the <code>mkdir </code>program.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The rest of the code is almost the same except for the <code>CMD</code> instruction. Instead of using an npm script, you’re using node to bootstrap the <code>notes-api/api/bin/www</code> script. This allows the operating system signals to reach the node executable directly instead of getting consumed by npm. This is why you had to set the <code>NODE_ENV </code>environment variable to production manually this time. The previously used npm script sets the variable during execution automatically.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Rebuild the image by executing the docker image build <code>--tag notes-api .</code> command and check the size by executing the <code>docker image ls</code> command.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4824,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocker-7-1.png" alt="Optimizing Your Image" class="wp-image-4824"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see the image size has come down to 384 megabytes. More than 600 megabytes less. But it can be smaller by implementing a multi-stage build.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code><meta charset="utf-8"># stage one
FROM node:lts-alpine as builder
# install dependencies for node-gyp
RUN apk add --no-cache python make g++
WORKDIR /app
COPY ./package.json .
RUN npm install
# stage two
FROM node:lts-alpine
ENV NODE_ENV=production
USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
COPY . .
COPY --from=builder /app/node_modules&nbsp; /home/node/app/node_modules
CMD &#91; "node", "bin/www" ]</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Instead of building the image one go, you’re dividing the process into two steps. The first step is the builder step. You use<code> node:lts-alpine</code> as the base, install all necessary build tools, set <code>/app</code> as the working directory and install all the dependencies. That’s the end of stage one.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The second stage also uses <code>node:lts-alpine</code> as the base. This stage is almost identical to the previously written single-stage Dockerfile. Instead of copying the package.json file and installing the dependencies, you copy the <code>node_modules</code> directory from the builder step and use that here. This allows you to skip the installation of all the unnecessary build tools. After building the image, Docker will discard the contents of the first stage.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Rebuild the image by executing the docker image build <code>--tag notes-api . </code>command and check the size by executing the docker image ls command.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4823,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocker-8-1.png" alt="Optimizing Your Image" class="wp-image-4823"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see, the resultant image is now only 128 megabytes in size which is only 12% of the initial image size, 1.01 gigabytes.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Writing Helper Scripts</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Managing the different containers, networks, and images manually while working on a multi-container project can become hectic. One way to make things easier is by writing some helper scripts. The <strong>notes-api</strong> project comes with some helper scripts by default. These are as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>The <strong>build.sh</strong> script is responsible for building the images, creating the network, containers, and volumes. The script also starts the containers once they are created.&nbsp;</li><li>The <strong>destroy.sh</strong> script is responsible for destroying all the resources created by the build script.</li><li>The <strong>shutdown.sh</strong> script on the other hand will only stop the running containers, not remove them.</li><li>The <strong>boot.sh</strong> file can restart containers stopped by the shutdown script.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>I won’t get into explaining all these shell scripts. These are optional and if you’re familiar with writing shell scripts, go ahead and take a look at them.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Making Things Easier With Docker Compose</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>So far you’ve seen how you can containerize a Node.js application efficiently. In this section, you’ll learn about setting up a proper Docker Compose configuration file to make working with the application locally easier.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Docker Composer is another tool that makes working with multi-container projects a breeze. Instead of creating containers and connecting them manually, you write all the configurations inside the YAML file and Docker Compose will read the file and boot up the containers for you.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Create a new file <strong>notes-api/docker-compose.yaml</strong> with the following content:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4822,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/nodejsdocker-9.png" alt="Making Things Easier With Docker Compose" class="wp-image-4822"/><figcaption><meta charset="utf-8"><a href="https://gist.github.com/fhsinchy/26a78ad31d9f4b252ec01ec3c153ae56" target="_blank" rel="noreferrer noopener">https://gist.github.com/fhsinchy/26a78ad31d9f4b252ec01ec3c153ae56</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Every valid docker-compose file starts with the file version number. At the writing of this article, the latest version was 3.8. You can always have a look at the official <a href="https://docs.docker.com/compose/compose-file/" target="_blank" rel="noreferrer noopener">reference</a> to find out what’s the latest.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The <code>services</code> section contains definitions for the different containers for this project. There are be two containers in this project. The <code>db</code> container and the <code>api </code>container.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The definition for the <code>db</code> container is identical to the command you used to start the database container in a previous section. Instead of creating the volume manually, you define it under the <code>volumes</code> section.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The <code>api container</code> uses the <code>./api</code> directory as the build context. The default command of the image has been overridden by a new one. In development mode, the application uses <a href="https://nodemon.io" target="_blank" rel="noreferrer noopener">nodemon</a> to reload the application automatically on code changes.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The environment variables are self-explanatory. Under the volumes section, there are two entries. The first one is an anonymous volume. Writing <code>/home/node/app/node_modules</code> basically instructs Docker to tuck away the content of <code>nodes_modules</code> directory to somewhere else than the container filesystem. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The second one is a bind mount. By writing <code>./api:/home/node/app</code> you’re instructing Docker to map the content of the<code> /api</code> directory from the local filesystem to the <code>/home/node/app</code> directory inside the container. This allows code changes on the local filesystem to be reflected inside the container instantly. If you do not put the <code>node_modules </code>inside an anonymous volume, its content will be overridden by the bind mount.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open your terminal on the <strong>notes-api</strong> directory and execute the <code>docker-compose up --detach</code> command to start the containers. Docker-compose will build the image if necessary. If you want to force image rebuilding you can use the <code>--build</code> option for the <code>docker-compose up</code> command.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To stop running containers execute the <code>docker-compose stop</code> command and to destroy the containers along with the volumes, execute the <code>docker-compose down --volume</code> command. You can migrate the database by executing the <code>docker-compose exec api npm run db:migrate </code>command once the containers are up and running.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you have working experience with <a href="https://www.gnu.org/software/make/" target="_blank" rel="noreferrer noopener">GNU Make</a>, you can call the functions defined in the <code>notes-api/Makefile</code> by following the <code>make FUNCTION_NAME</code> command syntax. So executing <code>make dev-start</code> command will invoke the <code>dev-start </code>function.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I would like to thank you for the time you've spent reading this article. I hope you've enjoyed it and have learned some useful stuff regarding Node.js and Docker. If you want to learn Docker from the ground up, consider checking out my open-source <a href="https://docker-handbook.farhan.dev" target="_blank" rel="noreferrer noopener">Docker Handbook</a> with tons of fun content and several practical projects. Till the next one, stay safe and keep on learning.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Node.js</category>
<author>Farhan Hasin Chowdhury</author>
<pubDate>Mon, 09 Aug 2021 09:54:15 +0000</pubDate>
</item>
<item>
<title><![CDATA[ The Lowdown on Agile Product Backlog Prioritization ]]></title>
<link><![CDATA[ https://adevait.com/blog/agile-work/agile-product-backlog-prioritization ]]></link>
<description><![CDATA[ <!-- wp:heading -->
<h2>What Is Product Backlog in Agile?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The product backlog is a simple prioritized list of deliverables. You should think of it as a list containing some new features or as a wish list that has everything you'd like to see in your product. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In short, it's a set of tasks containing some short descriptions about the features the product owner wants to see in a product. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The product backlog in Agile is a crucial aspect of development. It will help you estimate how much time it takes for implementation, refining the process, and prioritizing everything you want to get done. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We can safely say that product backlog is a decision-making document, or a collection of multiple source feedback, i.e., from users, sales, and other developers. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Tips for Product Backlog Management</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We already established that Product Backlog prioritization is the most important thing that will guide your Agile team.&nbsp;Why? Because it does a great job at breaking down the requests or feedback into a set of more manageable tasks.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here's how the product backlog management might go:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>The product owneer clearly describes the tasks and expectations without tech specifications. </li><li>The backlog is reviewed and discussed in backlog review sessions, where the developers (Wordpress, Java, React.js, React Native, <a href="https://adevait.com/ios" target="_blank" rel="noreferrer noopener">iOS developer</a>, or any other kind), estimate the items that are of importance at the time being or the items that are necessary to make a decision about. </li><li>The items are prioritized so that the most important things needed to be done first are singled out.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The developers' estimations are essential because they are the ones that will define the number of items from the backlog list that are going to be selected for the upcoming sprint.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Product backlog management is a rather complex process in which the product owner collaborates with other people to make sure that when the product comes into the hands of a customer, it will be in the most perfect form. Moreover, this is done by adjusting and grooming the backlog while prioritizing the product backlog.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4745,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/08/Managing-a-Product-Backlog.png" alt=" Managing a Product Backlog" class="wp-image-4745"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>Best Tips on Managing a Product Backlog</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Start Having the Vision of Your Final Product in Mind</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To ensure proper product backlog management, it's best to start developing the product with the final result in mind.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, it's important to mention that the product vision might change due to a range of factors, such as industry changes. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, you may start with one vision for your product but make major changes once you gather feedback and test the market. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once you have your product strategy ready, it will be much easier to develop your product vision or at least improve it. Why? Let's say that you create your product strategy. After conducting market research and competitor analysis, you might see that your target customers need a different version of your initial product. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Make the Backlog Manageable Again</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the most common mistakes made when creating a product backlog is an exhaustive list with hundreds of items. Your product backlog becomes unmanageable and loses in transparency.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Improve the Collaboration Between Teams</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Instead of just the product owner creating the backlog, it would be best to encourage frequent communication between the product owner and the Agile development team. In this way, you'll get the most successful backlog management possible.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Agile Backlog Management Challenges</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Product backlog prioritization<strong> </strong>is the primary way to manage roadmap and gain predictability in an Agile dev organization. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, keep in mind that if your product backlog grows uncontrollably, then the value it is supposed to provide may diminish proportionately. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><meta charset="utf-8"> An unnecessarily long product backlog can <meta charset="utf-8">weaken the team and ultimately become unmanageable and irrelevant. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Speaking truthfully, product backlog prioritization isn’t something one must do, but it's one of the easiest ways to control your product backlog from becoming unnecessarily long.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With an unnecessarily large product backlog, the only thing that will be achieved is the lost sight of the long-term goals the product owner had in mind.&nbsp; </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>That's why a better option would be to have those significant long-term goals of the project split up into a set of smaller tasks that will ultimately lead to the successful achievement of the long-term goals.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Some of the issues caused by an unreasonably long backlog are:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Reduction on the value</li><li>Inhibited innovation</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>It’s important to note that such issues can be avoided if the PO manages the backlog properly. Everything should be clear enough and only top prioritized items should be discussed with the team.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here are some additional tips for successful Product Backlog Management:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Consider using some tools that have been shown to be very effective in visualizing the strategy you’re going to use for your product.&nbsp;</li><li>A good connection between the product management, product owners, and the product development team is vital for a successful product backlog management</li><li>Although the product owner is one of the most important individuals that should be up-to-date with everything, the other stakeholders shouldn’t be kept out of the loop. Moreover, the product owner must provide all the backlog information, the latest updates, as well as full transparency regarding the backlog allowing the stakeholders to review the data and provide feedback.</li><li>Hold “grooming” meetings where the current backlog will be discussed in great detail.</li></ul>
<!-- /wp:list -->
<!-- wp:image {"align":"center","id":4746,"width":660,"height":461,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img src="https://static.adevait.com/2021/08/Product-Backlog-to-Sprint-Backlog.png" alt="Product Backlog to Sprint Backlog" class="wp-image-4746" width="660" height="461"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>Product Backlog vs. Sprint Backlog: What Is the Difference?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>When it comes to sprint planning, a product backlog is a list of the tasks or requirements that need to be done before launching a product. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Sprint backlogs are lists of work the team commits to do within the sprint. The product backlog may never be completed, but it is continually updated and refined as new features are added or old ones removed. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A sprint backlog is a subset of the product backlog and contains one week's worth of work.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To guarantee the success of the Agile Project, Scrum teams need to grasp core business imperatives and work efficiently to keep the focus on priority issues with the most extensive business impact, even under changing conditions.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Product backlog prioritization is one of the most important things on the product owner’s checklist. Also, in both methodologies, the Product Backlog, as well as the Sprint Backlog, the most important thing is the communication between the product owner and the product development team. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The product backlog delivery must likewise be kept targeted. In particular, each need during prioritizing is analyzed to see whether it is essential for the technological architecture or to provide value to the company.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It gets moved into the lowest end of a backlog or may even be deleted if it does not fall into any of these categories. This helps guarantee that only mandatory applicants are included in the backlog.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Agile</category>
<author>Ivana Janakieva</author>
<pubDate>Thu, 05 Aug 2021 00:21:45 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Java for Loops: Explained with Examples ]]></title>
<link><![CDATA[ https://adevait.com/java/java-for-loops ]]></link>
<description><![CDATA[ <!-- wp:heading -->
<h2>Introduction</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Repetition, together with decision and code reuse, is one of the building blocks of any programming language. Java followed the tradition of C-family programming languages and offered a for loop since version 1. Java 5 introduced a for-each loop, giving us an easier form of iteration over arrays and collections.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Basic for Statement</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This is the basic for loop you find in C-family programming languages. It is also known as a numeric loop.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It has three parts, separated by a semicolon: initialization, condition, and advancement. All three parts are optional, though most of the time you'll need them all.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>for (&lt;initialization&gt;; &lt;condition&gt;; &lt;advancement&gt;) {
//
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the first part, initialization, you'll initialize the control variable that is used to check when the loop should finish. As that control variable is usually only used inside the loop, it's common to also declare it in the initialization part of the for loop.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>for (int i = 0; &lt;condition&gt;; &lt;advancement&gt;) {
//
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The next part is the condition, where we decide if the loop is over. In Java, you need to write an expression that returns a boolean. When we're using the loop as a counter, which is the most frequent case, we compare the control variable with an upper limit - but that is not a requirement and depends on the algorithm you're coding.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>for (int i = 0; i &lt; 5; &lt;advancement&gt;) {
//
}
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Finally, the advancement part is where you make the control variable proceed to the next value. When counting, you simply increment the control variable.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>for (int i = 0; i &lt; 5; i++) {
System.out.println(i);
}
/*
0
1
2
3
4
*/</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The code above will print numbers from 0 to 4, which is perfect to iterate over a 5-items array like in the example below.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>int&#91;] myArray = new int&#91;] { 10, 15, 20, 31, 25 };
for (int i = 0; i &lt; 5; i++) {
int element = myArray&#91;i];
System.out.println(element);
}
/*
10
15
20
31
25
*/</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Most of the time we'll iterate from 0 to n-1 (where n is the size of the collection) because in Java these collections are indexed starting from zero. If you need to count from 1 to n, just remember to replace &lt; with &lt;= in the condition.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>for (int i = 1; i &lt;= 5; i++) {
System.out.println(i);
}
/*
1
2
3
4
5
*/</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2>Enhanced for Statement</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Since version 5, Java has an enhanced for statement - also known as for-each loop. This kind of for allows you to iterate over arrays or lists without having to calculate the index of each element or explicitly advancing an <em>Iterable</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The enhanced for has this format:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>for (&lt;loop variable&gt; : &lt;iterable&gt;) {
//
}
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The loop variable is a declaration of a variable that will assume the value of each element during the iteration. The iterable part may be an array or an object whose class implements the Iterable interface. Some common examples are <em>Collection, List, ArrayList</em>, and <em>Set</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The above example, that prints all elements of an array, would be coded like this:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>int&#91;] myArray = new int&#91;] { 10, 15, 20, 31, 25 };
for (int element : myArray) {
System.out.println(element);
}
/*
10
15
20
31
25
*/</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Notice how we don't need to calculate the index of each element. We also don't need a line just to get the indexed element from the array. As the enhanced for is shorter and more readable, it's preferable in most use cases.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Break and Continue</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Break</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Sometimes there is a need to break out of the loop. In other words, you stop iterating and jump directly to the first statement after the for body. One really frequent use of the break statement is when searching for an element:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>List&lt;String&gt; colorList = Arrays.asList("Cyan", "AliceBlue",
"Violet", "Gold");
String startingWithA = null;
for (String color : colorList) {
if (color.charAt(0) == 'A') {
startingWithA = color;
break;
}
}
System.out.println(startingWithA);
/*
AliceBlue
*/</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The above code will find the first element that starts with A, or leave the variable <em>startingWithA</em> unchanged with the value<em> null</em> if there was no element starting with that letter.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Some algorithms require nested loops and the need to break the outer loop from inside the inner loop. One option for that situation is to extract that fragment to a function and then use a <em>return</em> statement to exit from the function itself.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>private String selectColor(char&#91;] interestingLetters,
Iterable&lt;String&gt; colorList) {
for (char interestingLetter : interestingLetters) {
for (String color : colorList) {
if (color.charAt(0) == interestingLetter) {
return color;
}
}
}
return null;
}
private void printSelectedColor() {
char&#91;] interestingLetters = new char&#91;] { 'X', 'V' };
List&lt;String&gt; colorList = Arrays.asList("Cyan", "AliceBlue",
"Violet", "Gold");
String selectedColor = selectColor(interestingLetters, colorList);
System.out.println(selectedColor);
}
/*
Violet
*/</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The code above uses that strategy: we have a <em>selectColo</em>r function that finds the first color that starts with any of the interesting letters it received in the first parameter. As we needed to break all the loops at once, we used the return statement there. We couldn't have that return inside the <em>printSelectedColor</em> function because then we would exit that function too early and the following line (the call to <em>println</em>) wouldn't execute.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Continue</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The continue statement skips the rest of the for body and starts the next iteration. It's useful to flatten big ifs that enclose the for body entirely.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The following example creates a list with color names that start with a G and have up to 5 characters:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>List&lt;String&gt; colorList = Arrays.asList("Green", "AliceBlue",
"Violet", "GreenYellow");
List&lt;String&gt; shortStartingWithG = new ArrayList&lt;&gt;();
for (String color : colorList) {
if (color.charAt(0) == 'G') {
if (color.length() &lt;= 5) {
shortStartingWithG.add(color);
}
}
}
System.out.println(shortStartingWithG);
/*
&#91;Green]
*/</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This works but look at all the indentation needed inside the for body. That is considered to be less readable and one way to fix it is to use the continue statement as shown below.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>List&lt;String&gt; colorList = Arrays.asList("Green", "AliceBlue",
"Violet", "GreenYellow");
List&lt;String&gt; shortStartingWithG = new ArrayList&lt;&gt;();
for (String color : colorList) {
if (color.charAt(0) != 'G') {
continue;
}
if (color.length() &gt; 5) {
continue;
}
shortStartingWithG.add(color);
}
System.out.println(shortStartingWithG);
/*
&#91;Green]
*/</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2>Advanced Use Cases</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>For-Each with index</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are times where you want or need to use a for-each loop but also need the index. For these situations, you can calculate the index explicitly. Just remember to initialize the counter right before the loop, and to increment it just before closing the loop body:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>List&lt;String&gt; colorList = Arrays.asList("Cyan", "AliceBlue",
"Violet", "Gold");
int i = 1;
for (String color : colorList) {
System.out.println(i + " - " + color);
i++;
}
/*
1 - Cyan
2 - AliceBlue
3 - Violet
4 - Gold
*/</code></pre>
<!-- /wp:code -->
<!-- wp:heading {"level":3} -->
<h3>Iterator Interface</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The enhanced for statement works out of the box with the modern <em>Iterable</em> interface, but there are a few classes in the JDK that use more ancient interfaces. One of these almost deprecated interfaces is the <em><a href="https://docs.oracle.com/javase/7/docs/api/java/util/class-use/Iterator.html">Iterator</a> </em>interface. It's implemented, for example, by the <a href="https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html"><em>Scanner</em></a> class. The Scanner class can be used to parse space-separated words or other primitives (like integers or floats) from a string. We could use the basic for loop to iterate over its result.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>String input = "10 15 20 35";
for (Scanner scanner = new Scanner(input); scanner.hasNextInt();) {
int number = scanner.nextInt();
System.out.println(number);
}
/*
10
15
20
35
*/</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>As you can see, the advancement part of the loop is unused because it is not needed in this case. Arguably, <em>Iterators</em> are best iterated using the while statement as it's slightly more readable:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>String input = "10 15 20 35";
Scanner scanner = new Scanner(input);
while (scanner.hasNextInt()) {
int number = scanner.nextInt();
System.out.println(number);
}
/*
10
15
20
35
*/</code></pre>
<!-- /wp:code -->
<!-- wp:heading {"level":3} -->
<h3>Enumeration</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Another ancient interface is <a href="https://docs.oracle.com/javase/7/docs/api/java/util/class-use/Enumeration.html" target="_blank" rel="noreferrer noopener"><em>Enumeration</em></a>. This interface is used to list the files inside a ZIP file when using the <a href="https://docs.oracle.com/javase/7/docs/api/java/util/zip/ZipFile.html" target="_blank" rel="noreferrer noopener"><em>ZipFile</em></a> class. Again, we can iterate over its entries with a basic for loop:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>ZipFile file = new ZipFile("example.zip");
for (Enumeration&lt;? extends ZipEntry&gt; entries = file.entries();
entries.hasMoreElements();) {
ZipEntry entry = entries.nextElement();
System.out.println(entry.getName());
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Like in the <em>Iterato</em>r example, we're not using the third part of the loop and could rewrite it using the while statement:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>ZipFile file = new ZipFile("example.zip");
Enumeration&lt;? extends ZipEntry&gt; entries = file.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
System.out.println(entry.getName());
}</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To summarize, Java offers several options to iterate over many kinds of sequences. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Most of the time, using the for-each command will be the most readable option when working with arrays, lists, and anything similar - even in those cases when you also need an index to pair with each element. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Some exceptions are: using the basic for loop when all you need is a sequence of numbers, and using the <em>while</em> command to iterate over objects that implement the <em>Iterator</em> or <em>Enumeration</em> interfaces.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Java</category>
<author>Diogo Kollross</author>
<pubDate>Fri, 30 Jul 2021 14:56:32 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Laravel vs. Symfony: A Side by Side Comparison ]]></title>
<link><![CDATA[ https://adevait.com/laravel/laravel-vs-symfony-comparison ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>When facing the start of a brand new PHP application, there is one decision that can’t be overlooked: which framework should you use?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Theoretically, you could start with none, but assuming the project at hand is anything but trivial, that’d probably be a bad idea.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The good news is you’re not exactly short of options to choose from.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The bad news is you’re not exactly short of options to choose from, which can make the decision a little harder than you might expect.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Then again, even though there are many options out there, simply by scratching the surface you’ll notice that two stand above the rest: <a href="https://github.com/laravel/laravel" target="_blank" rel="noreferrer noopener">Laravel</a> and <a href="https://github.com/symfony/symfony" target="_blank" rel="noreferrer noopener">Symfony</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>At a glance, there’s one main difference between Symfony and Laravel which is that Symfony is both an Application Framework and a set of reusable components, while Laravel is simply a Framework. In fact, Laravel uses quite a few of Symfony’s components.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For the purpose of this post, I’ll refer to Symfony as a Framework but keep in mind that, because of how it’s built you should consider it a <em>meta-framework</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the following sections, you’ll learn the similarities and differences between them and how to choose the one that best suits the needs of your project.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Points We Will Cover in This Article</h2>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>What they have in common</li><li>Installation procedure</li><li>Directory structure</li><li>CLI tool</li><li>Configuration</li><li>ORM</li><li>Template Engine</li><li>Framework Extensions</li><li>Testing</li><li>Performance</li><li>Security</li><li>Internationalization</li><li>Project governance</li><li>Popularity</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>What They Have in Common</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Needless to say, the first similarity you’ll notice is that they are both PHP frameworks.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But that’s just the beginning. Here are the most outstanding features of both:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Open Source projects</li><li>Based on the MVC pattern (which means there are no big conceptual differences)</li><li>A CLI tool is available for common tasks</li><li>Code is organized in a particular way</li><li>Testing tools are available</li><li>Cover the full stack leveraging existing projects (ORMs, Template Engines, etc…)</li><li>Can be run on multiple platforms (Operating systems and database engines)</li><li>Have built-in internationalization features</li><li>Can be easily extended</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Now let’s get into the specifics so you can get a better understanding of their differences.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Installation Procedure</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>For the purpose of showing commands, I’ll be using a fresh Ubuntu 21.04 box virtualized using <a href="https://www.vagrantup.com/" target="_blank" rel="noreferrer noopener">Vagrant</a>, you can find the image <a href="https://app.vagrantup.com/bento/boxes/ubuntu-21.04" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Prior to running the commands, I’ll be showing you’ll have to install the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>PHP 7.2+</li><li><a href="https://getcomposer.org/" target="_blank" rel="noreferrer noopener">Composer</a>&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>When it comes to installation, they’re both fairly easy to start with, since both use composer, there’s not much mystery to it.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Installing Symfony</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The easiest way to get a Symfony project started is by running the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>composer create-project symfony/website-skeleton sfTest</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This will, assuming every dependency is met, leave you with a basic web application you can further customize to meet your needs.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>An alternative installation method, which is actually recommended by Symfony, is to <a href="https://symfony.com/download" target="_blank" rel="noreferrer noopener">install a new binary in your system</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Should you choose this option, the command used to create a new project is:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>symfony new sfTest --full</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>There are several advantages to using this method, one of them is you have a very handy command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>symfony check:requirements</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Which will help you detect and eventually fix any missing dependencies.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Either way, upon successful installation you’ll get a welcome screen telling you what the next steps are.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Installing Laravel</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Laravel also offers different ways of installing, the easiest one is running the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>composer create-project laravel/laravel lvlTest</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Another way to get a Laravel project started is by previously installing a Laravel installer (much like Symfony) by running:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>composer global require laravel/installer</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>And then:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>laravel new lvlTest</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2>Directory Structure</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Symfony Directory Structure</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>If you go into your newly created project and ask for a files list you’ll get this from Symfony:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4718,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/07/comparison-1.png" alt="Laravel vs. Symfony comparison" class="wp-image-4718"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Your code is expected to be organized as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>src will contain all of your business logic (Entities, Containers, Services, etc…)</li><li>templates will hold the presentation code (mostly html-like files)</li><li>tests will be stored in the tests directory</li><li>migrations will be the place for database upgrade scripts</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>And then there are other artifacts that have a particular place in the project:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>bin is where you’ll find useful CLI tools</li><li>vendor is where dependencies live (common behavior to every composer-based application)</li><li>config is where the configuration will be</li><li>in translations you’ll put the i18n related resources</li><li>var is a directory used internally by the framework, mostly for optimization purposes</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Finally, the public directory will be the point of contact with the outside world, here you’ll find the application’s entry point: the index.php file.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Laravel Directory Structure</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In the case of Laravel, this is what you’ll see:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4719,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/07/comparison-2.png" alt="Laravel vs. Symfony comparing the two technologies" class="wp-image-4719"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>In the case of Laravel, the code is distributed along the following directories:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>app holds the core code of your application</li><li>database is where you keep all of your database related code (Migrations, initialization scripts, Models, etc…)</li><li>in tests you’ll store your testing code</li><li>your templates and other static files will be stored at resources</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The configuration will mostly live within config, though the URL-to-Controller mapping will be stored in routes</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>CLI Tool</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In the case of Symfony, the CLI tool is found at bin/console, by simply running this command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php bin/console</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>From your project’s root directory you’ll get a complete list of available commands:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4721,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/07/comparison-3.png" alt="comparing Laravel vs. Symfony" class="wp-image-4721"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>And then, if you need help with a specific command, you can run:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php bin/console help &lt;COMMAND&gt;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>For instance, let’s look for help on make:auth command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php bin/console help make:auth</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Will produce:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4722,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/07/comparison-4.png" alt="Laravel vs. Symfony" class="wp-image-4722"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>It’s very much likely that you’ll be spending quite a bit of time using the <a href="https://symfony.com/doc/current/components/console.html" target="_blank" rel="noreferrer noopener">console component</a> if you use Symfony.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the case of Laravel, a similar tool is available right at the root directory of your application: artisan.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you run:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php artisan</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You’ll get a result like:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4723,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/07/comparison-5.png" alt="Laravel and Symfony" class="wp-image-4723"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>A very familiar look, right? The fact is artisan is built using the very same Symfony/console component, that’s why its UI is so similar to Symfony's console.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Coding Style</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Coding in Symfony is heavily based around the concept of Dependency Injection, which creates loosely coupled classes, making testing and long-term maintenance easier.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel can be used in a similar fashion but, by default, it proposes the usage of <a href="https://laravel.com/docs/8.x/facades" target="_blank" rel="noreferrer noopener">Facades</a> and <a href="https://laravel.com/docs/master/helpers" target="_blank" rel="noreferrer noopener">helper functions</a>, which, while easier to implement, can become a challenge in the long run.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>ORM</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>While virtually any ORM can be used in conjunction with Symfony, the default is <a href="https://www.doctrine-project.org/" target="_blank" rel="noreferrer noopener">Doctrine</a>, which implements the DataMapper pattern.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In Laravel, the default ORM is <a href="https://www.doctrine-project.org/" target="_blank" rel="noreferrer noopener">Eloquent</a> which is based on ActiveRecord.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The main difference between these two models is that in Doctrine entities are <a href="https://dev.to/fuadardiono/plain-old-php-object-usability-and-benefits-in-modern-php-programming-32oc" target="_blank" rel="noreferrer noopener">POPOs</a>, meaning they can be used in a variety of scenarios, even outside of the context of the ORM.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Eloquent proposes a structure where the Models are extensions to a base class that has all the logic for database access.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One advantage to using the DataMapper pattern is the ability to further optimize database operations by queueing them instead of immediately running them.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Configuration</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Symfony offers different kinds of configuration, which may be a little hard to understand at first glance.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There’s configuration by environment (.env files) which are meant to hold the very basic information for the application to run such as database access.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Then there’s the bundles configuration (YAML, XML or PHP files located within config/packages) which are meant to determine the behavior of the application in a given environment. For instance, the handling of email should not be the same in production as in testing or development.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Finally, there’s another way to deal with configuration: PHP annotations for PHP &lt; 8 and class attributes por php &gt;= 8. This is the most common case for routes and ORM mapping information.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Usually, a combination of all of them is used within a project.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The case of Laravel is a little simpler, there are .env files at the project root and simple PHP based files inside the config.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Template Engine</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In Symfony, the default template engine used is <a href="https://twig.symfony.com/" target="_blank" rel="noreferrer noopener">Twig</a> while Laravel uses <a href="https://laravel.com/docs/8.x/blade" target="_blank" rel="noreferrer noopener">Blade</a> as the default template engine but you can use a different one if you choose to… you can even opt for not using one at all!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Syntax aside there are no big differences between them, though Blade is usually perceived as simpler than Twig.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can get a more detailed comparison between both template engines in <a href="https://barryvdh.nl/laravel/twig/2015/08/22/comparing-blade-and-twig-templates-in-laravel/" target="_blank" rel="noreferrer noopener">this post</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Framework Extension</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In the case of Symfony, the way to do it is by creating <em>bundles</em>. In Laravel’s terminology, these are called <em>packages</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In both cases, they can be distributed as standalone code libraries which can be brought into future projects.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Installing a bundle in Symfony means downloading the code, editing the appropriate YAML file and indicating the bundle should be loaded at runtime by editing the file config/bundles.php.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This used to be somewhat complicated but nowadays, thanks to <a href="https://symfony.com/doc/current/setup/flex.html" target="_blank" rel="noreferrer noopener">flex</a> things got as easy as running a simple composer command such as:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>composer require symfony/apache-pack</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Which will take care of everything, leaving the bundle setup with a sensible default configuration.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the case of Laravel the process is similar, just run a command like:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>composer require laravel/breeze --dev</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>And everything you need to use the new package will be in place.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Testing</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Symfony proposes the distinction between three types of tests: Unit, Integration, and Application.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The unit tests are not really specific to either one as they both rely on phpUnit for the purposes of QA for individual classes.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the case of Integration tests, Symfony offers a base class called KernelTestCase, which extends the standard TestCase to allow the usage of the dependency injection container for testing several parts of the application at once.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Finally, the Application tests are not very different from the others in terms of code, but the idea behind them is to simulate user interactions, thus they rely on an HTTP client and a Dom Crawler.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel proposes the usage of Feature tests (on top of Unit tests off course).</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Feature tests aim to encompass large parts of the application, much like Symonfy’s Application tests.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In general, writing a Feature test for Laravel can be easier than the analogous for Symfony, since Laravel’s TestCase class offers a simpler API.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Performance</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The performance measurement is always an obscure matter as it can be composed of many variables but most benchmarks give Laravel the upper hand when it comes to application speed.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, Symfony is known for its many optimization options so, should performance really be an issue for you, there are levers to pull.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Security</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Symfony’s security system is powerful but, at the same time, a little complex to set up.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It allows for different ways of authentication as well as a very fine-grained permission model.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel uses a rather simpler approach to security but, in the most common cases, the basic features will be enough.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Internationalization</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Symfony supports several translation formats (PHP, .po .mo, XLIFF, etc…), while Laravel uses PHP and JSON only.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Deployment</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The deployment of a Symfony application implies:</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Uploading the code</li><li>Creating the cache and logs directory and assigning appropriate permissions</li><li>Creating environment files</li><li>Installing third party libraries</li><li>Building the cache</li><li>Configuring the webserver</li></ol>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><a href="https://symfony.com/cloud/" target="_blank" rel="noreferrer noopener">SymfonyCloud</a> is a hosting service specifically designed to host Symfony applications.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The deployment of a Laravel application implies:</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Configuring the webserver</li><li>Installing third party libraries</li><li>Optimizing cache configuration loading</li><li>Optimizing route loading</li><li>Optimizing view loading</li></ol>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Two services are available for helping with deployment tasks: <a href="https://forge.laravel.com/" target="_blank" rel="noreferrer noopener">Laravel Forge</a> and <a href="https://vapor.laravel.com/" target="_blank" rel="noreferrer noopener">Laravel Vapor</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Popularity</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>On the popularity front, Laravel is definitely the winner these days.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here’s a comparison on Google Trends:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4724,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://static.adevait.com/2021/07/comparison-6.png" alt="Laravel vs. Symfony popularity" class="wp-image-4724"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>And by GitHub stats: Symfony has 25.5k stars and Laravel has 65.8k stars.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another number to have in mind is regarding the community behind the frameworks: Symfony has 2394 contributors while Laravel has 2576.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Project Governance</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Release Cycle</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The Symfony project has a very strict release calendar: you can expect a new minor version every 6 months and a major version every two years.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can find more details about it <a href="https://symfony.com/doc/current/contributing/community/releases.html" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Recently Laravel moved from 6 months to a 12 months major release cycle. You can read more about this change <a href="https://blog.laravel.com/updates-to-laravels-versioning-policy" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Support for Older Versions</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Laravel offers both regular and LTS releases.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For LTS releases bug fixes are provided for 2 years and security fixes for 3 years, in opposition to 18 months of bug fixes and 2 years of security fixes for regular ones.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Symfony also has a release cycle based on regular and LTS versions.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the standard versions, bugs and security issues are fixed for 8 months and LTS versions get support for 3 years when it comes to bug fixing, and 4 for security issues.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Documentation</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>While both frameworks have extensive and detailed documentation available, Laravel’s docs are usually easier to read, understand and put to practice, while Symfony’s works better as a quick reference once you know the basics.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Which One Is Best for Your Software Development Project?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Of course, the answer depends on many factors but, in order to make a fair comparison, let’s say your team doesn’t possess any expertise in either.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel was designed with RAD in mind, so in case your deadline is tight, you probably want to go with it, especially if your developers’ seniority is closer to jr. than sr.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Symfony was designed with long-term maintainability in mind, which makes it more suited for business environments.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you’re looking at an application that will be a critical part of your organization’s success then you probably want to give Symfony a try as it will be a better base for more maintainable software over time.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another factor to keep in mind is how easy it will be to bring new developers into your team should the need arise.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In general, it’s easier to <a href="https://adevait.com/laravel" target="_blank" rel="noreferrer noopener">hire Laravel developers</a> so, unless you're willing to train new members of your team or risk delays in staffing projects, you’re going to be better off going with Laravel.&nbsp;&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Followup Resources</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Here are a few resources to complement what you’ve just learned:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://symfony.com/doc/current/best_practices.html" target="_blank" rel="noreferrer noopener">https://symfony.com/doc/current/best_practices.html</a></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://laracasts.com/series/laravel-8-from-scratch" target="_blank" rel="noreferrer noopener">https://laracasts.com/series/laravel-8-from-scratch</a></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>As you learned here, both frameworks are robust and mature tools that offer great features for professional and agile development using PHP.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>No matter which one you choose, if you follow general best practices you can always switch without too much trouble, so pick the one you feel more comfortable with today and start building apps!</p>
<!-- /wp:paragraph --> ]]></description>
<category>Laravel</category>
<author>Mauro Chojrin</author>
<pubDate>Wed, 28 Jul 2021 14:32:56 +0000</pubDate>
</item>
<item>
<title><![CDATA[ An Introduction To Queues In Node.js ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/introduction-to-queues-nodejs ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><strong><em>Within this tutorial, we’ll cover Queues in JavaScript. We'll make an introduction to what Queue is, look at different scenarios that need the implementation of a Queue, write code to demonstrate how Queues works, and explore the different parts of the code structure.&nbsp;</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There are common scenarios where an application will have a lot of workloads that should be processed asynchronously from application flows. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These asynchronous operations may contain asynchronous actions within them, too. This easily poses a common issue to handle in Node.js, but with Queueing as a technique in Node.js, we can easily and effectively handle asynchronous operations.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Prerequisites</strong></h2>
<!-- /wp:heading -->
<!-- wp:list {"ordered":true} -->
<ol><li>Basic understanding of JavaScript</li><li>Know the difference between synchronous programming and asynchronous programming</li><li>Basic understanding of Node.js</li></ol>
<!-- /wp:list -->
<!-- wp:heading -->
<h2><strong>Introduction to Queues</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Data Structure can be defined as the group of data elements that provides an efficient approach to storing and organizing data in the computer so that it can be retrieved and used efficiently. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A queue is also a linear data structure — linear data structures have data elements arranged in an orderly sequential manner and each member is connected to its previous and next sibling element. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This connectivity between the elements helps to traverse the linear data structure in a single flow and in a single run.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A queue is a linear data structure used in Node.js to appropriately and progressively organize asynchronous operations. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It is an ordered list of asynchronous operations where an asynchronous operation is inserted at the end of the queue and is removed from the front of the queue. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These operations exist in different forms, including HTTP requests, read or write file operations, streams, and more. Handling asynchronous operations within Node.js applications can be daunting to manage. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>JavaScript functions like native timers and other asynchronous operations can take an indefinite duration to complete their asynchronous operation. But with queues, we handle asynchronous operations synchronously by inserting a new element and removing an existing element on an array.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The <strong>call stack, event loop,</strong> and the<strong> callback queues</strong> help us implement Queues within a program. With the call stack, we can easily record and keep detailed track of the current function being executed and where the execution is happening from. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A function gets added to the call stack when it is about to be executed within the program. The <strong>event loop</strong> is what allows our Node application to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The operations are offloaded to the system kernel whenever possible, constantly checking the call stack for when it’s empty to take a function from the callback queue and add it to the call stack. The event loop only checks the queues when all synchronous operations have been executed. The callback queues are also queues that store callback functions — asynchronous operations, once any operation has been completed behind the scene.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Introduction To The Types Of Callback Queues</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Before we introduce the types of queues available, we’ll quickly give the order of priority given to them, then go ahead to discuss each one following their order of priority. There’s timer, close, I/O, microtask and check queues. The microtask queue is given the most priority, followed by the timer queue, the I/O queue, the check queue, and, lastly, the close queue.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Microtask Queue</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Within this type of callback queue, we’re constantly using the event loop to keep checking the queue for delayed functions before proceeding to other queues. The queue is first-in-first-out: tasks enqueued first run first. We implement this with two helpful different functions:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>process.nextTick</strong>: this is a function that would execute a different function within the queue at every next tick — the next iteration of the program. The structure of the microtask queue storing these functions makes it so easy that they can be executed at every next tick. The first queue holds this function.</li><li><strong>Promise</strong>: this represents the eventual completion (or failure) of an asynchronous operation. Promise handling is always asynchronous, as all promise actions pass through the internal “promise jobs” queue, also called “microtask queue”.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3><strong>Timer Queue</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Node.js provides us with a Timers module, containing functions that execute a program after a set period of time. This provides us with the means to have time-related operations that are asynchronous in nature.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>setTimeout(() =&gt; {
//Executed last
...
}, 0);
console.log("Executed first");</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The event loop goes on executing all synchronous operations within the program, then returns to the callback queues only when all synchronous operations have been completely executed to execute the asynchronous operations.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>I/O Queue</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Here, we’re dealing with operations that involve interacting with external environments outside our internal program. These operations are asynchronously handled by Node.js after the synchronous code has finished running. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Examples of these operations include read and write file operations, network operations, and other operations that reach outside your program to fetch data for use within your program. I/O callback queue transfers the operation to the event loop which in turn transfers to the call stack for execution.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Check Queue</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This queue allows immediate execution of the callback queue immediately after the callback functions in the IO queue have been executed. With this, we continually check the call stack if it becomes idle and scripts have been queued with<strong> setImmediate()</strong>, the event loop may continue to execute the check callback queue rather than waiting.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>setImmediate()</strong> is actually a special timer that runs in a separate phase of the event loop. It uses a libuv API that schedules callbacks to execute after the poll phase has been completed.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Close Queue</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This queue stores functions that are associated with close event operations. One example is stream, an abstract interface for working with streaming data in Node.js. For instance, the <strong>stream close event</strong>, which is emitted when the stream has been closed. It signifies that no more events will be emitted, and the <strong>HTTP close event</strong>, which is emitted when the server closes.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Implementing Queue in Javascript Using OOP</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We’ll be implementing the FIFO — First in First Out, nature of Queues as a data structure. The basic concept at the root of this implementation is adding elements at the end of the queue and removing the elements at the frontal section of the queue. Arrays are used to implement queues in JavaScript. Let’s explore it:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>Class Queue {
constructor() {
this.list = &#91;];
}
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>We just created a<strong> Queue </strong>class that contains an array, <strong>list</strong>, representing the bare minimum structure of a queue, using the constructor function to implement the array that would be used for the queue in this program. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Next, we start defining different methods that would exist on the queue data structure using conventional naming for each one.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The first function would be used to add an element at the end of a queue. We’ll use the <strong>Array.prototype.push()</strong> method to implement it.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>Class Queue {
...
enqueue = (el) =&gt; {
this.list.push(el);
}
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the above code, we’re defining a function with the name <strong>enqueue</strong> that accepts an argument. This argument is what gets added to the end of the <strong>list</strong> array. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The next function would remove elements from the front of the queue. We’ll use the <strong>Array.prototype.shift()</strong> method to implement this functionality. </p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>Class Queue {
...
dequeue = () =&gt; this.list.length !== 0 ? this.list.shift() : “No executable element”;
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>We implemented a function, <strong>dequeue</strong>, within the Queue class to always check if the array is empty. The array length isn’t equal to zero, before running the shift method to remove an element from the front of the array — queue.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The next thing we'll define is the <strong>helper functions</strong> for the Queue class we just created. These helper functions will be useful when working with the queue data structure.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This function will help to implement a functionality that would return an element with the position passed in as an argument within the queue:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>Class Queue { ...
queueIndex = (index) =&gt; this.list.length !== 0 ? this.list&#91;index] : "No executable element";}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>For the above method, we’re simply passing in the position of the element we want to retrieve, carefully ensuring the array isn’t empty.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We have constantly encountered the need to always check first if the array is empty before implementing the intended operation we want to carry out on the queue. To solve this, we’ll implement a helper function to constantly check the emptiness of the queue before implementing any operation:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>Class Queue {
...
isEmpty = () =&gt; this.list.length !== 0;
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>With this function, we can easily restructure our Queue method to use this function to check if the <strong>list </strong>array is empty or not.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This next function lies on what purpose the queue we’re implementing would serve for us within our application or program.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>Class Queue {
...
execAll = () =&gt; {
this.list.forEach(item =&gt; item())
}
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Our program assumes to be executing asynchronous operations synchronously. Meaning the elements within the queue are functions that would be executed within our program.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We’ll use the queue and all the methods defined within it to demonstrate a simple program that executes functions stored within the queue.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const queue = new Queue();
//add an element
queue.enqueue(() =&gt; "Hello world program");
queue.enqueue(() =&gt; "Demo program");
queue.enqueue((a, b) =&gt; {
switch (a) {
case a === b:
return `${a} and ${b} are absolute equals`;
case a !== b:
return `${a} and ${b} are absolute unequal`;
default:
return "No data passed in";
}
});
queue.enqueue(() =&gt; ({
first_name: "Amanda",
last_name: "Petes",
email: "adeva@adevait.com",
}));
queue.dequeue();
let executable = queue.queueIndex(2);
console.log(executable());
queue.execAll();
console.log(queue);
/**{
first_name: 'Amanda',
last_name: 'Petes',
email: 'adeva@adevait.com'
}
Demo program
No data passed in
{
first_name: 'Amanda',
last_name: 'Petes',
email: 'adeva@adevait.com'
}
Queue {
enqueue: &#91;Function: enqueue],
dequeue: &#91;Function: dequeue],
queueIndex: &#91;Function: queueIndex],
isEmpty: &#91;Function: isEmpty],
execAll: &#91;Function: execAll],
list: &#91;
&#91;Function (anonymous)],
&#91;Function (anonymous)],
&#91;Function (anonymous)]
]
} */</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the above code, we implemented a <strong>queue</strong> variable with a Queue class. We filled this queue with functions or better still operations that would be executed synchronously. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These functions are assumed to be asynchronous functions. We could achieve that with the <strong>enqueue</strong> method on the Queue class. We then removed an element from the front of the queue using the <strong>dequeue</strong> method that also exists on the Queue class. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We used the <strong>queueIndex</strong> method passing in a parameter of 2 into it. This returned an element or function at the index position of 2. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We saved this anonymous function in a variable called <strong>executable</strong>, and then executed the function. Then finally called the function that executes all the functions within the queue. The <strong>execAll </strong>method loops over all the elements within the <strong>queue.list</strong> element, calling each element within it. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We discussed what queues are, the concepts that make them relevant in our application. Arranging asynchronous code or operation in an order that executes them synchronously. The program used within this article can be advanced to contain asynchronous operation, like HTTP requests, stream events, etc. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Good luck!</p>
<!-- /wp:paragraph --> ]]></description>
<category>Node.js</category>
<author>Ikeh Akinyemi</author>
<pubDate>Fri, 23 Jul 2021 14:05:42 +0000</pubDate>
</item>
<item>
<title><![CDATA[ The Battle of the Ecommerce Giants: WordPress vs. Shopify vs. Wix vs. Magento ]]></title>
<link><![CDATA[ https://adevait.com/shopify/comparison-of-wordpress-ecommerce-website-builders ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>When it comes to choosing the right eCommerce platform, there are many factors to be considered before making a decision. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It’s perfectly clear that to have a fully functional website that will serve your future customers by prompting an excellent shopping experience, you need an expert specialized in the platforms you’ve decided to use. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Either way, a professional developer is required in any case if you want to avoid mishaps and technical problems from the beginning.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, if you choose to use WordPress for eCommerce, a very intuitive choice would be to <a href="https://adevait.com/wordpress" target="_blank" rel="noreferrer noopener">hire WordPress developer</a> because there are some <a href="https://adevait.com/wordpress/7-how-tos-every-wordpress-developer-must-know" target="_blank" rel="noreferrer noopener">WordPress how to</a>’s that only the most experienced developers know. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The same goes for Shopify – if it is your platform of choice, you will need to <a href="https://adevait.com/shopify" target="_blank" rel="noreferrer noopener">hire Shopify developer</a> to build your online store. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To further elaborate on the subject, I want to share a deeper analysis of the top most commonly used eCommerce website builders:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>WooCommerce WordPress</li><li>Shopify</li><li>Wix</li><li>Magento</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Wordpress eCommerce&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:image {"align":"center","id":4658,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/2.-Wordpress-1024x393.png" alt="Wordpress ecommerce" class="wp-image-4658"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>According to some of the most recent research, more than 39% of the world wide web is powered by WordPress. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If we look at the number of websites that only use a CMS, the numbers almost double, with WordPress having a market share of 64.1%.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These numbers prove once again that WordPress is one of the most popular website builders. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>WordPress eCommerce offers an elegant solution called WordPress WooCommerce, whose basic features come free of charge when it comes to online stores. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s take a peek at what advantages WordPress eCommerce offers and whether or not it is the solution you need.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Pros</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>WordPress is a website builder that offers many benefits and one especially useful function: the ability to be used for eCommerce purposes. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moreover, one reason why WordPress is so popular is that it can be molded according to one's needs. The fact that it is open-sourced is the single culprit for the extreme flexibility of the WordPress website builder. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The most significant part of WordPress's popularity is owed to its SEO friendliness. For a website to rank in the highest possible position, it's essential to optimize the website's overall user experience. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moreover, the factors considered essential by Google for achieving a better overall user experience are related to page loading, visual stability, and interactivity – the holy trinity of a website more commonly known as the <a href="https://adevait.com/wordpress/optimizing-the-core-web-vitals" target="_blank" rel="noreferrer noopener">Core Web Vitals</a>. With WordPress, optimizing for these factors is easy and straightforward. </p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td class="has-text-align-left" data-align="left">The original WordPress eCommerce feature is powered by the WooCommerce WordPress plugin.&nbsp;</td></tr><tr><td class="has-text-align-left" data-align="left">WordPress for eCommerce offers a bunch of extraordinary plugins that will provide some amazing features on your online store, like shipping calculations and foreign currencies.&nbsp;&nbsp;</td></tr><tr><td class="has-text-align-left" data-align="left">Easy integration with other plugins.</td></tr><tr><td class="has-text-align-left" data-align="left">Templating options, both free and premium ones.</td></tr><tr><td class="has-text-align-left" data-align="left">Simplified web development.</td></tr><tr><td class="has-text-align-left" data-align="left">Extensive online community.</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":3} -->
<h3>Cons</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Although WordPress for eCommerce has a pretty easy interface and everything is very straightforward, some users have difficulties using the WooCommerce WordPress plugin due to navigation. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Namely, navigating through the development, design, or maintenance of WordPress and WordPress WooCommerce can be challenging for those who don't have an IT background.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another reason for facing troubles is that the backend is inconsistent because of the many customization options. To be more precise, because every backend is a story of its own, people with no IT background can find it difficult to manage the backend as there aren't as many custom backend examples online. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To avoid this issue, the best recommendation is to consider hiring an expert WordPress developer. </p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td>Most plugins are paid.</td></tr><tr><td>You'll have to pair the plugins carefully, just as some of them don't play out, while some have similar features that you don't need both. For example, the two possible situations you should look for are not choosing plugins with similar features. Nevertheless, both plugins may have a different so-called main feature. It would help if you always looked for overlapping features to get the most of a plugin. The other situation is to have two plugins that give conflicting signs. Here's where the problem starts: the first plugin wants to put an order in the "Complete" field, and the second one prevents that from happening.</td></tr><tr><td>Sometimes if you have too many plugins can really slow the speed of your website or online store.</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":3} -->
<h3>WordPress Offers Hundreds Plugins, Tools, and Themes</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the main features that made both WordPress and WooCommerce WordPress popular in the first place was the extensive choice of themes, plugins, and tools available for usage. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Even though this makes WordPress very popular, I must emphasize that custom-made solutions in WordPress are the ones that answer every specific need of the client. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On the other hand, the themes and templates are always a choice when the budget is tight. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, you should stop for a moment and consider whether you are willing to sacrifice the functionality of your online store for the sake of investment money. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>WooCommerce Themes&nbsp;</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Keeping in mind that not all WordPress themes will be completely compatible with the WordPress eCommerce function and much less with WordPress WooCommerce, I made a list of the top ten <a href="https://wpforms.com/best-woocommerce-themes/" target="_blank" rel="noreferrer noopener">most popular WooCommerce WordPress</a> themes rated by users on the internet.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Astra WooCommerce Theme</li><li>Neve</li><li>OceanWP</li><li>Divi</li><li>SeedProd</li><li>Ultra</li><li>Online Shop Pro</li><li>Outfitter Pro</li><li>Storefront</li><li>Nozama</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>These are just some of the WordPress eCommerce themes that are fully compatible with WordPress WooCommerce. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, the popularity of these themes doesn't mean that they should be part of your web solution as, ultimately, everything is scaled to your business's needs. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>That is why a custom-made WordPress eCommerce site is always a better solution. The site will answer specifically to the needs of the targeted buyers while being unique, fast, and optimized for the target buyer's persona.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Also, you can improve the performance of your WordPress eCommerce themes by using plugins. Some of the WordPress plugins are created to enhance the security of your web solution. In contrast, others are made to speed everything up or offer additional features like more payment options.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can enhance your WordPress WooCommerce store with the help of some tools, usually some third-party integrations, that will help to grow your business more efficiently.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Pricing</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Although WordPress, as well as the WordPress eCommerce platform, is technically free of charge because the platform is open-sourced, there are some expenses you will need to consider before starting the development process. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Some of these costs include:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Paid premium or custom-made themes - the costs start as low as $50 and can go to some whopping sums of $10k per custom-made theme, everything depending on the client’s needs</li><li>Paid WordPress eCommerce plugins - the typical cost can vary from $0 to $129 per year</li><li>Premium support that can go up to $150 per month</li><li>Updates of premium plugins and premium themes which price range depends on the provider of the service but can go up to several hundreds of dollars&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Who is it best for?&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>WooCommerce WordPress plugin might be the most intuitive platform for your online store, especially if there are physical products in the middle. The main reason is that WooCommerce WordPress offers a ready-to-use solution that can fit in thousands of products and the best part is that you can still customize it according to your needs.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Shopify&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:image {"align":"center","id":4659,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/3.-Shopify-1024x347.png" alt="Shopify" class="wp-image-4659"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Covering nearly 11% of all eCommerce market share, Shopify is the third-largest online shop builder globally. You can use the eCommerce platform both online and offline in the building process of your online store.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Shopify offers the advantage of implementing the platform concept both online and in your traditional brick-and-mortar store. The idea is to set your store online with Shopify eCommerce and then use the Shopify POS for in-person purchases.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Shopify is not your usual store builder that will only help you launch and sell your products, but the platform can make your business reach the sky if used right.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The specially designed Shopify APIs, as well as the Shopify App Store, are here to ease out the process of store customization or help you build everything up from zero.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Pros</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>While Shopify is arguably one of the eCommerce platforms currently available for usage, the real question here is whether Shopify eCommerce is actually the best fit for you. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The Shopify platform has more advantages than disadvantages. However, every business has its own needs and understanding the key advantages and disadvantages of every store builder might be an important step in your decision-making process.</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td>Shopify offers a quick development process and easy maintenance.</td></tr><tr><td>Provides enough security for you to deal with some sensitive customer information like the billing details in the safest possible way.<br></td></tr><tr><td>You don't have to deal with PCI compliance. Instead, Shopify does it for you.&nbsp;<br></td></tr><tr><td>Their customer support team is available all around the clock.<br></td></tr><tr><td>The platform and the themes provided are mobile responsive, meaning that you'll have a great-looking store on all devices.<br></td></tr><tr><td>Shopify and all the themes it provides are entirely customizable.&nbsp;</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":3} -->
<h3>Cons&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the not-so-many disadvantages of Shopify is that some features are only available to businesses with the Shopify Plus plan like: </p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>fast checkout</li><li>customizable checkout</li><li>higher conversion rates with Shop Pay</li><li>built-in AR, video, and 3D media on product pages</li><li>managing everything from the Shopify admin page, all your stores, staff accounts, and automated workflows</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The most interesting thing about this Shopify Plus plan is its price tag of $2,000 USD per month. Another thing that can become quite a problem for the SEO of the whole store is that creating sub-categories in Shopify is not an easy task. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>No matter that Shopify has a blog section as a default feature, getting your non-commercial content looking the way you've imagined can also be quite tricky, which can be a problem for the SEO specialist.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Shopify Offers Hundreds Plugins, Tools, and Themes</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The nine eCommerce free themes provided by Shopify and each one of them having a couple of variants give you a good set of templates to choose from. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, if the free options are not appealing to you, one can always go for the premium option, i.e., a paid theme. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The good news is that you have 70 themes to choose from that are fully responsive, just as the free themes created from the Shopify dev themselves. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>While Debut, Simple, and Debutify might be the developers favorite free Shopify themes, check out some of the developers’ <a href="https://www.shopify.com/blog/shopify-themes" target="_blank" rel="noreferrer noopener">most popular premium picks</a>:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Galleria</li><li>Streamline</li><li>Context</li><li>Venue</li><li>Handy</li><li>Modular</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Furthermore, check the <a href="https://www.oberlo.com/blog/shopify-tools" target="_blank" rel="noreferrer noopener">nine best Shopify tools for 2021</a>:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Exchange</li><li>Hatchful</li><li>Oberlo</li><li>Slogan Maker</li><li>Finance Calculators</li><li>Burst</li><li>Business Name Generator</li><li>Kit</li><li>Image Resizer</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Pricing</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Shopify has four basic plans in their offer, plus the Shopify Plus plan. With that said, I can see that Shopify has a program made for every pocket and every business need.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>The Shopify Lite plan costs $9 per month</li><li>The Basic Shopify costing $29 per month, offers slightly better features than the Shopify Lite</li><li>Plain, old "Shopify" costs $79 per month</li><li>The Advanced Shopify version almost triples the price of the Shopify plan at $299 per month&nbsp;</li><li>The special Shopify Plus plan offers custom pricing, often beginning at $2000 per month</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Who is it best for?&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The Shopify eCommerce platform is built to be inclusive for everyone, from beginners that know very little about coding to experts that can do magic. Shopify makes an excellent option for two of the overall four eCommerce types: B2C (business-to-customer) and B2B (business-to-business). </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The main reason why Shopify is preferred by most businesses is that the platform makes it easy for companies to manage several eCommerce stores from only Shopify B2B websites. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Wix&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:image {"align":"center","id":4660,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/4.-Wix-1024x656.png" alt="Wix ecommerce" class="wp-image-4660"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Powering roughly 2.5 percent of all websites built with web builders, Wix lets you design and create a fully customized site or online store without a line of code. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Keeping in mind that the Wix platform itself runs in the cloud, there is nothing to be installed on the server you're hosting. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The whole process of creating your own Wix site, as well as the maintenance, can be done only via a web browser.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The web builder uses customizable templates, i.e., themes and an HTML5 drag and drop builder with everything included – apps, image galleries, vectors, fonts, etc. However, a major characteristic that lacks with the Wix platform is that it doesn’t offer SEO-optimised solutions. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Pros</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The Wix website builder has drastically improved in the last couple of years and now offers some really extraordinary benefits like:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td>Tons of pre-made themes available to choose from at any time.</td></tr><tr><td>Web development is made easy with Wix's drag and drop interface.</td></tr><tr><td>Wix App Market offers a number of apps, Wix business solutions, and tools.</td></tr><tr><td>Wix eases out the whole process of digital marketing.</td></tr><tr><td>Wix has all the tools you need to create exceptional social media content.</td></tr><tr><td>As Googles works on encouraging site owners to use SSL, Wix has started to offer the service of HTTPS free.</td></tr><tr><td>The Wix web builder platform offers competent customer support that operates all around the clock.</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":3} -->
<h3>Cons&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Here's the thing: Wix is terrible with SEO. Plain and simple. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Although you get access to their so-called SEO Wiz, this tool uses some really outdated optimization techniques. Things like page speed and crawlability are some of the most essentials things for SEO. The bad news is that Wix doesn't let its users optimize these crucial aspects of SEO. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With that said, if your SEO requirements are minimal and basic, Wix would probably be a good choice. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Other disadvantages of Wix that might annoy you are:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td>There are currently no Wix plans that include unlimited bandwidth or storage.</td></tr><tr><td>The drag and drop designed templates can kill your creativity or at least limit it.</td></tr><tr><td>The free Wix plan will force some Wix branding on your store or website.</td></tr><tr><td>Once your site or store is on Wix, it's on Wix, and you will not be able to make a transfer.</td></tr><tr><td>The fact that Wix is not as SEO friendly as promoted.</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":3} -->
<h3>Wix Offers Hundreds Plugins, Tools, and Themes</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>All the additional features that Wix offers can be found on the Wix App Market. You'll definitely find what you're looking for, keeping in mind that there are several different business app types – starting from some marketing tools and social media networking apps to analytics tools. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Some great apps one can find in the Wix App Market that will most definitely make great a difference to the eCommerce store and will ease your life in the process are:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Get some detailed insights on how people interact with your website with Visitor Analytics.</li><li>Get some extraordinary tools that will grow your business with POWR.</li><li>Take care of your customer support with the live chat tool - Tidio.</li><li>Use 123 Form Builder as one of the most effective ways to gather information.</li><li>Automate all your accounting with QuickBooks.</li><li>Boost email subscribers with the incredible tool offer by Poptin.</li><li>Level up your Social Media game with Elfsight.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Most of the Wix App Market apps are free to use and can be added to your eCommerce store in a matter of seconds. Moreover, almost all of the apps available are optimized for mobile devices, which will contribute to your site's SEO score and ultimately lead to higher rankings on Google and more organic traffic.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Pricing</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Wix has made two basic types of plans available in their offer: website plans and business &amp; eCommerce plans. Furthermore, the website plan set contains four plans, while the business &amp; eCommerce plan set contains three. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Website Plans:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>VIP (first priority support) costs $24.50 per month</li><li>Unlimited (entrepreneurs and freelancers) costs $12.50 per month</li><li>Combo (for personal use) costs $8.50 per month</li><li>Connect Domain (the most basic Wix plan) costs $4.50 per month</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Business &amp; eCommerce Plans:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Business VIP (first priority support) costs $35 per month</li><li>Business Unlimited (entrepreneurs and freelancers) costs $25 per month</li><li>Business Basic costs 8.50 bucks per month</li><li>Connect Domain (the most basic Wix plan) costs $17 per month</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Who is it best for?&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Everything points to the fact that the Wix web builder is one of the easiest ways to launch your eCommerce store. Although it might not be the first choice for many professional web developers, Wix really does a good job and is an excellent choice of a web builder for many beginners with no or little coding experience. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Magento&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:image {"align":"center","id":4661,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/5.-Magento-1024x726.png" alt="Magento ecommerce" class="wp-image-4661"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>With a market share of 0.8% of all known sites, Magento is a PHP-written eCommerce platform. The open-source eCommerce script is using the databases MySQL and Zend PHP. Magento is a fast-emerging and rich-in-features eCommerce platform giving its users the advantage to control almost everything from the site's looks to functionality and content. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Magento Versions</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There are three versions of Magento, of which the most popular is the open-sourced Community Edition.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Magento Community Edition - this version is entirely free of charge</li><li>Magento Enterprise Edition - the paid version</li><li>Magento Go - the hosted on Magento’s servers, which is also paid&nbsp;</li></ol>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Pros</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the main reasons why Magento is popular is that the eCommerce building platform can help you achieve optimal positioning in search engines. Furthermore, the platform offers other SEO-friendly features like section customization and URL modification on each page, which can alter the meta descriptions on each page and the sitemap, among others.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Magento also offers:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:table {"className":"is-style-regular"} -->
<figure class="wp-block-table is-style-regular"><table><tbody><tr><td>Optimal scalability as all of Magento's plans are designed to encourage the eCommerce store progression.</td></tr><tr><td>The platform has a simple and yet fully customizable interface.</td></tr><tr><td>Huge Marketplace where you can find all kinds of extensions.</td></tr><tr><td>Enormous online community.</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":3} -->
<h3>Cons&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The Magento system is pretty big and has a complex structure. That's why you might not be able to manage the whole process of development by yourself. Instead, you would need a team of professionals, i.e., Magento developers and Magento testers. Here emerges another disadvantage of Magento: the cost of development. If you choose the Magento Enterprise system plus the cost of eCommerce store development, the whole project would require a pretty hefty investment. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Pricing</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Depending on which version of Magento you choose, the costs can drastically change from zero dollars per year to a whopping $190,000 per year. The free version and the most popular at the moment is the Magento Community Edition or more commonly known as CE. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The other two versions of Magento are both paid. While the Magento 2 Enterprise Solutions Edition – EE and Enterprise Solutions Cloud Edition – ECE licenses usually start at $22,000 and $40,000 bucks, respectively. Both EE and ECE licensing prices depend on the expected annual gross sales revenue of the eCommerce business. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Who is it best for?&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The most popular Magento version is the Community Edition which is open-sourced, making it the perfect technology for growing businesses, as well as large businesses and stores. Although Magento is not the most affordable option for an eCommerce store out there, it does have a scalability feature that makes business owners update their store effortlessly.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Magento Offers Hundreds Plugins, Tools, and Themes</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The Magento Marketplace has everything you need to enhance and take out the most of your store. Keeping in mind that you can overspend time looking for the right Magento extension that will drive your online sales up, I have evaluated most of the extensions present on the Magento Marketplace just to filter <a href="https://neatly.io/10-magento-extensions-worth-paying-for/" target="_blank" rel="noreferrer noopener">the best ten extensions worth trying</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Processing of bulk orders and order export with Xtento.</li><li>Easy checkout with Amasty.</li><li>Do some advanced SEO-optimizing with Mirasvit.</li><li>Wyomind Simple Google Shopping.</li><li>Connect your Magento site to eBay, Amazon, and Google Play with M2Epro.</li><li>Increase your sales with Unirgy gift certificates.</li><li>Use the automatic related products feature of AheadWorks.</li><li>Take full control over your shipping options with Shipper HQ.</li><li>Automatically request reviews from your customers with Trusted Shops.</li><li>Offer an extraordinary customer loyalty program with the features of Sweet Tooth Rewards.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Generally speaking, with all the eCommerce platform solutions that exist today, business owners don't need to have previous knowledge and expertise to build an online store. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, it would be a real lifesaver if you actually had someone with the much-needed expertise to help you out with everything or, even better, relieve you of all stress and difficulties that come with creating an online store. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Surely, the pre-made themes are a real lifesaver that let you focus on the user experience and design of your eCommerce store or website. However, these pre-made themes are much slower than the custom solutions, not scalable, and, of course, used by many others which is a downside if you're looking for uniqueness. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Although there are some things you can customize with pre-made themes – like the website's colors, logo, and some other front-end stuff – there will be some limitations on what you can do with the drag and drop technique. As a result, your website may look unimpressive and one of many. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The best overall solution in which you'll be sure that every one of your expectations is flawlessly implemented is a custom-made eCommerce solution. Moreover, the team working on the project will ensure that your e-store has the optimal website speed and that all the code behind is optimized as much as possible.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Taking all of this into consideration, the most appropriate eCommerce solution for your business depends on your needs. Having listed the four most popular eCommerce solutions, with their pros and cons and important features, now it’s your turn to make a decision.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Shopify</category>
<author>Milan Savov</author>
<pubDate>Tue, 20 Jul 2021 09:06:53 +0000</pubDate>
</item>
<item>
<title><![CDATA[ An In-Depth Guide to API Authentication With Laravel Passport ]]></title>
<link><![CDATA[ https://adevait.com/laravel/api-authentication-with-laravel-passport ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Among all the features that Laravel provides out of the box, the authentication packages get the most attention from any newcomer. The fact that one can get functional authentication flow by executing a single command seems like magic.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Apart from the traditional form-based authentication approach, Laravel comes with two dedicated packages for API authentication. They are <a href="https://laravel.com/docs/8.x/passport" target="_blank" rel="noreferrer noopener">Laravel Passport</a> and <a href="https://laravel.com/docs/8.x/sanctum" target="_blank" rel="noreferrer noopener">Laravel Sanctum</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Between the two packages, Sanctum is easier to work with, targeted at SPAs, and uses a cookie-based approach. Passport on the other hand provides a full OAuth2 server implementation for your applications.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":1} -->
<h1>Table of Content</h1>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>Introduction to OAuth2</li><li>Implementing Authorization Code Grant<ul><li>Building The Authorization Server with Laravel and Passport<ul><li>Installing and Configuring Passport</li><li>Installing Laravel Breeze</li><li>Registering a New User and a New Client</li></ul></li><li>Building The Client Application with Vue.js and Bulma.css<ul><li>Designing a Simple Home Page with a Navigation Bar</li><li>Implementing The First Phase (Redirect Functionality)</li><li>Implementing The Second Phase (Callback Functionality)</li><li>Properly Persisting Access Tokens</li><li>Making Request to Protected Routes</li><li>Implementing The Logout Functionality</li><li>Implementing Automatic Token Refresh Functionality</li></ul></li><li>Fixing The Authorize Page Design</li></ul></li><li>Other Grant Types</li><li>Conclusion</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Introduction to OAuth2</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>According to Wikipedia - “<strong>OAuth</strong> is an open standard for access delegation, commonly used as a way for Internet users to grant websites or applications access to their information on other websites but without giving them the passwords.”</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Consider a situation where you want to use a third-party email application like <a href="https://www.bluemail.me/" target="_blank" rel="noreferrer noopener">Blue Mail</a> where you don’t submit your login credentials to the client application itself. Instead, the client application redirects you to the official Gmail login page and gets hold of your account once you’ve logged in. That’s OAuth at a basic level.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>OAuth was first introduced in 2007 and OAuth2 was introduced in 2012 as a revision to the previous version. Before diving into the implementation of OAuth2 using Passport, you’ll have to understand some fundamental concepts.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Authorization Server:</strong> The authorization server is the application responsible for logging the user in. In the example above, Twitter acts as the authorization server.</li><li><strong>Resource Server:</strong> In some cases, the server responsible for authorizing the request and the server responsible for providing the data can be different. Google for example authorizes requests from <strong>accounts.google.com</strong> and serves resources from other servers.</li><li><strong>Client:</strong> The client is the third-party website or application asking for authorization. In the example above, the Blue Mail application is the client.</li><li><strong>Resource Owner:</strong> The resource owner or user is the person who owns the data that the client wants to access.</li><li><strong>Grant Types:</strong> The grant types in OAuth2 are different authentication flows suitable for different situations. The most common grant type is authorization code grant.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Don’t worry if you don’t understand these clearly. Everything will become much clearer as you start implementing them. Also, this is not a definitive list. I’ve only mentioned the concepts that I think you should know right away.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Implementing Authorization Code Grant</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The authorization code grant type is probably the most common flow when it comes to OAuth and can be broken into two phases:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Phase 1:</strong> The client redirects the user to a special route on the authorization server with a certain set of parameters. In the case of Laravel Passport, this special route is <strong>/oauth/authorize</strong> and the required parameters are as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>client_id - This will be provided by the authorization server.</li><li>redirect_uri - This is a route on the client, usually <strong>/callback</strong> or <strong>/auth/callback</strong> but can be anything else.</li><li>response_type - The type of code expected by the client. In the first phase, the value should be <strong>code</strong>.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Once the client makes a successful request with all the above-mentioned parameters, the server lets the user login and redirects back to the client application with an authorization code in the query string.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Phase 2:</strong> The second phase begins with the extraction of the authorization code from the query parameter. The client then has to make a second request to another special route on the authorization server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This time the request has to be a POST request and contain another set of parameters in the request body. In the case of Laravel Passport, this second special route is <strong>/oauth/token</strong> and the required parameters are as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>client_id and redirect_uri will be the same as was in the previous request.</li><li>client_secret - This will be provided by the authorization server just like the ID.</li><li>grant_type - Indicates the type of grant which in this case is <strong>authorization_code</strong>.</li><li>code - The code received from the server as a result of the previous request.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>If the request is successful, the server will respond with an access token and a refresh token. The access token is your key to the protected data on the resource server and it expires after a certain period. The refresh token can be used for requesting a new access token once the current one expires.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>All these functionalities will become much clearer as you implement the authorization grant type by yourself. So, without further ado, let’s jump in.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Building The Authorization Server with Laravel and Passport</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I usually use the <a href="https://github.com/laravel/installer" target="_blank" rel="noreferrer noopener">laravel/installer</a> package to bootstrap my projects. As long as you know what you’re doing, you may use any other approach.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>laravel new auth-server</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Once the bootstrapping process is finished, open the project directory in your code editor of choice. If you have MySQL installed on your computer, then you can use that. But for the sake of simplicity, I’ll configure SQLite as the default database connection.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To do so, open up the .env file and replace all the database related variables with the following single line:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code># ...
DB_CONNECTION=sqlite
# ...</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now create an empty file database/database.sqlite inside your project directory.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4618,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-1.png" alt="API Authentication With Laravel Passport" class="wp-image-4618"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This is the default database name and path for SQLite in Laravel. The final step is to migrate the database by executing the php artisan migrate command.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Installing and Configuring Passport</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Like any other PHP package, Laravel Passport can be pulled in using <a href="https://getcomposer.org/" target="_blank" rel="noreferrer noopener">Composer</a>. To do so, open your terminal inside the project directory and execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>composer require laravel/passport</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Depending on your internet speed, the installation process may take a few seconds. The package comes with some migration scripts of its own. So, once it’s pulled in, the next step is to migrate your database once again.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php artisan migrate:fresh</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The migrate:fresh command, as you may already know, drops all your database tables and re-runs the migrations. Now if you open your database using a tool like <a href="https://sqlitebrowser.org/" target="_blank" rel="noreferrer noopener">DB Browser for SQLite</a>, you’ll see that five new database tables have been created with oauth_ prefix.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4619,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-2.png" alt="API Authentication With Laravel Passport" class="wp-image-4619"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The third and final step is to generate encryption keys needed to generate secure access tokens. The <a href="https://laravel.com/docs/8.x/passport#installation" target="_blank" rel="noreferrer noopener">documentation</a> at this point instructs you to execute the php artisan passport:install command.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This command creates the aforementioned encryption keys and also creates two OAuth clients which we aren’t going to use. So, instead of executing the passport:install command, execute the passport:keys command which skips the client creation step.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php artisan passport:keys</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now that the package is installed, you can start modifying your code to utilize it. First, make sure your App\Models\User class is using the Laravel\Passport\HasApiTokens trait.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4620,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-3.png" alt="API Authentication With Laravel Passport" class="wp-image-4620"/><figcaption>https://gist.github.com/fhsinchy/a47475e0c874e8e9d454eeabea5f6368</figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This trait implements the relationship between a user and the clients and tokens. Next, open up your App\Providers\AuthServiceProvider class and in the boot method, add a call to the Laravel\Passport\Passport::routes() method.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4621,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-4.png" alt="API Authentication With Laravel Passport" class="wp-image-4621"/><figcaption><a href="https://gist.github.com/fhsinchy/67bab6c051e4a63812d793d67f0769cc">https://gist.github.com/fhsinchy/67bab6c051e4a63812d793d67f0769cc</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This method registers a bunch of new routes necessary for performing Passport-related actions. To make sure that the routes have been registered successfully, execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php artisan route:list | grep oauth</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>As long as you see a bunch of routes prefixed with oauth/ you’re good to go. Finally, you’ll have to change the driver for the api guard inside the config/auth.php file.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4623,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-5.png" alt="API Authentication With Laravel Passport" class="wp-image-4623"/><figcaption><a href="https://gist.github.com/fhsinchy/9c785283090d5c028fb51422bc4bf084">https://gist.github.com/fhsinchy/9c785283090d5c028fb51422bc4bf084</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Inside the guards array, the default driver for the api guard is token in any new Laravel project. Change that to passport and now your application will use Passport’s TokenGuard when authenticating incoming API requests. Any route that uses the auth:api middleware is now protected by Laravel Passport.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Installing Laravel Breeze</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Apart from Laravel Passport, you’ll also need login and register pages for the redirected users to interact with. You can either make your custom register and login routes or use the <a href="https://laravel.com/docs/8.x/starter-kits#laravel-breeze" target="_blank" rel="noreferrer noopener">Laravel Breeze</a> starter kit.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel Breeze will provide you with beautiful-looking auth scaffolding accompanied by the necessary controllers and routes. Execute the following command to install Laravel Breeze in your project:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>composer require laravel/breeze --dev</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Next, execute the breeze:install command to publish all the resources that come with Laravel Breeze.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php artisan breeze:install</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Once the assets have been published to your project, you’ll have to compile the CSS file. To do so, execute the following commands inside the project directory:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install
npm run dev</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Finally, migrate your database by executing php artisan migrate:fresh and you’re ready to register a new user.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Registering a New User and a New Client</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To create a new user, start the project by executing php artisan serve and visit the http://localhost:8000/register route:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4622,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-6.png" alt="API Authentication With Laravel Passport" class="wp-image-4622"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Create a new account using whatever name, email address, and password combination you want. I usually use characters from books I’ve read as dummy users. Now that you have a user, all that is left is creating a new client that can act on behalf of this user.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Clients, as I’ve already said in a previous section, are websites or applications that can act on behalf of a user. For a client to be able to ask for authorization, it has to register with the authorization server. Usually, it’s done through user interfaces, but in this case, we’ll use the terminal.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To create a new client on the auth server, execute the php artisan passport:client command:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"id":4624,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://static.adevait.com/2021/07/passport-7.png" alt="API Authentication With Laravel Passport" class="wp-image-4624"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>You’ll be asked a bunch of questions. The user ID refers to the owner of this client. In my case, this is <strong>1</strong> because <strong>Athelney Jones</strong> is the only user I have in my database. The client name can be anything. This is only needed for easy identification of the client.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Finally, the callback URL is where the user will be redirected after they’ve logged in. This is usually a route on the client application. My client application will run on port 8080. That’s why I’ve used http://localhost:8080/callback as the redirect URI. Copy the client ID and client secret somewhere safe – you’ll need them soon.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The server is now ready to handle requests from clients. So in the next section, you’ll learn about creating a client application.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Building The Client Application with Vue.js and Bulma.css</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>For creating a new project, I usually use <a href="https://cli.vuejs.org/" target="_blank" rel="noreferrer noopener">Vue CLI 3</a> for bootstrapping my Vue.js projects. If you want to use something else like React, you may do so. I’ll try my best to keep the explanations simple and easily replicable.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>vue create auth-client</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the next step, manually select features and make sure to select Router from the list of features. Also, make sure that you pick version 2.x and not 3.x to be completely in line with this article. I’m using version 2 of Vue.js as many people are not yet familiar with version 3.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once the project has been bootstrapped, you’ll have to install <a href="https://github.com/axios/axios" target="_blank" rel="noreferrer noopener">axios/axios</a> for making HTTP requests to the server and <a href="https://github.com/ljharb/qs" target="_blank" rel="noreferrer noopener">ljharb/qs</a> for building/parsing query strings. You’ll also have to install the <a href="https://bulma.io/" target="_blank" rel="noreferrer noopener">Bulma</a> CSS framework. All these packages can be installed in a single command.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install axios qs bulma</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>That’s all in terms of package installation for this project. Next, you’ll have to create a .env file on the project root.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4625,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-8.png" alt="API Authentication With Laravel Passport" class="wp-image-4625"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Open up the file and add the following environment variables to it:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>VUE_APP_OAUTH_CLIENT_ID=
VUE_APP_OAUTH_CLIENT_SECRET=
VUE_APP_OAUTH_CLIENT_REDIRECT=
VUE_APP_OAUTH_AUTH_SERVER=</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Make sure you prefix all the variable names with VUE_APP_ or else they won’t be embedded in the client bundle. Populate the VUE_APP_OAUTH_CLIENT_ID, VUE_APP_OAUTH_CLIENT_SECRET, and VUE_APP_OAUTH_CLIENT_REDIRECT fields with the values according to the client you created earlier.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Don’t worry if you didn’t save them somewhere safe – you can retrieve the ID, secret, and redirect URI from the oauth_clients table in your database.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4630,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-9.png" alt="API Authentication With Laravel Passport" class="wp-image-4630"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The value of VUE_APP_OAUTH_AUTH_SERVER will be the URL of the authorization server. The authorization server runs on port 8000 by default, so you can put http://localhost:8000 here.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Designing a Simple Home Page with a Navigation Bar</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In terms of the user interface, it’ll be a very simple one. I’ll not get into components and other stuff to keep this article simple. Begin by updating the src/App.vue file as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"id":4629,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://static.adevait.com/2021/07/passport-10.png" alt="API Authentication With Laravel Passport" class="wp-image-4629"/><figcaption>https://gist.github.com/fhsinchy/bae13920b65397a5d8d1563c6e89983a</figcaption></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This is the code for a simple navigation bar with a Bulma logo and a log-in button. That isLoggedIn boolean will be replaced by a proper computed property later on. Also, the code for the redirect() and logout() methods will be written later. Next, open the src/views/Home.vue file and update its code as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4628,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-11.png" alt="API Authentication With Laravel Passport" class="wp-image-4628"/><figcaption><a href="https://gist.github.com/fhsinchy/c32da5dffa310848c5dc18af134d78eb">https://gist.github.com/fhsinchy/c32da5dffa310848c5dc18af134d78eb</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This code renders a simple message on the screen depending on whether the user is logged in or not. Just like the navigation bar, the isLoggedIn boolean will be replaced by a proper computed property later on.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The views are almost ready to use, but there is only one last thing to do. Open the src/main.js file and add the following line of code in there:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>import 'bulma/css/bulma.min.css';</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now start the application by executing npm run serve and visit http://localhost:8080 in your browser.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4627,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-12-1024x87.png" alt="API Authentication With Laravel Passport" class="wp-image-4627"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>That’s good enough for this article. You’ll have to create one more view for the application to work. Create a new file src/views/OAuthCallbackHandler.vue and put the following code in there:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4626,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-13.png" alt="API Authentication With Laravel Passport" class="wp-image-4626"/><figcaption><a href="https://gist.github.com/fhsinchy/0ee79108dcfab99c37619f1f07b1a311">https://gist.github.com/fhsinchy/0ee79108dcfab99c37619f1f07b1a311</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Finally, open the src/router/index.js file and map this view to /callback route.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4631,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-14.png" alt="API Authentication With Laravel Passport" class="wp-image-4631"/><figcaption><a href="https://gist.github.com/fhsinchy/eb059c43cbec942ce3320f4ef0ca80f6">https://gist.github.com/fhsinchy/eb059c43cbec942ce3320f4ef0ca80f6</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>You can delete unnecessary files like src/views/About.vue and src/components/HelloWorld.vue from the project. Now that the necessary views are ready, let’s begin implementing the functionalities.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Implementing The First Phase (Redirect Functionality)</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I hope that you remember that in the first phase of the authorization process, the client redirects the user to the /oauth/authorize route on the authorization server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I’ve also mentioned that the client will have to send a bunch of parameters in the query string. The required parameters are client_id, redirect_uri, and response_type.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open your src/App.vue file and update the code for the redirect() method as follows. Most of the changes are in the script section and there is a minor change in the template section.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4632,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-15.png" alt="API Authentication With Laravel Passport" class="wp-image-4632"/><figcaption><a href="https://gist.github.com/fhsinchy/7f9902cd35c79568759f2ab6b0420e07">https://gist.github.com/fhsinchy/7f9902cd35c79568759f2ab6b0420e07</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The qs.stringify() function converts objects into URL encoded query strings. So the `${process.env.VUE_APP_OAUTH_AUTH_SERVER}/oauth/authorize?${qs.stringify(queryString)}` statement will translate to http://localhost:8000/oauth/authorize?client_id=1&amp;redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fcallback&amp;response_type=code during runtime. Setting this value to window.location.href causes a redirect. This is basic JavaScript stuff, nothing fancy.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s test it out. Start the auth-server project on port 8000 by executing php artisan serve – port 8000 and start the auth-client project on port 8080 by executing npm run serve commands.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now open http://localhost:8080 on the browser and you should see something as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4634,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-16-1024x93.png" alt="API Authentication With Laravel Passport" class="wp-image-4634"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Click on the log-in button and you should be redirected to the authorization server running on port 8000 automatically by the client. Put in your email address, password combination, and hit log in.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4633,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-17.png" alt="API Authentication With Laravel Passport" class="wp-image-4633"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>You should see a pretty nasty-looking page, but don’t worry, that’s completely fine.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4635,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-18-1024x84.png" alt="API Authentication With Laravel Passport" class="wp-image-4635"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This happens because the Laravel Passport package still uses Bootstrap but the new Laravel projects don’t come with Bootstrap built-in. I’ll show you how to fix this later on, but for now, click on the authorize button and you should be presented with the following page:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4636,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-19-1024x86.png" alt="API Authentication With Laravel Passport" class="wp-image-4636"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This means that the server has authorized the request and sent the user back to the client. The callback URL was http://localhost:8080/callback and that’s what you’ll find in the browser’s address bar. You’ll also find a long string of code in the query parameter.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Implementing The Second Phase (Callback Functionality)</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The second phase, as I’ve already explained, begins by extracting the authorization code received as a query parameter.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>http:&#47;&#47;localhost:8080/callback?code=def5020090a4967a72ee90c96309c39238622e4f92b7d1801efaf3b38b49dc5f9e00bca0ad249aa5181aeac3d5fb9462104aa28c2daf41c6d7f6412eb45f3c518c183e60656974892c2f430da24699bfde42a0e6f23ad9a10fe8feb239dbf9483cee9f223ee87aa1c74378592597786429e69885a3042783d23932cbed4a06a0dc68143d2162ce5bb82bf7d2038d2069f33984d99fd7acc9bbabeb804f0c0f7ddeb722d6b16dc5aad46199e11457b639b7eb2f07876b087279dfb8cc65a2dac3bc59939812c60b5b13ec9bc42f559ad1a3006eff9c791ee5523bc5c7f3812584c577e646ede4739e0a291fd8203bc23fb4518be06b79f4bcc15c8c4be4899bfdeea7518ac1c1116ca9921c20a124421ff6094e567e4006fe9af0fc432acb6a2d74f5ac1276f0b573f90ee14d9348129aa173d262aaa5068b9c25edb7f25032f6d91cef36e73ca0f270d931b74ec2f3d29f436099ec9e9a6969ade3ce5565</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This long string labeled as code in the query parameter is the authorization code. The client application will have to make a second request to the /oauth/token route on the authorization server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open up the src/views/OAuthCallbackHandler.vue file and add a new mounted hook as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4637,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-20.png" alt="API Authentication With Laravel Passport" class="wp-image-4637"/><figcaption>https://gist.github.com/fhsinchy/c5a1da9f8e8cf92e96032bdb8fcd4379 </figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see, the view makes a POST request to the authorization server with a set of parameters in the request body. The client_id and redirect_uri are the same as the previous request.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Three new additional parameters have been added. They are the client_secret, the grant_type, and the code. The code parameter is the authorization code that came back from the authorization server.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To test out the new functionality, restart the client application and perform the entire authorization flow once again. This time, after the server redirects you back to the client, you should see the following output in the browser console:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4638,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-21-1024x115.png" alt="API Authentication With Laravel Passport" class="wp-image-4638"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The server has responded with token_type, an access_token, a refresh_token, and an expires_in variable. This access token is what you need for accessing protected information on the server.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Properly Persisting Access Tokens</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that the client has received an access token from the server, it has to be persisted. In this article, I’ll save the access token and the refresh token in local storage. Although this approach is not liked by a lot of people, it's good enough for an article like this.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open up the src/views/OAuthCallbackHandler.vue file once again and update the mounted hook as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4639,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-22.png" alt="API Authentication With Laravel Passport" class="wp-image-4639"/><figcaption><a href="https://gist.github.com/fhsinchy/984acdc04fea6cf030c3f119bc78be28">https://gist.github.com/fhsinchy/984acdc04fea6cf030c3f119bc78be28</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Instead of logging the response to the console, tokens are now saved in the local storage. The router.push() statement sends you to the home page. Restart the application and do the authorization flow from the beginning. This time, you should be redirected to the home page instead of being stuck at the “Logging you in...” message.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Also, check the browser’s local storage and you should see the access token and the refresh token there.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4640,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-23-1024x114.png" alt="API Authentication With Laravel Passport" class="wp-image-4640"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Persisting the access token in the local storage alone is not enough. The access token is a shared piece of data. That means multiple views are dependent on it. Such data should be served from a single source of truth such as Vuex. but using Vuex for a project as simple as this one seems like overkill. A simple DIY store pattern should do the trick. Create a new file src/store.js and put the following content in it:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4645,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-24.png" alt="API Authentication With Laravel Passport" class="wp-image-4645"/><figcaption><a href="https://gist.github.com/fhsinchy/db71d7cab045e0560f772fec71e674a7">https://gist.github.com/fhsinchy/db71d7cab045e0560f772fec71e674a7</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The Vue.observable() function makes a variable reactive. Assuming that you’re familiar with the concepts of getters, mutations, and actions in Vuex, this code should be pretty self-explanatory. The setToken() mutation sets a given token value in the store. The isLoggedIn() getter returns true or false depending on the existence of a token.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now go back to the src/views/OAuthCallbackHandler.vue file and update its mounted hook as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4644,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-25.png" alt="API Authentication With Laravel Passport" class="wp-image-4644"/><figcaption><a href="https://gist.github.com/fhsinchy/bf0a855a645f1e743f19596f7dd4abce">https://gist.github.com/fhsinchy/bf0a855a645f1e743f19596f7dd4abce</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The only change I’ve made is importing the mutations from the store and calling the setToken() mutation with the received access token passed as the parameter.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Also, now that you’ve implemented a store, open src/views/Home.vue and src/App.vue files and update the isLoggedIn computed property as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4643,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-26.png" alt="API Authentication With Laravel Passport" class="wp-image-4643"/><figcaption>https://gist.github.com/fhsinchy/17e035a0822eeb55b397cf2a2f98a64e </figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Manually clear the tokens from local storage and perform the entire authentication flow one more time. This time you should be redirected to the home page just like before, but the home page may look a bit different.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4642,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-27-1024x90.png" alt="API Authentication With Laravel Passport" class="wp-image-4642"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Due to the access token being present in the local storage, the isLoggedIn computed variable becomes true. I hope you remember that the “You're not logged in!” message only shows up if the computed variable is false.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, this message was supposed to be “Welcome back <strong>Athelney Jones</strong>!” but you haven’t yet requested the user information from the server. In the next section, I’ll show you how you may use the access token to request such information from the server.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Making Request to Protected Routes</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Every Laravel project comes with a protected API route registered inside the routes/api.php file. The /api/user route returns information about the currently authenticated user. In this section, you’ll request the aforementioned route and retrieve the user information.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open up the src/views/Home.vue file and update its mounted hook as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4641,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-28.png" alt="API Authentication With Laravel Passport" class="wp-image-4641"/><figcaption><a href="https://gist.github.com/fhsinchy/59f56d754cb718f088a12966537771b8">https://gist.github.com/fhsinchy/59f56d754cb718f088a12966537771b8</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Once mounted, the home view checks if a user is logged in or not. If yes, the client requests the aforementioned protected route. The client also sends the access token in the <strong>Authorization</strong> header. Appending <strong>Bearer</strong> before the access token is required – this is the token type.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once the data has been fetched, the client then fills the previously defined empty user object with the values from the server. You can look at the user data by simply adding a console.log(response.data); statement somewhere in the function.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Restart the client application and try performing the authentication flow again. This time you should see the user’s name on the home page.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4646,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-29-1024x91.png" alt="API Authentication With Laravel Passport" class="wp-image-4646"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Congratulations if you do see the name. If you don’t, you can always look at the reference repository that comes with this article. Now that you’ve completed the entire authentication flow, the only thing that’s left is implementing a log-out functionality.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Implementing The Logout Functionality</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Open up the src/store.js file and add the following snippet of code at the end of the file:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4647,"width":468,"height":267,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/07/passport-30.png" alt="API Authentication With Laravel Passport" class="wp-image-4647" width="468" height="267"/><figcaption><a href="https://gist.github.com/fhsinchy/d5189ba0c7d741543a277a35086fa589">https://gist.github.com/fhsinchy/d5189ba0c7d741543a277a35086fa589</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This is a simple logout action that wipes out the tokens from local storage and sets null as the token value in the store.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now open the src/App.vue file and update the code for the logout() method as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4648,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-31.png" alt="API Authentication With Laravel Passport" class="wp-image-4648"/><figcaption><a href="https://gist.github.com/fhsinchy/83346cbaec9e726d93b09f66eda29e4f">https://gist.github.com/fhsinchy/83346cbaec9e726d93b09f66eda29e4f</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Try hitting the log-out button now and you should be back where you were before logging in.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4649,"width":840,"height":68,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/07/passport-32-1024x83.png" alt="API Authentication With Laravel Passport" class="wp-image-4649" width="840" height="68"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Also, check the local storage and you should see the tokens disappear. With that, you’ve successfully implemented a complete authentication system with Laravel Passport. In the next sections, I’ll show you some additional functionalities that you should know about.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Implementing Automatic Token Refresh Functionality</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I’ve already mentioned in a previous section that all the access tokens and the refresh tokens have a validity period. This plays a big role in your application’s security.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>By default Laravel Passport issues tokens with a validity period of 1 year. What if someone manages to steal one of your access tokens and wreaks havoc in your account?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To prevent this from happening, you should issue tokens with much shorter validity periods. When a token expires, you can use the refresh token and the client secret to request a new access token from the server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open the App\Providers\AuthServiceProvider file in the authorization server project and update the code for the boot() method as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4650,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-33.png" alt="API Authentication With Laravel Passport" class="wp-image-4650"/><figcaption><a href="https://gist.github.com/fhsinchy/deb8604822b3582a2dd01c0a48d9ce40">https://gist.github.com/fhsinchy/deb8604822b3582a2dd01c0a48d9ce40</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>For this example, I’m configuring my access tokens to be valid for 15 days and the refresh token for 30 days. You can increase or decrease as per your needs. The refresh token can have a longer period of validity. Even if someone manages to steal the refresh token, it’ll be of no use without the client secret.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Next, you’ll have to write an Axios interceptor in your client application project. Create a new file services/http.js file in your client application project and put the following code in there:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4651,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-34.png" alt="API Authentication With Laravel Passport" class="wp-image-4651"/><figcaption>https://gist.github.com/fhsinchy/3bf4e2cc9bf0b22b275f7b0bd0da98d9 </figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>An interceptor, as the name suggests, is capable of intercepting an ongoing request or incoming response. In the code above, I’ve written a very simple response interceptor for refreshing expired tokens automatically.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The axios.interceptors.response.use() function takes two callback functions as parameters. The first one is triggered if the response is successful and the second one is triggered if the response is a failure.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In case of a failure, the failed request configuration is saved inside the originalRequest constant. The originalRequest._retry boolean indicates if the request has already been retried or not.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel Passport returns 401 status code for expired token. So if the error code is 401 and Axios hasn’t retried the request yet, the client sends a request to /oauth/token in the authorization server just like in the callback route. This time, however, the grant_type is refresh_token instead of authorization_code.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The client receives a set of new tokens from the server. It then saves the tokens to the local storage, updates the access token in the failed request, and returns the updated request for Axios to retry.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If the request fails again then the client will fire the logout action and refresh the page. The router.go() function, when called without any parameter, refreshes the current view.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To use this interceptor in your application, add following lines code in the /src/main.js file:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4652,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-35.png" alt="API Authentication With Laravel Passport" class="wp-image-4652"/><figcaption><a href="https://gist.github.com/fhsinchy/214ec4edc4785708bf706f8eeeb3bc3f">https://gist.github.com/fhsinchy/214ec4edc4785708bf706f8eeeb3bc3f</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Rest of the code remains unchanged. That’s it. Axios is now globally configured to use the interceptor. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s test out this functionality. First, go back to App\Providers\AuthServiceProvider file in the authorization server project and replace the Passport::tokensExpireIn(now()-&gt;addDays(15)); line with Passport::tokensExpireIn(now()-&gt;addSeconds(15)); line. This will reduce the validity of access tokens from 15 days to 15 seconds.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now restart the client application. Clear any previous tokens from the local storage and do the entire authentication flow. Make sure that you keep the browser console open.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once you’re logged in, wait for 15 seconds on the home page. Once the token has expired, refresh the page. If everything goes fine, you should see the user name appear on the home page just like before but, pay attention to the console window.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4653,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-36-1024x193.png" alt="API Authentication With Laravel Passport" class="wp-image-4653"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see, the request failed with a code of 401. But then the refresh functionality kicked in, refreshed the token, and resent the request to the server with the new access token.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can look at the network tab as well and you should see something as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4654,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passport-37.png" alt="API Authentication With Laravel Passport" class="wp-image-4654"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>As you can see, the fourth request from the top has received a 401. The seventh request then fetched a new token from the server. Finally, the last request has successfully fetched the user information using the new access token.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Fixing The Authorize Page Design</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In a previous section, you saw that the authorization page’s design was completely broken.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4655,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/passpsort-38-1024x84.png" alt="API Authentication With Laravel Passport" class="wp-image-4655"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>This can be fixed very easily. Open a terminal window inside your authorization server project and execute the following command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>php artisan vendor:publish --tag=passport-views</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This publishes a file resources/views/vendor/passport/authorize.blade.php on your project directory. Open that file and replace the following line:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&lt;link href="{{ asset('/css/app.css') }}" rel="stylesheet"&gt;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>With the following line:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&lt;link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous"&gt;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This is the link to the latest <a href="https://getbootstrap.com/docs/5.0/getting-started/introduction/#css" target="_blank" rel="noreferrer noopener">Bootstrap CSS</a> file. That’s it, now the design should be fixed.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Other Grant Types</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Apart from the authorization code grant type, Laravel Passport supports some other grant types. These are as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Password Grant Tokens</li><li>Implicit Grant Tokens</li><li>Client Credentials Grant Tokens</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>On <a href="https://oauth.net/2/grant-types/" target="_blank" rel="noreferrer noopener">oauth.net</a>, the password grant tokens and the implicit grant tokens are labeled as legacy types and should be avoided. The client credential grant type, on the other hand, has very small use cases.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There is another concept called proof key code exchange, or PKCE for short, that can be useful when you don’t want to use a client secret. If you’ve understood the general authorization grant type properly, you should be capable of understanding PKCE from the official <a href="https://laravel.com/docs/8.x/passport#code-grant-pkce" target="_blank" rel="noreferrer noopener">docs</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I would like to thank you for the time you've spent reading this article. I hope you've enjoyed it and have learned all the essentials of API authentication with Laravel Passport.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can find the reference code for this article on this GitHub repository - <a href="https://github.com/fhsinchy/guide-to-laravel-passport" target="_blank" rel="noreferrer noopener">https://github.com/fhsinchy/guide-to-laravel-passport</a>. Although the code is almost the same as the article, there may be some minor changes here and there.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Laravel</category>
<author>Farhan Hasin Chowdhury</author>
<pubDate>Wed, 14 Jul 2021 15:42:00 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Automated Accessibility Testing for Svelte Applications using AXE and GitHub Actions ]]></title>
<link><![CDATA[ https://adevait.com/qa/automated-accessibility-testing-for-svelte-applications ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>In this tutorial, you will learn by doing. You will identify accessibility issues in a pre-built Svelte application using both Axe-core DevTools and PA11Y. By the end of this post, you'll know how to set up a workflow to continuously check for accessibility each time a change is pushed to GitHub.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Goal</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>After going through this tutorial, readers will:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>have an understanding of what Web Accessibility is</li><li>scenarios where it can be beneficial to users</li><li>how to automate checks for accessibility using PA11Y and GitHub Actions</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Note</strong>: Although the demo web application used in this article was built using Svelte, the knowledge learned from this article can be applied when building a web application with other frameworks.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To make this tutorial easy to navigate, it has been broken down into the following sections. You can either follow through in the order they appear below or move to any section that interests you the most.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Prerequisites</li><li>Introduction</li><li>Web Accessibility Terminologies</li><li>Getting Started with Accessibility Checks<ul><li>Demo Application</li><li>Checking For Accessibility<ul><li>Using Axe-core DevTools</li><li>Using PA11Y</li></ul></li></ul></li><li>Accessibility Checks In A Continuous Integration workflow.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Prerequisites<strong>&nbsp;</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To follow along with this tutorial, it is expected that you satisfy the following requirements:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Basic knowledge of version control using GitHub.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>Basic knowledge of existing HTML tags.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>Have the NodeJS runtime installed on your local machine.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>Have either yarn or npm installed locally as a package manager.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Introduction</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Web Accessibility, often shortened as (A11Y), refers to the user-friendliness of a web application to all people. It includes people who have a permanent physical disability, such as the loss of an arm, and those whose present condition makes them temporarily disabled, such as an individual viewing a website while nursing an infant.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Several statistical reports show that a large percentage of the world’s population is living with various forms of disabilities<a href="https://adevait.com/software/accessibility-in-software-development" target="_blank" rel="noreferrer noopener">.&nbsp;Implementing the web accessibility guidelines in your application</a> could be a great way to increase your application’s user base.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Getting Started</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Before you proceed to improve the accessibility of your web application, it would be quite helpful to understand some commonly used terminologies relating to web accessibility.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Web Accessibility Terminologies</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Below is a list of three frequently used terminologies within this article:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>World Wide Web Consortium (<strong>W3C)</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The World Wide Web Consortium, often shortened to (W3C), is a body of organizations, formed to achieve the common goal of developing guidelines and standards that ensure the long-term progress and usage of the web.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Web Content Accessibility Guidelines (<strong>WCAG )</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Web Content Accessibility Guidelines, often shortened to ( WCAG ), was created by the World Wide Web Consortium to provide a common standard for web accessibility that meets the needs of individuals, organizations, and governments internationally.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Accessibility Rule sets</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Accessibility rule sets are a set of explicit regulations and ethics governing the procedure of building accessible web pages. These guidelines define how to make Web content more accessible to people with disabilities.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>An example rule is the page-has-heading-one rule. It requires that a “<strong>page must contain a level-one heading</strong>”. Meaning that the page should contain an h1 element that appears before the start of the main content. Applying this rule allows screen readers to use keyboard shortcuts to navigate the entire page structure.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Getting Started with Web Accessibility<strong> </strong>Checks</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Modern browsers today have extensions or add-ons which allow users to run an accessibility check on the target web application to find and fix accessibility issues outlined in the generated report.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>An example is the axe DevTools built by<a href="http://www.deque.com/" target="_blank" rel="noreferrer noopener"> Deque Systems</a>, which can be installed from the<a href="https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd"> Chrome Web store</a> and<a href="https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/" target="_blank" rel="noreferrer noopener"> Firefox Marketplace</a> for Chrome and Firefox desktop browsers respectively.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Testing the accessibility of a web application can also be automated and performed as a part of a Continuous Integration workflow, each time a new change to the web application is made and pushed to a version control system such as GitHub. Some automation tools built for this purpose are:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Axe-Core built Deque Systems.</li><li>PA11Y.</li><li>Automated Accessibility Testing Tool ( AATT ) built by PayPal.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>In the next section, you will clone a prebuilt Svelte Web Application that was built for the recently concluded International Women's Day Celebration. While this application looks great, it has poor support for accessibility. You will run an accessibility check using the axe DevTools from your browser and the<a href="https://pa11y.org/"> PA11Y</a> automation tool to find and fix accessibility issues.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Demo Application</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The demo application is a Single Page Application with only a homepage for displaying a list of heroines.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>To begin, clone the application using Git from your command line.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>&nbsp;git clone https://github.com/vickywane/adeva-svelte-a11y-article.git</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Move into the newly cloned project and install the application’s dependencies:</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code># change directory
cd adeva-svelte-a11y-article
# install application dependencies
npm install </code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>At this point, you have the application fully set up on your computer. Now, you can start the application using the npm dev command and view the application home page through your web browser at http://localhost:3000.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4593,"width":725,"height":420,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/07/automated-1-1024x594.png" alt="Automated Accessibility Testing for Svelte Applications using AXE and GitHub Actions
" class="wp-image-4593" width="725" height="420"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>Checking for Accessibility</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><a href="https://svelte.dev/" target="_blank" rel="noreferrer noopener">Svelte</a> is built with first-class support for accessibility. Whenever an element is missing a tag that aids accessibility, Svelte prints a warning to the console that recommends adding the missing tag to the affected element.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Have a look at the terminal where the application is running to see if there are any accessibility-related warnings:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4595,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/automated-2.png" alt="Automated Accessibility Testing for Svelte Applications using AXE and GitHub Actions
" class="wp-image-4595"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>From the terminal output above, the accessibility warning is being thrown by Svelte due to the missing<a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt" target="_blank" rel="noreferrer noopener"> Alt</a> attribute in the<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img" target="_blank" rel="noreferrer noopener"> img</a> tag in the card component.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The text value of the<a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt" target="_blank" rel="noreferrer noopener"> alt</a> attribute is displayed by the browser as a fallback in scenarios where an image cannot be loaded, either due to the image link being invalid or network error. The text is also read out by screen readers when reading a web page containing an image.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Using your preferred code editor, open the card.Svelte file in components directory and add an alt attribute to the img tag in the file as shown in the code snippet below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&lt;img alt={data.name} class="img" src={data.img_uri}/&gt;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the snippet above, an alt attribute has been added to the image element, and it would contain the name of the heroine being passed to the card a prop from the home component.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Save the card.Svelte file and have a look at the terminal running the Svelte application. You would observe that all accessibility warnings have been cleared out.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Using axe DevTools</h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>If not installed, install the axe DevTools extension from the Chrome web store to your Chrome or Firefox desktop browser.</li><li>Next, from your browser, navigate to the running Svelte application at http://localhost:3000, and launch using the browser DevTools using the ctrl + shift + I key combination for Linux and Windows operating systems and Cmd + Opt + I for macOS operating system.</li><li>From the developer tools console, click the axe DevTools tab to access the recently installed extension.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Being in the axe DevTools default page, click on the “<strong>Scan All Of My Page</strong>” option to scan the current page opened in the browser. The axe DevTools extension would scan the page and generate a report containing accessibility issues identified on the current page.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After scanning the entire home page within the demo Svelte web application in this tutorial, nine issues with different severity levels were identified as shown in the image below:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4596,"width":665,"height":362,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/07/automated-3-1024x559.png" alt="Automated Accessibility Testing for Svelte Applications using AXE and GitHub Actions
" class="wp-image-4596" width="665" height="362"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>In the image above, you can see the total amount of issues identified with respective severity levels. Also, the axe DevTools provides a breakdown of each identified issue, providing links to the accessibility rule impacted by the issue and a recommendation on how to fix it.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Using PA11Y</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>From the<a href="https://github.com/pa11y/pa11y" target="_blank" rel="noreferrer noopener"> documentation</a>, PA11Y is described as your automated accessibility testing pal that provides the functionality of running a headless accessibility check against a web application either via the command line or Node.js.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Note: </strong><em>You can also configure Pa11y to run accessibility checks using a Puppeteer</em><a href="https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-browser" target="_blank" rel="noreferrer noopener"><em> instance</em></a><em>, however by default, Pa11y works in a headless mode.&nbsp;</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Using the following steps below, you will use the Pa11y JavaScript interface to find accessibility issues within the application.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Execute the command below from a terminal to install the PA11Y package into the project.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install pa11y</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Create a new file with the name a11y.spec.js in the tests directory. You would configure the PA11y package to use its JavaScript interface for testing your application’s accessibility.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const pa11y = require("pa11y");
(async function () {
try {
const result = await pa11y(process.env.APPLICATION_URL, {
includeWarnings: true,
level: "error",
runners: &#91;
"htmlcs"
]
})
console.log(result)
} catch (e) {
throw new Error(e)
}
} )();</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Going through the code block above, you would notice the following things about how the PA11Y package is used to find accessibility issues within the demo Svelte web application:</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>The PA11Y interface is being used within a try/catch block in an Immediately Invoked Function Expression ( IIFE ). An Immediately Invoked Function Expression is being used to ensure that the checks are performed immediately the test file is executed. Also the async keyword is used with the function to enable the use of the async/await syntax for handling asynchronous operations.</li></ol>
<!-- /wp:list -->
<!-- wp:list {"ordered":true,"start":2} -->
<ol start="2"><li>The interface is given an APPLICATION_URL as the url parameter. This URL points to the default page of the running Svelte application.&nbsp;</li></ol>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Note</strong>: Storing the target application’s URL as an environment variable allows the value to be dynamically changed as the need be. For example, within the continuous integration workflow, you might want to check both the local and deployed versions of the application.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Also, the interface is given a second object parameter with the following properties:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>An includeWarnings field used to indicate that accessibility warnings should be included in the generated report.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>A level field indicating the level of error that can fail the test, and lastly a runners array specifying the runners to be used by PA11Y when checking for accessibility.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:list {"ordered":true,"start":3} -->
<ol start="3"><li>In the catch block within the code block above, an error is intentionally thrown to crash and stop the test with an exit code of 1. This is needed when running the tests within a continuous integration flow, as you might want to stop a new deployment of your web app when a new feature contains a serious accessibility error.</li></ol>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Note</strong>: When using the htmlcs runner, Pa11y would run an accessibility check using the<a href="https://github.com/pa11y/pa11y/wiki/HTML-CodeSniffer-Rules" target="_blank" rel="noreferrer noopener"> HTML Code Sniffer WCAG2AAA ruleset</a> standard. You can also change the standard in your check by specifying the standard field in the options object passed to the PA11Y interface as a configuration.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Next, add the single code line below to the script object within the package.json file to create a command that runs the accessibility tests using the a11y.spec.js file.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code> "test:a11y": "node tests/a11y.spec.js"</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>To test the new pa11y setup, execute the npm run test:a11y command from a new terminal window. After running the check, an object containing a documentTitle, pageUrl, and issues will be printed out on the console.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Note: </strong>The first terminal or command line window that the Svelte server was started on should be left running, as the tests would be run against the running Svelte application.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Execute the npm run test:a11y command from a new terminal to view ach identified accessibility issue would be added as an object to issues array within the parent object printed out to the console as shown below:&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4597,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/automated-4-1024x576.png" alt="Automated Accessibility Testing for Svelte Applications using AXE and GitHub Actions
" class="wp-image-4597"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>From the console output shown in the image above, you would observe that the issues identified are the same as the ones identified by the axe DevTools extension.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>At this point, we have set up an accessibility testing workflow. Now we can focus on fixing the following identified issues.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><a href="https://dequeuniversity.com/rules/axe/3.5/heading-order?application=axeAPI" target="_blank" rel="noreferrer noopener">heading-order</a> —&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>This error object has a message field value of Heading levels that should only increase by one and the context field of &lt;h3&gt;Ada Lovelace&lt;/h3&gt; indicating it is identified in the card.svelte component.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Going through the recommendation link attached to the error message, you would understand that this error message is triggered due to an incorrect ordering of the Heading tags on the page. An h3 tag was used in the card component to display the heroine’s name. Although this doesn't break the code syntax, it affects the page hierarchy and structure.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To fix this error, open the card.svelte component file in your preferred code editor and change the Heading ( h3 ) tag to a paragraph ( p ) with a name class to style the tag as done in the code snippet below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&lt;div style="margin: 0 4rem;"&gt;
&lt;div class="align-center"&gt;
&lt;img alt={data.name} class="img" src={data.img_uri}/&gt;
&lt;/div&gt;
&lt;br/&gt;
&lt;h3&gt; {data.name}&lt;/h3&gt;
&lt;p&gt; {data.description} &lt;/p&gt;
&lt;br/&gt;
&lt;div class={"align-center"}&gt;
&lt;button on:click={() =&gt; handleRouting(data.name)} class="custom-btn"&gt;
Read Biography
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Running the yarn test:a11y&nbsp;command again, you would observe the header-order error is gone, indicating it has been resolved.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><a href="https://www.w3.org/TR/WCAG20-TECHS/G148.html" target="_blank" rel="noreferrer noopener">WCAG2AA.Principle1.Guideline1_4.1_4_3_F24.F24.FGColour</a> —&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>This error object has a type code of 2 and a message field with the value Check that this element has an inherited background color or image to complement the corresponding inline foreground color and a context field of &lt;span style="color: #F88C00"&gt;leadership&lt;/span&gt; indicating it was identified in the text-color styling property applied to the span tag in the banner component.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Although the text-color applied might seem appealing to some users, it has an effect on how the content is displayed for visually impaired users. Individuals with visual impairments such as color blindness often configure their browsers to override certain colors that they can't see. However, with the text-color applied to the span tag, the browser cannot perform this functionality.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To fix this error you can remove the text-color style property applied to the span tag in the banner.svelte&nbsp;file. The other option is to replace the span tag with a bold ( b ) tag to lay emphasis on the <strong>leadership</strong> text as shown in the code snippet below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&lt;h1 class="banner-title"&gt;
Women in &lt;b&gt;leadership&lt;/b&gt;
&lt;br /&gt; Achieving an equal future &lt;br /&gt;
in a COVID-19 world.
&lt;/h1&gt;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Running the yarn test:a11y&nbsp;command again, you would observe that the issues array printed out on the terminal is empty, indicating that no accessibility issue was found in the scanned page. Running a check on the page using the axe-core DevTools also shows that all previously identified issues have been fixed.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4598,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/automated-5-1024x580.png" alt="Automated Accessibility Testing for Svelte Applications using AXE and GitHub Actions
" class="wp-image-4598"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>At this point, we have fixed all identified accessibility issues within the demo web application.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To ensure that your application maintains a high accessibility standard as it grows, it is advised to include the check for accessibility among the jobs executed in your continuous integration workflow.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Accessibility Checks in a Continuous Integration Workflow</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>GitHub Actions enables you to create a custom software development life-cycle workflow directly in your project contained in a GitHub repository. Through the configuration file, the action workflow can be configured to execute based on a defined event.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For the demo web application, you would want the accessibility test to be executed against all new code updates pushed to the project’s repository on GitHub either in a pull request or directly to the main branch.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The following steps outline how to do this:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Create a .github directory in the root directory, then create a ci.yml file in the new directory.</li><li>Add the content of the code snippet below into the ci.yml file you created.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>name: adeva-a11y-app Accessibility Test
on: &#91;pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Install Node JS ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- uses: actions/checkout@v1
- name: Install application dependencies
run: npm install
- name: Test local application accessibility
run: yarn dev &amp; sleep 10 &amp; yarn test:a11y
- name: Checkout generated files
uses: actions/checkout@v1</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the workflow file above, we have the following three jobs executed each time a new commit is pushed to a branch in a pull request:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Using the a<a href="https://github.com/actions/setup-node" target="_blank" rel="noreferrer noopener">ctions/checkout@v2</a> action, Node.js is installed into the running workflow build. Installing <a href="https://adevait.com/nodejs" target="_blank" rel="noreferrer noopener">Node.js</a> makes it possible to run Node.js applications within the build through the use of the npm or yarn command.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>Using the installed Node.js action, the next job’s command installs all dependencies listed in the package.json file within the project. Installing the project dependencies makes it possible to run the application for testing with the workflow instance.</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li>The third job’s command would start the web application and also run the accessibility test using the yarn test:a11y command. If a new update to the web application contains an accessibility issue, the check would fail and stop the job.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>To execute the new workflow, push a new change to your fork of the demo web application repository. After pushing the changes, a new build would be started and you can view the results from the Actions tab on GitHub as shown below:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4599,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/07/autoated-6-1024x475.png" alt="Automated Accessibility Testing for Svelte Applications using AXE and GitHub Actions
" class="wp-image-4599"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The image above shows all automated checks specified in the ci.yml workflow file passing. This is due to the previous accessibility fixes that you did in the svelte application.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With this automated workflow setup, you can be assured that your application would have some level of accessibility. However, you need to remember maintaining an accessible web application is a continuous process, hence you should often check if your web application maintains an accessible standard. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can also increase the rules used by PA11Y by adjusting the standard field within the configuration passed to the PA11Y interface or adding more runners to PA11Y.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion<strong>&nbsp;</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Within this article, you learned about Web Accessibility with a scenario where accessibility was needed by an application’s user.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Using the browser-based axe-core DevTools extension, you scanned a pre-built Svelte demo application for accessibility issues. After fixing the issues, you set up an automated accessibility testing process using PA11Y and GitHub Actions.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><br>For further reading, I would recommend going through the <a href="https://github.com/pa11y/pa11y" target="_blank" rel="noreferrer noopener">documentation</a> to familiarize yourself with various PA11Y configuration options. This article written by <a href="https://github.com/ireade" target="_blank" rel="noreferrer noopener">Ire Aderinokun</a> also explains more details about PA11Y and how you can configure it via a JSON file.</p>
<!-- /wp:paragraph --> ]]></description>
<category>QA</category>
<author>Nwani Victory</author>
<pubDate>Thu, 08 Jul 2021 10:42:07 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Node.js vs Java: Side by Side Comparison ]]></title>
<link><![CDATA[ https://adevait.com/java/nodejs-vs-java-comparison ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Choosing the suitable backend technology to use in your software project can be hectic. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Factors such as scalability, performance, and architecture are important when considering a backend technology. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this post, we will compare two major backend technologies side by side – Node js vs Java. We will also learn which backend technology between Node.js and Java is the best for which software development project.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's begin!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Points We Will Cover in This Article</h2>
<!-- /wp:heading -->
<!-- wp:list {"ordered":true} -->
<ol><li>A comparison of Java installation procedure and Node.js installation procedure</li><li>Basic models of the <a href="https://adevait.com/nodejs/most-common-nodejs-architecture-problems-and-solutions" target="_blank" rel="noreferrer noopener">Node js Architecture</a></li><li>Components of Java Architecture</li><li>Node.js and Java programming concepts</li><li>Applications of Java and Node.js</li><li>Which technology is better in terms of scalability</li><li>Performance comparison between Java and Node.js</li><li>Advantages and disadvantages of Java</li><li>Advantages and disadvantages of Node.js</li><li>Draw conclusions on which one is the best for which software development project</li></ol>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Let's start first by understanding the sole purpose of each backend technology. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Java is a programming language that is designed to be object-oriented, class-based. It was developed by James Gosling at Sun Microsystems and released on January 23, 1996. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Java is widely used in developing:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Android applications</li><li>games</li><li>Desktop GUI</li><li>web apps&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>It is amongst the top five most used programming languages worldwide, as shown by <a href="https://www.statista.com/statistics/793628/worldwide-developer-survey-most-used-languages/" target="_blank" rel="noreferrer noopener">Statista</a>. Knowing <a href="https://adevait.com/java/5-best-and-worst-practices-in-java-coding" target="_blank" rel="noreferrer noopener">how to code in Java</a> significantly increases your chances of getting hired as the demand for Java developers remains strong. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On the other hand, Node.js is a runtime environment that runs Javascript code outside of the web browser.&nbsp; </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It is extensively used in developing:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>APIs</li><li>servers</li><li>video streaming apps</li><li>chat applications</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The <a href="https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/" target="_blank" rel="noreferrer noopener">non-blocking I/O model</a> makes it efficient at carrying out its tasks which is why video streaming apps use it. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The good news is that <a href="https://adevait.com/nodejs" target="_blank" rel="noreferrer noopener">Node.js developers for hire</a> are currently in demand. Adding <a href="https://adevait.com/nodejs/top-6-nodejs-developer-skills" target="_blank" rel="noreferrer noopener">Node js developer skills</a> to your developer portfolio will increase the chance of you getting a job. Many start-up companies are opting for it, and major companies such as PayPal are shifting to Node.js. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>66.8% of developers in StackOverflow rated Node.js as the most loved tool in StackOverflow, as shown by the </em><a href="https://insights.stackoverflow.com/survey/2020" target="_blank" rel="noreferrer noopener"><em>StackOverflow developer survey 2020</em></a><em>.</em></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>A Comparison of Java vs. Node.js Installation Procedure</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Installing Java is an easy task. The only thing to do is to download the Java Development Kit (JDK) from the oracle website. The Java Development Kit also includes the Java Runtime Environment. You have to add the JDK file location to the environment variables on your laptop. You can download it <a href="https://www.oracle.com/uk/java/technologies/javase/javase-jdk8-downloads.html">here</a>. Once that is done, you would only have to install updates.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A computer with a minimum of 8GB RAM and Intel i5 processor or better specifications will be able to run Java and Node.js efficiently.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Node.js has two versions. The first one is the latest updated version, and the second one is the Long Term support version. It is advised that you should install the LTS version, which focuses on stability. If you encounter any issues, you can find solutions online compared to the current version under active development. You can download any of them <a href="https://nodejs.org/en/download/" target="_blank" rel="noreferrer noopener">here</a>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To use and install Node.js, one has to be familiar with the command line or terminal.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Basic Models of the Node.js Architecture</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Asynchronous I/O</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The asynchronous I/O&nbsp; prevents the program from blocking by allowing an application to overlap with I/O tasks.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Event-driven architecture</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The event-driven architecture is a model that promotes the production and detection of events. An event in this context is a change in state.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Event Loop</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Node.js runs on a single thread. All of the tasks are run on a single thread. The event loop is the essential part of Node.js as it executes callback functions and clears heavy functions.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Components of Java Architecture</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The Java architecture consists of the Java Runtime Environment, Java Virtual Machine, and the Java Development Kit. All of these components are necessary for the creation and execution of a Java program.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Java Development (JDK)&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is a software development environment that is used when developing Java applications.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Java Runtime Environment (JRE)</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This component is responsible for the execution of the Java code.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Java Virtual Machine (JVM)</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The JVM manages and improves program memory and also allows your computer to run Java programs.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Java vs. Node js Programming Concepts</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>If you're a beginner, it is important to start with Java first, as you will learn many fundamental programming concepts hidden in Javascript.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It takes an average programmer two years to learn Java, but a well-committed person putting more effort into practicing and putting in more hours can take 3-6 months. Below are the core concepts in Object-oriented programming:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Encapsulation</li><li>Abstraction</li><li>Polymorphism</li><li>Inheritance</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Here are some frameworks you could use to develop Java and Node.js applications. These frameworks add efficiency to the software development process:</p>
<!-- /wp:paragraph -->
<!-- wp:table -->
<figure class="wp-block-table"><table style="width: 100%;"><tbody><tr><td><strong>Examples of Java Frameworks</strong></td><td><strong>Examples of Node js frameworks</strong></td></tr><tr><td>Apache Wicket</td><td>Express.js</td></tr><tr><td>Spring</td><td>Meteor.js</td></tr><tr><td>Vaadin</td><td>Koa.js</td></tr><tr><td>Struts</td><td>socket.io</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:paragraph -->
<p>Having a good background in Javascript will make the process of learning Node.js faster. Here are Javascript concepts you should master before starting Node.js:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Modules</li><li>Prototyping</li><li>Callbacks</li><li>Asynchronous I/O</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Applications of Java and Node.js</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Java focuses on a lot of fields as compared to Node.js. Node.js has a great speed that makes it suitable for applications that have a lot of data traffic. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Large companies such as PayPal, Netflix, and Trello use Node.js. As Node.js provides great performance, Paypal no longer uses Java only but has shifted to Node.js.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Java is widely used in many categories of software applications. We can call it the jack of all trades. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Due to its ability to carry out heavy computing tasks, many scientific applications such as MATLAB use Java. Business applications also use the Java Enterprise Edition. Java is also used in the following application categories:</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Gaming Technology.</li><li>Web-based Applications.</li><li>Android apps: Most of the android applications are built using Java even though <a href="https://developer.android.com/kotlin" target="_blank" rel="noreferrer noopener">Kotlin</a> is now the official language for Android apps.</li><li>Java Desktop GUI Applications.</li></ol>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Node.js vs. Java: Which Technology Is More Scalable?&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Node.js can stand heavy load peaks, and it's lightweight which makes it great for microservices. Microservices are software approaches where software is composed of small independent services. This software approach increases flexibility.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Java has a development architecture known as the Enterprise Java Beans. This implementation makes it the best language to use in building enterprise applications. Enterprise Java Beans also uses the event-driven architecture which is used by Node.js. This architecture improves scalability as services are deployed in multiple instance scenarios.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Node js vs. Java Performance Comparison</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Node.js is built on the&nbsp; Google Chrome V8 engine, which is very fast.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What's more, the asynchronous I/O model prevents the application from blocking and allows the application to overlap with I/O operations.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Java constantly releases updates that improve performance, such as the <em>Just in time compiler</em> that was released in August 2014. This feature optimizes performance by compiling bytecode into the native machine code at runtime.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the end, your project will define which backend technology will perform better. Both of the two back-end technologies have their own niches.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Advantages and Disadvantages of Java</h2>
<!-- /wp:heading -->
<!-- wp:table -->
<figure class="wp-block-table"><table><tbody><tr><td><strong>Advantages of Java&nbsp;</strong></td><td><strong>Disadvantages of Java&nbsp;</strong></td></tr><tr><td>Cost-effective development</td><td>The Java framework uses a lot of memory</td></tr><tr><td>Increased security, as it avoids the usage of explicit pointers</td><td>It is slow when compared to natively compiled languages such as C or C++</td></tr><tr><td>Java programs are stable</td><td>Java code uses too many words which leads to long sentences that are hard to scan</td></tr><tr><td>The syntax is easy to learn and understand</td><td></td></tr><tr><td>Easy to install and maintain</td><td></td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":1} -->
<h1>Advantages and Disadvantages of Node.js</h1>
<!-- /wp:heading -->
<!-- wp:table -->
<figure class="wp-block-table"><table><tbody><tr><td><strong>Advantages of Node.js&nbsp;</strong></td><td><strong>Disadvantages of Node.js</strong></td></tr><tr><td>Node.js has very few restrictions as developers build their projects from scratch</td><td>There is a high demand for Node.js developers, but there are few well-experienced developers</td></tr><tr><td>The Non-blocking model provides more scalability as two or more requests can be processed at the same time</td><td>Node.js does not support multi-threaded programming; henceforth, it is not efficient at working out complex and heavy calculations and heavy computing</td></tr><tr><td>Node.js has grown into a huge community over the past years, making it easy to find solutions if you encounter bugs</td><td>Some modules and packages of Node.js are not well documented</td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading {"level":1} -->
<h1>Which One is Best for Your Software Development Project?&nbsp;</h1>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Node js vs Java: which one should you go for?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you're working on a software application that carries out heavy computing tasks, it's important to choose Java. Java is also suitable for enterprise applications as it has a dedicated architecture, the Enterprise Java Beans. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If the web application you're developing will have a lot of data traffic, choose Node.js as your backend technology.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the end, applying best practices and conventions will improve the performance of Java and Node.js.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Useful resources to read after reading this article</strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><a href="https://adevait.com/java/top-5-java-trends-to-watch-in-2021" target="_blank" rel="noreferrer noopener">5 Java Trends to Watch in 2021</a></li><li><a href="https://medium.datadriveninvestor.com/the-node-js-architecture-f86e2337bcd2" target="_blank" rel="noreferrer noopener">The Node.js Architecture!. Hello, everyone. Hope you are doing… | by Aditya Channe | DataDrivenInvestor</a></li></ul>
<!-- /wp:list --> ]]></description>
<category>Java</category>
<author>Boemo Wame Mmopelwa</author>
<pubDate>Thu, 01 Jul 2021 10:36:40 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Build a CRUD App With Only JSON Files Using a Node.js API ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/build-a-crud-app-with-only-json-files ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>When building a small web app or just testing out an API that needs to perform CRUD operations, using a database like (Mongo, Mysql) can be overkill. In this tutorial, we will learn how we can create CRUD operations with just JSON files.</em></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Goals</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this tutorial, we will learn how to serve and edit data from just our JSON file and how to post and save data in our JSON file. All that is needed to follow along in this tutorial is a little bit of <a href="https://adevait.com/nodejs" target="_blank" rel="noreferrer noopener">Node.js development</a> knowledge.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Overview</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this tutorial, we'll go straight to the point of creating and setting up our server and all the endpoints that we need. We'll then build all our routes and test the app, creating new accounts, and making CRUD operations.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Prerequisite</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To follow along in this tutorial, you don’t need to be a “badass” programmer – a general programming knowledge, a little bit of Javascript, and familiarity with Node.js will suffice.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Kickstarting Our Project</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>First, we'll create a project folder with the name of the project and initialize the package.json file containing information about our project and all the dependencies we're going to need.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>mkdir crud-operation-with-jsonfile
cd crud-operation-with-jsonfile
npm init -y
code .</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>There are some dependencies that are necessary for building this project, including:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Express - a Node.js framework for easily performing HTTP request and creating API’s.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install express</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Nodemon - a very helpful package that will automatically restart your server once there is any file change.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install nodemon</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Body-parser - a body parsing middleware used for parsing and processing data from the body sent to our express server.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install body-parser</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>Setting Up the Server</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that we have everything we need to start building, we have created an app.js file at the root of our project folder. This is where we'll begin building our server.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong><em>Note: </em></strong><em>Set app.js file as the project entry file in our package.json and nodemon to target the app.js file and automatically restart the server once there's a change.</em></p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code> "main": "app.js",
"scripts": {
"start": "nodemon app.js"
},
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the app.js file, we require express, body-parser and Node.js built in file system (fs) module which we will be using to serve our JSON file.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const express = require("express")
const bodyParser = require("body-parser")
const fs = require('fs');
// create our express app
const app = express()
// middleware
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }));
// route
const routes = require('./routes/Routes')
app.use('/', routes)
//start server
app.listen(3000, ()=&gt;{
console.log("listeniing at port:3000")
}) </code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>&nbsp;There are a few things going on in the app.js file above:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>We created and initialized our express application.</li><li>We set up body-parser to handle JSON data from our body to the express API we create.</li><li>We imported/required the file that we make all our routing operations in.</li><li>We started our server and listened for requests at port 3000.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>If we try running this app.js file, we will run into an error because we haven’t set up our routes. That is exactly what we'll do next.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Setting Up Our Routes</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We want the first route we created in this application to be the account route. To do this, we create a route folder at the root of the directory, and in this directory, we create a Route.js file. Back in our app.js file above, we can see that we have already imported the route. All our requests will now be prepended with / now that we have created the routes.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the Route.js file, we require express and the fs module again and define our express router. We also make sure to export the router.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>// Route.js
const express = require("express")
const router = express.Router();
const fs = require('fs');
module.exports = router;</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>&nbsp;Account Route</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Create a details folder at the root of the application and add an account.json file, which is a JSON file containing user account details. </p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
"1465": {
"username": "madfinger11",
"email": "maddy@gmail.com",
"password": "yddam5342"
},
"2646": {
"username": "yemiakin",
"email": "emiakiy@gmail.com",
"password": "iy@g65"
},
"3253": {
"username": "ikechifortune",
"email": "echifo@gmail.com",
"password": "ifo#mf23"
}
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now that our JSON data is available to us, let us begin performing the CRUD operations.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the same Route folder, we create an account.js file that serves as our account route. This is the route where we perform our CRUD operations. We define our router with the accountRoutes variable and we export the route.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>// account.js
const express = require("express")
const accountRoutes = express.Router();
const fs = require('fs');
module.exports = accountRoutes</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>For our server to know this route exists, we have to import it into the main Route.js file and use it.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>// Route.js file
const express = require("express")
const router = express.Router();
const fs = require('fs');
const accountRoutes = require('./account.js') // import account route
router.use(accountRoutes) // use account route
module.exports = router;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>While we perform CRUD operations, there'll be times when we'll need to use the file system to read and write data to our JSON file. We can make our code a bit cleaner from the start by declaring util functions at the top of the file with the main purpose of reading and writing from our file system.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For now, all we'll be doing will take place within the account route.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The two util functions we'll be reusing are:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>saveAccountData</strong> - This function will make use of the writeFileSync method to read our account data in the JSON file.</li><li><strong>getAccountData</strong> - This function will make use of the readFileSync method to get the account data from the JSON file.</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const dataPath = './Details/useraccount.json' // path to our JSON file
// util functions
const saveAccountData = (data) =&gt; {
const stringifyData = JSON.stringify(data)
fs.writeFileSync(dataPath, stringifyData)
}
const getAccountData = () =&gt; {
const jsonData = fs.readFileSync(dataPath)
return JSON.parse(jsonData)
}</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>Create an Account</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Each Account in the JSON database should have a unique id to identify each account easily. We will generate a 6 digit number using Javascript math.random, then assign the 6 digit number to a variable newAccountId and set the new Id to whatever we get from our body. Our JSON data is now updated with the latest information of the new account created. We'll use the saveAccountData util function to write the new data into our JSON file.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Lastly, we'll send a success message:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>accountRoutes.post('/account/addaccount', (req, res) =&gt; {
var existAccounts = getAccountData()
const newAccountId = Math.floor(100000 + Math.random() * 900000)
existAccounts&#91;newAccountId] = req.body
console.log(existAccounts);
saveAccountData(existAccounts);
res.send({success: true, msg: 'account added successfully'})
})</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>Reading Data</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that we have implemented being able to create a user, we want to be able to fetch all the available accounts data we have in our JSON file and display it. We'll use the get method to do this. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When we hit the /account/list endpoint, we then run the getAccountData util function, store it in a variable accounts, and send the JSON data.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>// Read - get all accounts from the json file
accountRoutes.get('/account/list', (req, res) =&gt; {
const accounts = getAccountData()
res.send(accounts)
})</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>Updating Account Data</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To update a particular piece of account information, we have to set up a dynamic route /account/:id. The /account/list is going to be whatever id of the property we choose to update in our account data. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When we hit the endpoint, we'll fetch the account data using the getAccountData util function and store it in the existAccount variable. We'll get the id from the route and use it to target the account data we want to change in our list of account data, setting it to whatever new data we send from our body. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We'll save the updated list of account data using the saveAccountData util function and send a success message saying that the id has been updated successfully.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>// Update - using Put method
accountRoutes.put('/account/:id', (req, res) =&gt; {
var existAccounts = getAccountData()
fs.readFile(dataPath, 'utf8', (err, data) =&gt; {
const accountId = req.params&#91;'id'];
existAccounts&#91;accountId] = req.body;
saveAccountData(existAccounts);
res.send(`accounts with id ${accountId} has been updated`)
}, true);
});</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>Delete an Account</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In the update method we used above, we targeted the ID we wanted to update. The same thing happens when we want to delete an account.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>First, we'll get the list of existing account data and then we'll get the id from our dynamic endpoint route /account/delete/:id using req.params. We'll target the id in the account list data we fetched and use the Javascript delete operator used in deleting properties from an object to delete that particular property with the associated id. A message regarding the account with that id being deleted will be sent.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>// delete - using delete method
accountRoutes.delete('/account/delete/:id', (req, res) =&gt; {
fs.readFile(dataPath, 'utf8', (err, data) =&gt; {
var existAccounts = getAccountData()
const userId = req.params&#91;'id'];
delete existAccounts&#91;userId];
saveAccountData(existAccounts);
res.send(`accounts with id ${userId} has been deleted`)
}, true);
})</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2><strong>Testing Our App</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We are now all done with the crud operations. The next step is to test it out using Postman, which is a platform we can use to test if our API is working. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To test our READ operation, we'll open Postman and go to http://localhost:3000/account/list endpoint and it will return all the account data:</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh4.googleusercontent.com/rybtPCOs2R4rpm2zlZOut85KMzVlETxlxSzGIFh6AmpoguOjdSa6qd4pFH_gKTBCP0S9bDO4ftfLupeQN5AQqDeN7CObKKk9IfOZcTM0yLaC73jN9AMtUdlNpNn28j2yG2mjeKyD" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>To test the POST operation, we'll set the new account info in the body of our request. When we send the request, we'll notice that a new account object has been added in our JSON file and a success message has been displayed in Postman.</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh6.googleusercontent.com/2qyNBy7smWl95ApMV0tJs0-MRjjz0jqcER0ut7IkD2j5X9Qrv9v-AcIUH2BtftMKkZDfoqhr4uWkDwzPH0rkEiF0ClE6-8GLm8FzBafSnGkLyllzVcdKyprqnALuqjPPZCcRULLL" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>To test the UPDATE operation, we'll choose the Id of the account we want to update. The next step is to add the new data object and send the request. The JSON data is now updated and we get the success message with the ID of the data that was updated.</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh3.googleusercontent.com/QzLNmK8SicqSEYvwOBEQuHqU6KbDxOMBKBRnCjKbLWiUeaL4hbnI_XhM19y6N0oo0QaPgDxIY_lL5WGsRQQCqkkZKRV8EZLtJSRCt5ynEee8Gw03dmhN-tPhfixmQ93Q2j-f-v_y" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>To test the DELETE operation, we'll set the ID of the account we want to delete. When we navigate to the endpoint /account/delete/:id and send our request, the JSON data will be updated and our account will no longer exists. We'll also get a message on Postman stating the ID of the account that was deleted.</p>
<!-- /wp:paragraph -->
<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh6.googleusercontent.com/KDCSsJzahPlpV3kasZjl8Cz-WL58gwjBBEH4GAUj7C123gVT9P7WOBHVKggNIKIsH-BtOA9zytPvJ4xPC6xnl01HVfqKl2JgBdvbsCEVmi00dJ7ApodFf4W1wbR9Tx6P1PRsv4uw" alt=""/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p><em><strong>Note</strong>: We need to know that using a JSON file as a database is not particularly a good idea for real-world applications. This tutorial teaches you how to perform a normal operation that a database like mongo is capable of if you're working on a little project and don’t want to face the hassle of setting up a native database.</em></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><em>Yay!</em> We have come to the end of this tutorial. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Hopefully, we have learned how to use a JSON file as a database and perform CRUD operations on it. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The code for this project can be found <a href="https://github.com/uma-victor1/CRUD-app-with-JSON-file">in this Github repo</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Good luck!</p>
<!-- /wp:paragraph --> ]]></description>
<category>Node.js</category>
<author>Uma Victor</author>
<pubDate>Wed, 23 Jun 2021 21:36:32 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Building Node.js APIs with Sails.js ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/building-nodejs-apis-with-sailsjs ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Building APIs and user interfaces with JavaScript can be an advantage for small and large teams. However, building easy-to-deploy and scalable Node.js APIs to power your frontend, web, or mobile application is not an easy task for any <a href="https://adevait.com/nodejs" target="_blank" rel="noreferrer noopener">Node.js developer</a>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This article will teach you how to build scalable and production-ready Node.js web API using Sails.js framework - an MVC framework for Node.js. We will be building user management endpoints for a web API service. We will create endpoints for the following features:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>User registration</li><li>User login</li><li>Forget/reset password&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Let's get started by first introducing Sails.js.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Prerequisites</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To better understand this article, knowledge of server-side development and Node.js is necessary.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>What Is Sails.js?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Sails.js or Sails is a real-time MVC framework for building scalable production-ready Node.js applications. Created by Mike McNeil in 2015, Sails.js takes inspiration from Ruby on Rails MVC framework. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It comes out of the box with features like:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Websockets - This is used for real-time communication and is suitable for real-time chat apps and more.</li><li><a href="https://waterlinejs.org/" target="_blank" rel="noreferrer noopener">Waterline</a> - An ORM for Node.js is used for a data layer of your application to make it faster and more scalable.</li><li>A CLI tool, Sails, that aids you to scaffold a new sails application, generate boilerplate to speed up development server, controller actions, and database migration.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Organizations and companies like Microsoft, Philips, Amazon, and Verizon currently use Sails to build web APIs for their various clients.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It's important to note that Sails is built on top of Express.js, a framework of Node.js.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Getting Started</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To get started with web API in Sails, you will need to install the Sails CLI tool. To do this, you will use the command below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install -g sails</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The code block above will install Sails CLI globally on your local machine. To verify that Sails is installed, you can run the code block:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sails -v</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The code block above would return a version number if the install was successful.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Creating a New Sails Application</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To create a new application with Sails, let's run the command below:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sails new {project name}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The command above takes in flags; this is used to tell Sails what boilerplate code to generate for our application. So let's run the code block below on our terminal to create a new Sails app:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sails new sails_api --no-frontend --fast</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The command above is used to create a new Sails application; the --<strong>no-frontend</strong> is used to tell Sails, not to generate <strong>assets</strong> and <strong>views</strong>. The <strong>--fast</strong> flag is used to create a Sails app and skip dependency installations.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>cd</strong> into your project directory and open the application in your text editor of choice. We can do this using the command below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>cd sails_api &amp;&amp; code .</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Your project structure should look like the image below.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4505,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/06/photo-1.png" alt="sails api" class="wp-image-4505"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The image above is boilerplate code generated by Sails for building web APIs; some of the files in the directory include:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>API</strong>: Perhaps the most used file in Sails, is where you will be creating most of your <strong>API</strong> logic; it contains <strong>controllers</strong>, <strong>models</strong>, and <strong>helpers</strong> subdirectories.</li><li><strong>controllers</strong>: This is where you add controllers for your application.</li><li><strong>helpers</strong>: This folder contains helper functions for your application. Helpers are reusable code that follows the node-machine specification.</li><li><strong>models</strong>: This contains your waterline models, which are also database schemas.</li><li><strong>config</strong>: This is where you define your app configurations; inside, it is where you define your `routes`, your database adapter for Waterline, and your policies and actions. </li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>You can learn more about Sails files and directories from Sails docs<a href="https://sailsjs.com/documentation/anatomy" target="_blank" rel="noreferrer noopener"> here.</a></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Creating Our User Endpoint</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this section, we will create our user endpoint to do this. First, navigate into your <strong>config/routes</strong> where we will be defining the request type and location. So open your <strong>config/routes.js</strong> and add the code block below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>"GET /": "home/index"</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The code block above is for a GET request assigned to the index action in the home controller that will handle this request.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Our <strong>routes.js</strong> file should look like the image below:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4507,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/06/photo-2-1.png" alt="routes.js - sails api" class="wp-image-4507"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Next, let's create an action for our <strong>index</strong> request. To do this, we will use Sails to create a <strong>controllers/home</strong> directory by running the code block below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sails generate action home/index</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The code snippet above will create a <strong>home</strong> folder in the <strong>controllers</strong> directory, and an <strong>index</strong> action should be in it. The <strong>index.js</strong> should look like the image below:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4508,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/06/photo-3.png" alt="index.js - sails api" class="wp-image-4508"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>To complete our home route, we need to add a response when a request is made to the `/` endpoint. Update your <strong>home/index.js</strong> file to look like the code block below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>module.exports = {
friendlyName: 'Index',
description: 'Index home.',
inputs: {
},
exits: {
},
fn: async function (_, exits) {
// All done.
exits.success({message: 'Sails API'});
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Sails uses the <strong>exits.success</strong> method to return a success response for a request. With this, a JSON message is sent as a response when a user visits the `/`route.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Create a New User Endpoint</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this section, we will be doing the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Setup database connection and create a new user</li><li>Store the user in the database&nbsp;</li><li>Create an error handling process in case of errors</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Setting Up the Database Connection</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We will be using<a href="https://www.mongodb.com/" target="_blank" rel="noreferrer noopener"> MongoDB.</a> You can check out<a href="https://docs.mongodb.com/manual/installation/" target="_blank" rel="noreferrer noopener"> this tutorial</a> on how to install MongoDB on your machine.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Sails comes with an official adapter for MongoDB for Waterline which we will use. You can install the adapter using the command below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install sails-mongo</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Next, we need to add the name of the adapter and our database connection to our <strong>config/datastore.j</strong>s.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You should have created your Mongo database before now, if you haven't, you can check<a href="https://www.mongodb.com/basics/create-database" target="_blank" rel="noreferrer noopener"> this link for help</a>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Update your <strong>config/datastore.js</strong> file to look like the code block below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>default: {
adapter: 'sails-mongo',
url: 'mongodb://sails_api/@localhost:3324/sails_api' //you can add your own database url here
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After you've done this, navigate to your <strong>config/models.js</strong> and uncomment the code snippet below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>id: { type: 'string', columnName: '_id' }</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you've done this, restart your development server by running <strong>sails lift</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Moving on, let's create a Schema for our user model in the section.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Creating User Model Schema</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To create a schema in a Mongo database, we will use Mongoose. For our users collection, we will need the following documents: <strong>full name, email,</strong> and <strong>password</strong>. To create a user model, let's run the command below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sails generate model user</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The above command will create a file in the <strong>models</strong> directory called <strong>User.js</strong>. Inside the file, we will add the code block below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>var mongoose = require('mongoose');
bcrypt = require('bcrypt');
SALT_WORK_FACTOR = 10;
var UserSchema = new mongoose.Schema({
fullName: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
}, {timestamps: true});
UserSchema.pre('save', function(next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) {return next();}
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, (err, salt) =&gt; {
if (err) {return next(err);}
// hash the password using our new salt
bcrypt.hash(user.password, salt, (err, hash) =&gt; {
if (err) {return next(err);}
// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code>UserSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, (err, isMatch) =&gt; {
if (err) {return cb(err);}
cb(null, isMatch);
});
};
module.exports = mongoose.model('User', UserSchema);</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Using the Mongoose schema attribute, we defined the schema for our User schema. The last function is to encrypt a user's password before we store it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>UserSchema.pre('save', function(next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) {return next();}
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, (err, salt) =&gt; {
if (err) {return next(err);}
// hash the password using our new salt
bcrypt.hash(user.password, salt, (err, hash) =&gt; {
if (err) {return next(err);}
// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>To add a <strong>createAt</strong> and <strong>updateAt</strong>, we added MmongoDB's <strong>timestamps: true</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you've done all these steps, run <strong>sails lift</strong> to start our development and see our changes. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Creating Create User Controller</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>So we have our user models setup. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The next step is to create a route and a controller also known as an <strong>actio</strong>n for creating new users. First, let's start with creating a route for it in our <strong>routes.js</strong> file below: </p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>'POST /user/register': 'user/register'</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>To create a register user action, run the command below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sails generate action user/register</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After we've done this, we need to define the data in the input field of our POST request, so add the code snippet below in your <strong>input:{}</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>inputs: {
fullName: {
type: 'string',
required: true,
},
email: {
type: 'string',
required: true,
unique: true,
isEmail: true,
},
password: {
type: 'string',
required: true,
minLength: 7,
},
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the code above, we added validation properties to the inputs. The next step is to add <strong>exits</strong> which are the results for an endpoint. To add responses to our requests, add the code block below to your <strong>exits:{}</strong> in our <strong>register.js</strong> file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>exits: {
success: {
statusCode: 201,
description: 'New user created',
},
emailAlreadyInUse: {
statusCode: 400,
description: 'Email already in use!',
},
error: {
description: 'Something went wrong, try again',
},
},</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>It's important to note that before you use the <strong>fn</strong> async function in Sails: this is for catching errors. Next, let's create a user record below. Add the code block below after your <strong>exits:{}</strong> function.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>fn: async function (inputs, exits) {
// All done.
try {
const newEmailAddress = inputs.email.toLowerCase();
let newUser = await User.create({
fullName: inputs.fullName,
email: newEmailAddress,
password: inputs.password,
});
return exits.success({
message: `${newUser}}account created successfully`,
});
} catch (error) {
if (error.code === 'E_UNIQUE') {
return exits.emailAlreadyInUse({
message: 'Oops :) an error occurred',
error: 'This email already exits',
});
}
return exits.error({
message: 'Oops :) an error occurred',
error: error.message,
});
}
},</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the code above, we added email validations and responses for our <strong>exits</strong> requests. We will build our login endpoint in the next section.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Creating Login Endpoint</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To create a login endpoint, first, we need to add a route for it in our <strong>routes.js</strong> file. Let's do that below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>POST /user/login': 'user/login</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>To create a user login endpoint, we will need to make sure that the user's email is registered. Run the command below in your terminal to create login actions:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>sails generate action user/login</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>To make sure that an email address is registered, we will need a policy called <strong>can-login.js </strong>in our <strong>policies</strong> directory. You can find out more about policies<a href="https://sailsjs.com/documentation/concepts/policies#policies" target="_blank" rel="noreferrer noopener"> here.</a></p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>module.exports = async function (req, res, proceed) {
const { email } = req.allParams();
try {
const user = await User.findOne({ email: email });
if (!user) {
res.status(404).json({
error: `${email} not found`,
});
} else {
return proceed();
}
} catch (error) {
res.status(401).json({ error: error.message });
}
};</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In the code block above, we use Node.js <strong>findOne</strong> method to look for emails provided by the user on login. If the user isn't found in our database, we will return a 404 error code and message that the email not found. We also added a <strong>catch</strong> method in case an error occurs during the process.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Writing API Policy</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Policies, according to the Sails documentation, are added tools for authorisation and access control. Finally, we will create a policy that works with our action in our API. Let's add the code block below to our <strong>policies.js</strong> file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>"user/login": 'can-login'</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now add the inputs and exits to your <strong>inputs:{}</strong> and <strong>exits:{}</strong> object:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>inputs: {
email: {
type: 'string',
required: true,
},
password: {
type: 'string',
required: true,
},
},
exits: {
success: {
description: 'Login successful',
},
notAUser: {
statusCode: 404,
description: 'User not found',
},
},</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Similar to our last policy, we will use an <strong>fn</strong> function with a <strong>try/catch</strong> method to first; find the user with the email, add an exit for when the user is not found; second, check the password of the user and an exit for when the user password is correct. Let's implement these below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code> fn: async function (inputs, exits) {
try {
const user = await User.findOne({ email: inputs.email });
if (!user) {
return exits.notAUser({
error: `${inputs.email} not found`,
});
}</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code> await sails.helpers.passwords
.checkPassword(inputs.password, user.password)
.intercept('incorrect', (error) =&gt; {
exits.passwordMismatch({ error: error.message });
});
return exits.success({
message: `${user.email} is logged in`,
data: user,
token,
});
} catch (error) {
sails.log.error(error);
if (error.isOperational) {
return exits.operationalError({
message: `Error logging in user ${inputs.email}`,
error: error.raw,
});
}
return exits.error({
message: `Error logging in user ${inputs.email}`,
error: error.message,
});
}
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>For a successful exit, we returned a message that the user is logged in, and in the case of errors again, we used the <strong>try/catch</strong> method.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this post, we have learnt how to create APIs with Node.js framework Sails.js. You can extend this application by adding authentication and deploying it to any provider of your choice. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can find the source code for this article on<a href="https://github.com/iamfortune/sails_app" target="_blank" rel="noreferrer noopener"> GitHub</a>. Below are a few more resources to help:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><a href="https://sails.js.com/" target="_blank" rel="noreferrer noopener">https://sails.js.com</a></li><li><a href="https://scotch.io/tutorials/build-a-sailsjs-app-from-api-to-authentication" target="_blank" rel="noreferrer noopener">Building a Sails.js app from api to authentication</a></li><li><a href="https://marketplace.visualstudio.com/items?itemName=dominuskelvin.sailboat" target="_blank" rel="noreferrer noopener">The Sailboat Extension</a></li><li><a href="https://codeburst.io/how-i-deployed-my-sails-%EF%B8%8F-v1-0-app-on-heroku-29696ee13328" target="_blank" rel="noreferrer noopener">Deploying Sails app on Heroku</a></li></ul>
<!-- /wp:list --> ]]></description>
<category>Node.js</category>
<author>Fortune Ikechi</author>
<pubDate>Fri, 18 Jun 2021 10:43:47 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Ethical Recruitment: A Quick Look at the Most Important Aspects ]]></title>
<link><![CDATA[ https://adevait.com/blog/workplace/ethical-recruitment ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Most recruiters have one goal: to find people that will be good, productive members of the team.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, there is another type of recruitment process called ethical recruiting that considers not only what's best for the company but also what's best for the candidate.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And it's called ethical recruitment.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Acknowledging the subject of ethical recruitment will answer why a company must treat each candidate equally and why the importance of this treatment is a benefit for everyone involved.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's explore the topic in more detail!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>What Is Ethical Recruitment?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In short, ethical recruitment is a non-legal way of doing what is right, showing respect and appreciation to each candidate applying for a job.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On another note, the way we communicate and the regard we show to candidates during the recruiting process is the most transparent picture we give to present the <a href="https://adevait.com/blog/workplace/build-strong-engineering-culture" target="_blank" rel="noreferrer noopener">company culture</a> and reputation.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Recruitment is an important process for any company because it directly affects how a company grows and succeeds in its industry or field of work. It can increase a company's reputation as it involves transparent communication with candidates, transparency in job postings, fair interviews, etc.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>How Is Ethical Recruitment Different?&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In short, recruitment is the process of identifying, attracting, screening, shortlisting, and <a href="https://adevait.com/blog/startups/interviewing-developers" target="_blank" rel="noreferrer noopener">interviewing suitable candidates</a> for a job.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is a simple definition that gives each company the basics of how a process should be run. Putting the word "ethic" next to it is a choice we make.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Caught up between working in fast-paced environments, seeking for greatness, and filling "that position," professionals often forget about the most essential part: trust.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Recruiters are responsible for building this trust and acting in the best interest of candidates.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And the best candidates crave transparency.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When we want to be ethical during the recruitment process, we must consider a candidate's personality, work ethic, interests, and goals, in addition to their qualifications.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This means that companies will not only hire people based on what they need right now but also for future needs as well.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Recruiters should also keep in mind that only by considering all candidates equally can an employer be sure that they are not losing a valuable employee.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Why Should We Care About Ethical Recruitment?&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>According to the latest <a href="https://assets.hcca-info.org/Portals/0/PDFs/Resources/library/EmployeeEngagement_LRN.pdf" target="_blank" rel="noreferrer noopener">LRN Ethics Study</a>, companies that foster an ethical corporate culture have an increased ability to attract, retain, and ensure productivity in employees.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The numbers showed that most workers (94%) say it is "critical" or "important" the company they work for is ethical.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Having recruitment as the first step in reaching out to, and communicating with candidates and employees, puts every recruiter and hiring manager as a front liner and direct contributor in presenting the company's reputation, quality, and consistency.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But being ethical doesn't mean just successful marketing and employee branding.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It also means care, respect, honesty, and transparency for all candidates because they matter. Speaking truthfully, each candidate is a person spending a good amount of their time talking with recruiters, going through interviews, and being subjected to tests, all in an effort to join a company.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4469,"width":672,"height":674,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/What-Is-Ethical-Recruitment-and-What-Are-Its-Main-Components_inside_1@2x-1020x1024.png" alt="ethical recruitment" class="wp-image-4469" width="672" height="674"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>The Ethical Recruitment Process: 4 Important Aspects</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that we looked into the concept of ethical recruitment and discussed why having an ethical culture is crucial, let's dive into the four main aspects of the ethical recruitment process. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>1. Transparency</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Transparency </strong>when presenting job openings is vital in the ethical recruitment process.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Presenting a job opening to a candidate is presenting the company itself. Each candidate is eager to know more about the place where they will work, the culture, their tasks, and company goals. Using employee reviews is an excellent way of promoting and presenting a company's values.</p>
<!-- /wp:paragraph -->
<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><strong>Candidates trust the company’s employees 3x more than the company to provide credible information on what it’s like to work there.</strong></p><cite><strong>LinkedIn Talent Solutions</strong></cite></blockquote>
<!-- /wp:quote -->
<!-- wp:heading {"level":3} -->
<h3>2. Job Descriptions</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Job descriptions</strong> are made to outline the main duties and responsibilities involved in a particular job. The candidate must be familiar with their duties and responsibilities when applying for a job.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Each candidate should be given guidance to help them understand the offer and its associated career implications. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A transparent job description is a must.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But what exactly is a transparent job description?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In short, it's an overview of the skills and future tasks required by the company, written and defined by the expectations. To be truthful and transparent, recruiters must avoid misleading the candidates.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The best job description is simply the one that lists ALL job requirements clearly and doesn't change the new hire's responsibilities once they join the company.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>3. Interviews</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Interviewing candidates </strong>is a vital part of the recruitment process.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Unfortunately, many candidates will tell you how they have been mistreated and felt unsuitable during an interview.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Therefore, the recruiter's task is not to discriminate on the basis of gender, race, origin, religion, or political views, and to always review candidates based on their merits.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What can recruiters do in order for all the candidates to receive the same treatment and same respect?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They can focus on the questions.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>During interviews, many recruiters just go with the flow and improvise. This can sometimes lead to creating an incomplete profile for a candidate. Having the question flow prepared before the interview means recruiters know exactly what they are looking for in a candidate. All candidates must have the time and opportunity to present themselves properly.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Speaking about time and opportunity, spending equal time with all candidates during interviews is another ethical piece in the recruitment process. Even if the recruiter has that gut feeling that the candidate is "not the one," the candidate must be given the same amount of time and the same opportunity as the others to present themselves.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>4. Salary Transparency</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Salary transparency</strong> is the most important ingredient while building a relationship of trust with the candidates.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>All recruiters want to make sure that their time is worth spending on numerous interviews, calls, and tests. Sharing the compensation benefits with the candidates is a great way to confirm you're on the same page. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The most common interview question recruiters ask is: "What are your salary expectations?"</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A better alternative would be informing the candidate about your budget range for the position and compensation plan for the future. </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4470,"width":678,"height":407,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/What-Is-Ethical-Recruitment-and-What-Are-Its-Main-Components_inside_2@2x-1024x615.png" alt="ethical recruitment basics" class="wp-image-4470" width="678" height="407"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2>Key Takeaways </h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To sum up the importance of this article, we need to understand the meaning of ethics in our profession. In other words, to understand the meaning of commitment, consciousness, and competency.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Commitment</strong>: <em>“The desire to do the right thing regardless of the cost.”</em></li><li><strong>Consciousness:<em> </em></strong><em>“The awareness to act consistently and apply moral convictions to daily behavior.”</em></li><li><strong>Competency: </strong><em>“The ability to collect and evaluate information, develop alternatives and foresee potential consequences and risks.”</em></li></ul>
<!-- /wp:list --> ]]></description>
<category>Workplace</category>
<author>Dragana Delova</author>
<pubDate>Thu, 10 Jun 2021 19:09:32 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI ]]></title>
<link><![CDATA[ https://adevait.com/javascript-developers/build-a-headless-trello-clone ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>In this tutorial, we’ll learn how to build a headless Trello clone, a backend-only content management system using TypeScript, set up FaunaDB using Fauna SDK, and finally deploy our application through the Vercel CLI.</em></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Goal&nbsp;</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>At the end of the tutorial, readers will comfortably be able to use Fauna SDK with FaunaDB together with headless CMS concepts to build their applications, understand the core concepts, and implement them in their projects. Within this tutorial, our focus will be on managing our headless CMS using FaunaDB, and TypeScript to build a similar and simplified version of Trello, a Trello clone.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Disclaimer</strong>: We won’t be covering the drag and drop feature found within the Trello application. This will help us focus more on setting up our Headless CMS, the database, and the CRUD functions.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Prerequisite</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The following tools will be used within our tutorial and would be necessary to successfully follow along throughout the whole project:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Basic knowledge of TypeScript.</li><li>Have NodeJS runtime installed on your local machine.</li><li>Basic knowledge of <a href="https://adevait.com/react" target="_blank" rel="noreferrer noopener">React</a> and React Hooks.</li><li>Have yarn or&nbsp;npm installed as a package manager.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2><strong>Introduction</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We’ll begin by defining some concepts and tools that would be used within the tutorial. This will give us basic knowledge or an introduction to some implementation that we will see during this tutorial.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Fauna SDK</strong> is an open-source <a href="https://adevait.com/javascript-developers" target="_blank" rel="noreferrer noopener">JavaScript</a> driver that provides the capacities and resources required to interact with Fauna. This makes communicating with Fauna Database and other Fauna services easier through the frontend.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A <strong>content management system</strong> (<strong>CMS</strong>) is a computer software used to manage the creation and modification of digital content. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>CMS typically has two major components: </p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>a content management application (CMA), a front-end user interface that allows a user, even with limited expertise, to add, modify, and remove content from a website without the intervention of a webmaster</li><li>a content delivery application (CDA) that compiles the content and updates the website</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><a href="https://fauna.com/" target="_blank" rel="noreferrer noopener"><strong>Fauna</strong></a> is a unique indexed document system that supports relations, documents, and graphs for unmatched modeling flexibility. Its query interface features complex joins and custom business logic (ala stored procedures), as well as support for real-time streaming and GraphQL.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Using headless CMS in production is beneficial for <a href="https://adevait.com/software" target="_blank" rel="noreferrer noopener">software developers</a> as it gives them the freedom to choose their choice of Frontend tool or framework to work with within the project. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Fauna provides serverless, multi-region, transactional database instances that are accessible via a cloud API. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It's easy to adopt and highly productive to use. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It gives developers the data safety and reliability they need, without the operational pain typically inflicted while working with databases. We can easily query our database using Fauna SDK, a lightweight JavaScript Driver.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Pros and Cons of Using FaunaDB and Headless CMS</strong></h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3><strong>Headless CMS Pros</strong></h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>Deploying to any hosting platform works easier with headless CMS. The applications (blogs, websites, etc) built with headless CMS have great support to work on various displays such as mobile devices, web device, and AR/VR devices.</li><li>It gives developers the flexibility to choose any frontend framework to work with since the frontend and backend are separated from each other. This makes it possible for us to pick any choice of front-end technology that suits our needs.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3><strong>Fauna Pros</strong></h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>We can query data using GraphQL or Fauna Query Language (FQL).</li><li>Access data in multiple models including relational, document, graph, and temporal.</li><li>We can easily access and manage our database through the terminal through Fauna Console as well as Fauna Shell.</li><li>Great features like built-in authentication, transparent scalability, and multi-tenancy are all made available on Fauna services.</li><li>Fauna makes it quite easy to create and use a Fauna database instance from within the development environment of the hosting platforms like Netlify or Vercel using serverless functions.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3><strong>Headless CMS Cons</strong></h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>There will be a need to set up infrastructure and manage the presentational component of our site, app, or other experience all by ourselves.</li><li>In headless CMS, the frontend development is handled with separate software and tools, this means that the developers have to be familiar with multiple codebases to be able to handle their general project.&nbsp;</li><li>Implementation of headless CMS is known to be more costly than the traditional CMS. Headless CMS applications that embody analytics are not cost-effective.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Fauna Cons</h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>Querying our database using SQL queries is not yet supported.</li><li>FaunaDB is not offered as an on-premises database.</li><li>Fauna Query Language, <strong>FQL,</strong> is schemaless.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2><strong>Setting Up The Headless CMS With FaunaDB</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Our first step is to create the database that would be used in our app in the Fauna dashboard. If you have not created an account on Fauna before now, create one<a href="https://dashboard.fauna.com/accounts/register?utm_source=DevTo&amp;utm_medium=referral&amp;utm_campaign=WritewithFauna_NodeFauna_FIkechi" target="_blank" rel="noreferrer noopener"> here</a>. Once done, we are going to be welcomed by the dashboard screen: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4460,"width":717,"height":350,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello1-1024x501.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 1" class="wp-image-4460" width="717" height="350"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We click on the NEW DATABASE button to create a database for our application. The next screen would be to provide a name for our database, which we’ll use as our content management system, then click the SAVE button. Within this tutorial, we named it <strong>Trello_clone.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4459,"width":779,"height":356,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello2-1024x469.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 2" class="wp-image-4459" width="779" height="356"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The next thing we have to do is create a collection in our database. A COLLECTION is similar to SQL tables that contain our data that can be categorized into a group of similar items. To create a new collection, we start by click on the NEW COLLECTION button:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4454,"width":726,"height":335,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello-3-1024x473.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 3" class="wp-image-4454" width="726" height="335"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Next, we choose a name for the collection we created above. This is the name we’ll use to organize our content. We’ll name our collection, <strong><em>trello_board</em></strong> then click on the SAVE button. </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4455,"width":794,"height":367,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello-4-1024x473.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 4" class="wp-image-4455" width="794" height="367"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>The next step in setting up our database for our project is to create a new index. Go to the <strong><em>Indexes</em></strong> tab on the sidabar to create an index. We’ll use this index in searching documents in our Fauna database, specifically by matching given inputs against an index’s terms field. Click on the NEW INDEX button to create an index. In this tutorial’s project, we’ll name our index <strong><em>all_tasks</em></strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4456,"width":743,"height":417,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello-5-1024x576.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 5" class="wp-image-4456" width="743" height="417"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Next, after creating our&nbsp;index, is to create our document. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This will contain the contents/data we’ll use for our headless CMS application. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The content we'll use to populate our frontend would be created here. This is the core concept of Headless CSM, taking the management of our data away from the frontend. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Click on the NEW DOCUMENT button to navigate to the screen where we’ll get started with the text editor to create our documents. </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4461,"width":777,"height":379,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello-6-1024x500.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 6" class="wp-image-4461" width="777" height="379"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>We just created a single task document that holds a&nbsp;content key with a value of what the task entails. We will use this to populate our frontend that will be built in the next part of this tutorial. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can extend the document to contain more key/value fields according to the contents you will need within your frontend application. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To keep the project concise and simple to follow through, we will create four more documents/tasks to use within our project.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4458,"width":728,"height":357,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello7-1024x503.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 7" class="wp-image-4458" width="728" height="357"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Next, we move on to create our React app, the frontend.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Get Started With the React Application</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We begin our frontend development by bootstrapping our frontend with npx create-react-app my-app – template typescript to create a React application adding TypeScript support to it. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After this process is over, we’ll proceed with installing all needed&nbsp;dependencies such as FaunaDB SDK, styled-components, and Vercel in our React application. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We can use any other UI framework to also build our frontend application.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npx create-react-app my-app --template typescript
# we install other dependencies once our project is done/created
yarn add faunadb @types/styled-components styled-components
# next we install vercel globally
yarn global add vercel</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>We will start building different components of our front-end application. We will create a Navbar component within the components folder inside the src folder, src/components/Navigation, to contain our application name, <strong>Trello clone</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>import styled from "styled-components";
const Navbar = () =&gt; {
return (
&lt;Wrapper&gt;
&lt;h1&gt;Trello Clone&lt;/h1&gt;
&lt;/Wrapper&gt;
);
};
const Wrapper = styled.div`
background-color: #02111b;
color: #fcfcfc;
&amp; &gt; h1 {
margin: 0px;
}
padding: 1rem 2rem;
`;
export default Navbar;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>After we imported the Navbar component within our App components, the above code coupled with the stylings written with the styled-components library, will turn out to look like the below UI: </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4457,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/06/trello8-1024x72.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 8" class="wp-image-4457"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Next, we’ll create the body of the website that will contain the task data from our database. We’ll build another component, called <strong><em>Column</em></strong>, which will contain our tasks created on the backend database.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>import styled from "styled-components";</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code>const Column = () =&gt; {
return (
&lt;Wrapper&gt;
&lt;h3&gt;Web Development&lt;/h3&gt;
&lt;ul&gt;
&lt;Li key={1} id={`ID-number`}&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div&gt;
&lt;button type="button"&gt;Complete?&lt;/button&gt;
&lt;/div&gt;
&lt;/Li&gt;
&lt;/ul&gt;
&lt;/Wrapper&gt;
);
};
const Li = styled.li`
border-radius: 0.3rem;
color: #fcfcfc;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #5b6c5d;
margin: 1rem 0.4rem;
&amp; &gt; p {
margin-left: 1rem;
}
&amp; &gt; div {
margin-right: 1rem;
button {
background-color: #fcfcfc;
padding-top: 0.4rem;
padding-bottom: 0.4rem;
border: none;
border-radius: 0.3rem;
cursor: pointer;
}
button:hover {
background-color: #eee;
}
}
`;
const Wrapper = styled.div`
width: 45%;
border: 2px solid #ff6b6b;
border-bottom-right-radius: 0.4rem;
border-bottom-left-radius: 0.4rem;
&amp; &gt; h3 {
background-color: #ff6b6b;
margin: 0px;
padding: 1rem 1.5rem;
}
`;
export default Column;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>We created the column that we will populate later with tasks from our Headless CMS. The above code contains styles for JSX that we created.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4463,"width":755,"height":262,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello9-1024x355.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 9" class="wp-image-4463" width="755" height="262"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2><strong>Integrate Fauna SDK Into Our React App</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Create a new file db.js at the directory path src/config/. Then import the faunadb driver and define a new client.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The secret passed as an argument to the faunadb.Client() method is going to hold the access key from .env file:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>import faunadb from 'faunadb';
const client = new faunadb.Client({
secret: process.env.REACT_APP_DB_KEY,
});
const q = faunadb.query;
export { client, q };</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Next, we create a new directory called src/api/ and inside it, we’ll create a new file called index.js. We write our CRUD function here:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>import { client, q } from "../config/database";
//Fetch All Items from Database;
const fetchAllTasks = client
.query(q.Paginate(q.Match(q.Ref("indexes/all_tasks"))))
.then((response: any) =&gt; {
const taskRef = response.data;
const fetchAllDataQuery = taskRef.map((ref: any) =&gt; {
return q.Get(ref);
});
return client.query(fetchAllDataQuery).then((data) =&gt; data);
})
.catch((error) =&gt; error.message);
//Delete task from Database
const deleteTask = (taskId: number) =&gt;
client
.query(q.Delete(q.Ref(q.Collection("trello_board"), taskId)))
.then((res) =&gt; res)
.catch((error) =&gt; error.message);
export { fetchAllTasks, deleteTask };</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The next step is to update our Column component, defining the useState and useEffect hooks that will help us query our CMS, and store the data for use on the frontend. You should also import the functions to query the CMS alongside. Our code should look like the code below:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>import styled from "styled-components";
import { fetchAllTasks, deleteTask } from "../../api/index";
import { useEffect, useState } from "react";
const Column = () =&gt; {
const &#91;tasks, setTasks] = useState&lt;any&#91;]&gt;(&#91;]);
useEffect(() =&gt; {
fetchAllTasks.then((res: any) =&gt; {
setTasks(res);
});
}, &#91;]);
const handleDeleteItem = (
event: React.MouseEvent&lt;HTMLElement&gt;,
id: number
) =&gt; {
event.preventDefault();
deleteTask(id).then((res) =&gt; res);
const newTaskArr = tasks.filter((task) =&gt; task.ref.id !== id);
setTasks(newTaskArr);
};
return (
&lt;Wrapper&gt;
&lt;h3&gt;Web Development&lt;/h3&gt;
&lt;ul&gt;
{tasks &amp;&amp;
tasks.map((task) =&gt; (
&lt;Li key={task.ref.id} id={`${task.ref.id}`}&gt;
&lt;p&gt;{task.data.task.content}&lt;/p&gt;
&lt;div&gt;
&lt;button
type="button"
onClick={(event: React.MouseEvent&lt;HTMLElement&gt;) =&gt;
handleDeleteItem(event, task.ref.id)
}
&gt;
Complete?
&lt;/button&gt;
&lt;/div&gt;
&lt;/Li&gt;
))}
&lt;/ul&gt;
&lt;/Wrapper&gt;
);
};
...</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>With the complete code structure above, our Trello clone application should look like the below UI:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4462,"width":764,"height":336,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/06/trello10-1024x451.png" alt="Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 10" class="wp-image-4462" width="764" height="336"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Within our src/api/ functions, we defined a deleteTask action to delete our items. We can still go to our CMS, that’s the database, and delete the items.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Deploying To Vercel</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Visit <a href="https://vercel.com/dashboard" target="_blank" rel="noreferrer noopener">Vercel</a> to register an account if not registered. The following steps will get our project hosted from your terminal:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>vercel login# provide the right answers to the prompts
vercel</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Below is a sample answer to the prompts:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>vercel
? Set up and deploy "~/Projects/JavaScript/React JS/trello_clone"? &#91;Y/n] y
? Which scope do you want to deploy to? ikehakinyemi
? Link to existing project? &#91;y/N] n
? What's your project's name? (trello_clone)
# click enter if you don't want to change the name of the project
? In which directory is your code located? ./
# click enter if you running this deployment from root directory
? ? Want to override the settings? &#91;y/N] n</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This will deploy your project to vercel platform.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Congrats! You made it to the end. The combination of Fauna with Headless CMS concepts allows you to build a great web application that needs data to be stored and retrieved for use on the front-end. Here’s the<a href="https://github.com/IkehAkinyemi/trello_clone" target="_blank" rel="noreferrer noopener"> GitHub link</a> to the code sample we used within our tutorial.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Good luck!</p>
<!-- /wp:paragraph --> ]]></description>
<category>Javascript</category>
<author>Ikeh Akinyemi</author>
<pubDate>Thu, 03 Jun 2021 11:15:15 +0000</pubDate>
</item>
<item>
<title><![CDATA[ How to Build a “Smarter” DevOps Roadmap — The SMART Maturity Assessment Method ]]></title>
<link><![CDATA[ https://adevait.com/devops/smart-maturity-assessment ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Last year, I was tasked with creating a roadmap to raise the DevOps Maturity of our <a href="https://adevait.com/software" target="_blank" rel="noreferrer noopener">product development teams</a>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I needed to assess how far we went in our transformation journey and decide what more to accomplish. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Therefore <strong>I needed a tool or methodology to perform the evaluation and gather feedback from everyone.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With my Industrial Engineering background, I decided to <strong>repurpose a Lean Manufacturing methodology</strong> that enabled me to complete the task. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Lean Six Sigma practitioners have been working on a toolbox to evaluate the adoption of their practices for the past three decades. Without a doubt some lessons to learn from that.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This article aims to revisit the methodology called SMART Maturity Assessment to create a similar tool that would <strong>facilitate tracking a company or team's progress through their digital transformation journey and adoption of DevOps culture</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I will walk you through the steps that lead you to evaluate your organization's maturity and create a roadmap to advance further in your journey.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>More About The SMART Maturity Assessment Methodology</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The activity I recommend follows the <strong>Improvement Kata Model</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p> SMART Maturity Assessment is just a tool you will use in your Kata's planning phase (see illustration below). As the person who leads the transformation, your mindset should be the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>First,<strong> Identify core practices in the establishment of the DevOps methodology</strong>. It should help you understand the direction or challenges that need to be taken into consideration.</li><li>Second, Use a methodology (SMART) to <strong>grasp the current situation and establish the following targets</strong> that would best benefit the company by improving its maturity in some core practices.</li></ul>
<!-- /wp:list -->
<!-- wp:image {"align":"center","id":4416,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/05/2.-The-four-steps-of-the-improvement-kata-model-1024x592.png" alt="The four steps of the improvement kata model" class="wp-image-4416"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2><strong>More About SMART Itself</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The manufacturing world was facing the challenge of creating a “satisfactory and ongoing trajectory towards an effective application of Lean principles.” </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Consequently, a novel Maturity Model and assessment tool called SMART has been developed as part of a Lean Transformation Toolkit (Lean T2) within the LeanPPD project funded by the European Commission (NMP-2008–214090).</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>SMART is an acronym</strong> for the five levels of maturity used in the methodology: <strong>S</strong>tart, <strong>M</strong>otivate, <strong>A</strong>pply, <strong>R</strong>eview, <strong>T</strong>ransform.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The levels of the SMART Maturity Model and Assessment adapted to DevOps are the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Level 1 (<strong>S</strong>tart): The organization does not implement DevOps practices in its product development.</li><li>Level 2 (<strong>M</strong>otivate): The organization is aware of the DevOps practices and is starting to implement them.</li><li>Level 3 (<strong>A</strong>pply): The organization applies DevOps practices in its product and process development and has achieved a basic implementation level.</li><li>Level 4 (<strong>R</strong>eview and Improve): The company is applying DevOps practices in its product and process development and continuously measures its results to implement improvement actions.</li><li>Level 5 (<strong>T</strong>ransform): The organization applies DevOps best practices and shares them internally and externally along the complete value chain.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The result of the evaluation can be easily represented as a<a href="https://chachart.net/radar?lang=en" target="_blank" rel="noreferrer noopener"> Radar Chart</a>. With time and effort, you should see the area covered in the diagram grow. <strong>It is a great way to keep track of your progressions over time</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4417,"width":611,"height":484,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/05/3.-SMART-Maturity-Assessment-1024x812.png" alt="SMART Maturity Assessment" class="wp-image-4417" width="611" height="484"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2><strong>When Should I Use SMART?</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I recommend using this evaluation<strong> if you have been working on your digital transformation for at least a year</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you are looking for an initial evaluation, there are better models you can find. They should offer you a set of specific questions to answer and a list of actions or directions to start with, leading to a better understanding of the DevOps culture.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The way I see this, this version is more like a retrospective exercise at the organization level that provides not only an evaluation but also specific insight proper to your business that you can work to improve. This is in the spirit of the Improvement Kata Model.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>SMART in the DevOps World</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The original SMART tool in the Lean T2 toolkit evaluates 14 lean practices under four perspectives. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Thus, the assessment integrates the results of 56 qualitative Lean approaches – the four perspectives being Time, Cost, and Quality Measurement (1), New Product Development Process (2), Tools (3), and Skilled People (4).</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Similarly, we can identify any number of practices in the DevOps world to feed our SMART tool.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://leanpub.com/measuringcontinuousdelivery" target="_blank" rel="noreferrer noopener">Steve Smith</a> introduces in his talk 15 techniques involved in the transformation of continuous delivery that I took as a reference in my first implementation of SMART. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I personally stopped at those 15 items and dropped the four perspectives mentioned in the original method. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I did not judge them as relevant in my context because it would make the evaluation process heavier. This is the list of items I have evaluated:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Version Control</li><li>Automated configuration</li><li>Automated infrastructure</li><li>Deployment pipeline</li><li>Branching Model</li><li>Continuous integration</li><li>Evolutionary architecture</li><li>database migration</li><li>test-driven development</li><li>Acceptance Tests</li><li>Smoke Test</li><li>Exploratory Testing</li><li>Non-functional test</li><li>Dynamic test data</li><li>Monitoring and alerting</li><li>Canary deployment and Feature Toggling</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>As the evaluator (i.e. DevOps evangelist), it is not your role to determine the teams' maturity level.<br></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It will be better if you aimed to <strong>increase adoption and ease the change management process</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Still, you need to lead the improvement Kata, meaning that you are an observer that will organize interviews and workshops to grasp the current situation. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You are accompanying everyone like a gentle wind pushing the boat in the right direction. Proceeding that way will better include your colleges in the journey.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Implementing SMART Maturity Assessment</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Step 1: Team Lead and Product Owner Interviews</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In the first phase, gathering initial feedback is essential. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It is the catalyst for improving people’s mindsets and empowering them with new techniques. <strong>Tech lead</strong> most likely already have an opinion on the improvements they would like to implement.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p> On the other hand, <strong>Product Owners</strong> need to be aware of product development’s best practices. They also need to understand why they should dedicate some development time to improve some technical aspects. They need to understand the business value of the proposed practices in the product development cycle.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It is your chance to bring the business, the development, and the operation on the same page.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>During the interview:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Explain what SMART Maturity Assessment is</strong>.</li><li><strong>Review each of the 15 items and try to place them in each of the maturity levels (1 to 5</strong>).</li><li><strong>Each time, open the conversation to gain as much insight as possible</strong>. Remember the planning step of the Improvement Kata model.</li><li><strong>Understand the direction or change</strong> .  What is Canary deployment? What is the value of it?</li><li><strong>Grasp the current situation </strong>. What do we do concerning Version control? What can we improve? Is there a blocker that stops us from implementing improvements? Do we need to do more research on the topic to understand the best practices on the market?</li><li><strong>Establish the following target condition</strong> . Do we have an interest in getting better on that item? Do we have a use case for it? Do we have a project that would immediately benefit from it?</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><em>Don’t be afraid of admitting that you are at a maturity level 1 (Start).</em></p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Step 2: Team Retrospective</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This exercise will help us gather feedback from everyone and have a more accurate evaluation of the maturity. Your Tech lead opinions may not reflect the team buy-in for some practices, or the knowledge among teams or across teams may be heterogeneous. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Therefore, the more people you involve in the process, the more accurate your evaluation will be.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>1) <strong>I organized this exercise as a retrospective exercise</strong>. An excellent way to introduce the activity would be to highjack one of the retrospectives for each team. So get your post-it ready! (or a miro board during Covid time).</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>You do not need to introduce SMART yet. The exercise below approaches</em> the assessment from a different angle to gather the maximum number of insights.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>2) <strong>Create 3 cards or post-its for each of the 15 items</strong> – so 45 cards in total. We want to duplicate items so several team members can express themselves on the same topic.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>Based on the previous step, do not hesitate to remove an item you identified as level 1. Those items may create confusion among your participants, and they will not provide meaningful insight.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>3<strong>) Distribute your deck of the card so that everyone has 3 to 4 cards</strong>. Giving more cards would result in a prolonged exercise. You can count on the fact that we duplicated each card and that you will repeat the exercise with several teams to converge to a clear picture of the situation.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>4) <strong>Ask the participant to write comments on a post-it for each item they have been given </strong>— following these rules:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>You need to write at least 3 post-its per card.</li><li>You must write positive feedback on a green post-it.</li><li>You must write negative feedback on a red post-it.</li><li>If you know very little about the card, you can write a single post-it that says you don’t know anything about it or we did not implement anything yet.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><em>Set a 10 min timer for people to create the post-its</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The participant’s post-its should look like this:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4418,"width":458,"height":758,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/05/4.-Participant-post-its-619x1024.png" alt="smart maturity assessment post-its" class="wp-image-4418" width="458" height="758"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>5)<strong> Draw the following figure on the board</strong>. We are going to try to evaluate our 15 items on a scale from unrefined as charcoal to shiny as diamond.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4419,"width":586,"height":462,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/05/5.-Empty-Retrospective-Board-1024x808.png" alt="Empty Retrospective Board" class="wp-image-4419" width="586" height="462"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>6) In turn<strong>, ask the participants to stick cards and post-its on the board</strong>. Ask them:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>Do we shine like diamond or are we unrefined like coal?</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As a general rule:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>If you mainly wrote <strong>red</strong> post-its (negative feedback), you should be closer to the pile of charcoal.</li><li>If you mainly wrote <strong>green</strong> post-its (positive feedback), you should be closer to the diamond.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>7) <strong>Discuss the items with the group when laying down the post-its</strong>. This is the time to have group conversations and take some notes.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4420,"width":620,"height":488,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/05/6.-Final-Retrospective-board-for-SMART-1024x808.png" alt="Final Retrospective board for SMART maturity assessment" class="wp-image-4420" width="620" height="488"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>8) You can now<strong> explain what is SMART Maturity Assessment and tell participants what you will do with all their insight </strong>(keep reading, so I tell you what to do with all the post-it collected). A good conclusion would be to create the Radar Chart for this activity:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Charcoal count as level 1</li><li>Diamon count as level 3</li><li>Everything else counts as level 2</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Step 3: Compiling the Results</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Create a table in your favorite tool (Confluence, Excel, or others). </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Compile the maturity score for the interview and retrospective exercise</strong>. Create an average score across your organization; this is your maturity level from which you will <strong>create the final Radar Chart</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Report and compile all the insight collected</strong> alongside the SMART Maturity Assessment score. They will be helpful to develop your road map.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>Why do we score items between 1 and 3 in </em>Step 2: team retrospective <em>exercise and not between 1 and 5?</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Since it is the first time you do the exercise, we can assume that you did not review any process. Remember that to reach level 4, you need to measure results to implement improvement actions continuously. It may be the case, and if some member mentioned in their post-it that you have KPI ready for that item, then go ahead of your earn your level 4 maturity level for that item (Congratulations).</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Step 4: Deciding on a Road Map</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Creating the road map base on SMART is as simple as asking: How do I want my Radar Chart to look like in a year from now?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The levers to achieve and sustain changes are based on the maturity level:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Moving from <strong>S</strong>tart to <strong>M</strong>otivated involves making a presentation, creating a workshop to promote best practices associated with an item. It could also mean you need to encourage professional training, conferences, or searching for specific skills in future recruitment.</li><li>Moving from <strong>M</strong>otivated to <strong>A</strong>pplied requires some Epic or Stories to implement changes.</li><li>Moving from <strong>A</strong>pplied to <strong>R</strong>eviewed forces you to implement KPIs, document the process, dedicate time to review the tools in place continuously.</li><li>Moving from <strong>R</strong>eviewed to <strong>T</strong>ransformed symbolizes that you have established a “Bible” of how you do X in company Y.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Final Thought</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I noticed a lot of interest in the DevOps world for repurposing lean manufacturing toolbox. VSM (Value Stream Mapping) is very popular at the moment. This eagerness for “lean” tools is the main reason that leads me to share my experience with another tool. On top of that, I believe that this tool provides a strong structure that drives the change management process.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Good luck!</p>
<!-- /wp:paragraph --> ]]></description>
<category>DevOps</category>
<author>Alexandre Couedelo</author>
<pubDate>Thu, 27 May 2021 10:01:26 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Running Effective One-on-One Meetings as an Engineering Manager [7 Tips & Tricks] ]]></title>
<link><![CDATA[ https://adevait.com/blog/workplace/effective-one-on-one-meetings ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>Effective one-on-one meetings are the cornerstone of a good manager and employee relationship. Learn how to run effective meetings with these seven tips that will boost your management strategy.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You may be at your wit's end trying to figure out the best way to run effective one-on-one meetings. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Whether this is your first time <a href="https://adevait.com/guides/distributed-teams" target="_blank" rel="noreferrer noopener">leading teams</a> or are looking to up your game, here are my top 7 tips that can transform a dull and pointless one-on-one into a productive and empowering discussion.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>7 Tips for Making Your One-on-Ones Super Effective&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let me say this straight:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There isn't one universal model that's best for all individuals when it comes to running effective one-on-one meetings.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Instead, <strong>every meeting should be tailored to each individual's needs</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, meetings with a junior Laravel engineer should differ from meetings with a <a href="https://adevait.com/laravel" target="_blank" rel="noreferrer noopener">senior Laravel engineer</a>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Why is that?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Well, a junior engineer may need more help with adjusting to your company culture, while a senior engineer may require guidance on how to progress to a managerial position.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With this in mind, it's time for me to share a few general guidelines that can ensure your one-on-ones are going smoothly and your engineers are not staring into blank space.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4397,"width":664,"height":350,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/05/connection-between-employee-motivation-and-effective-management@2x-1024x541.png" alt="effective one-on-one meetings" class="wp-image-4397" width="664" height="350"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Start the Meeting by Sharing a Win</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Here's an interesting story:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://hbr.org/2011/05/the-power-of-small-wins" target="_blank" rel="noreferrer noopener">When HBR researchers</a> explored creative work inside businesses, they stumbled upon a remarkable phenomenon. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They analyzed diaries kept by knowledge workers and discovered a significant progress principle. They concluded that the most critical thing that can boost motivation during a workday is <strong>making progress in meaningful work</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In other words, the more often people experience a sense of progress, the more likely they are to be creatively productive in the long term.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Whether it's someone working on a scientific breakthrough project or building a tech product,<strong> even the smallest win can make a difference</strong> in how employees feel and perform.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here's what one programmer said to HBR researchers after a productive day:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>I smashed that bug that’s been frustrating me for almost a calendar week. That may not be an event to you, but I live a very drab life, so I’m all hyped.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This somewhat extensive explanation takes me to my first tip for running effective one-on-one meetings:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Start your meetings by sharing a win</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It doesn't have to be a large win; it can be something as small as complementing the engineer on the latest functionality they built.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Unfortunately, there's a negative side as well.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It turns out that negative events can have an even more powerful impact than positive ones on an employee's motivation for work.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With this in mind, managers should do their best to minimize daily hassles that can negatively affect a person's motivation.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Create a Psychologically Safe Environment to Help Them Open up&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In 2015, Google’s People Operations department set out to answer the question <strong><em>What makes a Google team effective?</em></strong>&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They discovered that five fundamental dynamics make the difference between successful and unsuccessful teams.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://rework.withgoogle.com/blog/five-keys-to-a-successful-google-team/" target="_blank" rel="noreferrer noopener">According to their study</a>, one of the most critical dynamics turned out to be <strong>psychological safety</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In short, psychological safety means that team members feel safe to be vulnerable in front of each other. The study found that teams with higher psychological safety:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>are more effective</li><li>bring in more revenue</li><li>are less likely to leave the company</li><li>are more likely to harness the power of diverse ideas from their teammates</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Think about it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Psychological safety makes people become more open-minded, motivated, and resilient. Their sense of humor also increases, as well as their problem-solving and divergent thinking abilities.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>My tip #2 for effective one-on-one meetings is this: <strong><em>create a psychologically safe environment by encouraging the employee to open up</em></strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The best way of doing so is first to open up yourself.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, share a story about something you did wrong at work and how that affected your mood that day. By demonstrating vulnerability, you're actually telling the employee that it’s OK to make mistakes.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another idea is to start every meeting by breaking the ice. Icebreaker questions are fantastic conversation starters. As cheesy as they may sound, they can do a fine job making the meeting environment more relaxed and safe.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, you can ask them:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>What is one item you couldn’t live without?</li><li>What quirky thing do you do regularly?</li><li>What’s your unusual talent?</li><li>Where would you go once the pandemic ends?</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Once you have the conversation going, continue by asking some of the following questions:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>What would you like us to discuss today?</li><li>Are there any roadblocks preventing you from completing your tasks?</li><li>How do you think we should structure our meetings?&nbsp;</li><li>Is there anything specific you'd like to discuss with me today?&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>I try to build a good rapport with my direct reports. Sometimes this is sharing an interesting/funny story about something that happened while I was in their position, or illustrating a specific challenges I had that I believe everyone faces. I also have several resources on hand to fall back on to get them to open up better. </p><cite>James Carr, Infrastructure Engineering Lead at Zapier</cite></blockquote>
<!-- /wp:quote -->
<!-- wp:image {"align":"center","id":4398,"width":650,"height":343,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/05/Psychological-safety@2x-1024x541.png" alt="psychological safety one on one meetings" class="wp-image-4398" width="650" height="343"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Create a Shared One-on-One Meeting Agenda</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Don't you just hate it when you go into a meeting and the discussion seems to be all over the place? You jump from one topic to the next without any insightful discussion or action plan.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I've been there.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Over the years, I've discovered that there are multiple benefits to having a clear structure for your meetings.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Knowing what will be discussed during a meeting helps my employees prepare and ensures the discussion doesn't go off the rails.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>My third tip for effective one-on-one meetings is to set a few recurring themes that you will discuss in your meetings</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, you can be talking about projects you completed in the previous week and priority tasks that should be completed in the week. You can discuss issues, roadblocks, and action items.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Keep in mind that your direct report should own the overall agenda of the meeting.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Ask them what they want to see added to the agenda. The agenda should reflect their needs—that is, if you care about employee engagement.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Ask them to suggest agenda items and the reason why they want to see those items included. In case you decide not to include something they suggested, don't forget to offer an explanation.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here's a rough sum up of what the meeting agenda can include:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Discuss this week</li><li>Revisit later</li><li>Roadblocks and wins</li><li>Goals</li><li>Action items</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Adding a bit of flexibility to your meetings is also recommended.</strong>&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once a month, change the agenda for the meeting. Use the time you have to talk about the engineer's growth and career development plan or listen to their constructive feedback.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here are a few more ideas on what you could discuss in your meetings:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Feedback on any in-progress assignments.</li><li>Checking in on company goals.</li><li>Identifying and resolving any roadblocks.</li><li>Celebrating milestones.</li><li>What worked well and what not on recent projects.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Keep in mind that a structure that works for one direct report may not work for another. Find a process and structure that works best for each employee.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Don't forget to type in the meeting agenda when you schedule the recurring meetings so that your attendee can easily reference it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another idea is to write the meeting agenda in Google docs and include the URL in the meeting description box so that you both have easy access when the time for the meeting comes around.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If Asana is your go-to tool for everything from sharing files to checking up with employees, <a href="https://asana.com/guide/examples/meetings/one-on-ones" target="_blank" rel="noreferrer noopener"><strong>here's a step-by-step guide on how to create a one-on-one project on the platform</strong></a>.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Now that I'm using Asana, my conversations and 1:1s are so much more productive because we have this shared space where we can collaborate. </p><cite>Tim Wood, Head of Product, Patreon</cite></blockquote>
<!-- /wp:quote -->
<!-- wp:heading {"level":3} -->
<h3>The Length and Frequency Can Vary for Each Employee</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The fact is that 30-minute weekly one-on-ones are the most common choice for engineers and their managers.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, this doesn't mean that you should adopt the same model.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The length and frequency of your one-on-one meetings should differ with each employee.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, meetings with your team leader may occur more frequently and last longer as you may have plenty of things to discuss, ranging from issues with team members to software development roadblocks.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When deciding on the length and frequency of your one-on-ones, here are some things you need to consider:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Is the engineer a newly employed employee, or have they been a part of the company for a while?</li><li>Is the engineer a team leader?</li><li>Do you have a lot to discuss every week?</li><li>Are you guiding the employee towards becoming a tech leader?</li><li>Do you have something urgent to discuss with your report each week?</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>If we look at what studies and reports show, employees who have regular meetings with their managers are almost three times more likely to be engaged than employees who don't have regular meetings with their managers.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But hear this: <strong>the fact that one-on-ones happen at all is more important to employees than the frequency of meetings</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>My tip would be to experiment with frequency until you find the right rhythm.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you have nothing to discuss this week, and the engineer feels the same, you can just cancel the one-on-one. This is completely normal, and it happens all the time.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I'd rather have my employee work on an urgent task than spend 30 minutes in a meeting that's pointless.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>As a software developer, avoiding meetings is generally a good call because they interrupt flow and often don’t really need you to be there, and meetings aren’t really getting work done. One of the weirdest things about becoming a manager is how much more meaningful meetings seem to become, and how many more of them appear on the calendar.</p><cite>Chris Kelly, Former Senior Manager, Software Engineering at Salesforce</cite></blockquote>
<!-- /wp:quote -->
<!-- wp:heading {"level":3} -->
<h3>Take Action on Your Engineer's Feedback</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let's imagine the following scenario:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Your<a href="https://adevait.com/shopify" target="_blank" rel="noreferrer noopener"> Shopify developer</a> shares feedback with you during one of your meetings. They say the development team is understaffed and needs to add a few more software engineers.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Do you take action?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here's the thing:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Whether you agree or disagree with the feedback, a better strategy is to acknowledge it than to ignore it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, saying something like, “Let me think about it and I'll get back to you next week," can greatly improve the employee's motivation and engagement.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Take some time to think about the employee's feedback and discuss it over the course of your next meeting.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>How do I know?—From personal experience and reading various studies.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For instance, <a href="https://www.businessnewsdaily.com/1934-leadership-listening-employee-input-initiative.html" target="_blank" rel="noreferrer noopener">one study conducted by John Izzo</a>—an author, speaker, and advisor on corporate sustainability issues—found that a big factor in preventing employees from speaking up is how leaders react to their ideas and input.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A whopping 38% of respondents said that "<strong>leaders dismissing ideas without exploring these ideas</strong>" is why they don't take initiative.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another 26% said that "<strong>not getting rewarded or recognized for playing outside the lines</strong>" is another major factor why they don't step up.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The biggest problem for people was "<strong>leaders making decisions without seeking input</strong>."</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>So, what does this all mean?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It means that if you expect employees to take initiative and bring forth ideas, you have to build a company culture that values ideas.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In fact, building a company culture that values people's ideas can lead to an improvement in so many areas of your company, such as employee productivity, engagement, retention, and innovation.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4395,"width":528,"height":454,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2021/05/employees-taking-initiative@2x.png" alt="listen to employee's feedback 1 on 1 meetings" class="wp-image-4395" width="528" height="454"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Include Different Topics in Your Meetings</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let's be real:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Very often, one-on-one meetings turn into simple status updates—nothing more, nothing less.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In fact, <strong>54% of managers said that one of the main goals of these meetings was to ask how specific projects are coming along</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Don't get me wrong.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I'm not trying to say that you shouldn't prioritize pressing issues and those of strategic importance.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What I'm saying is that you should include different topics in your meetings.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For instance, one-on-ones are an ideal opportunity to discuss an employee's growth and development. So, why not use the meeting to be curious about their plans for the future?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It's up to you, but when I plan on discussing growth and development with an engineer, I let them know beforehand. As these meetings usually require reflection and thought, I give my reports the time and space to think about what they want to say.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Here are a few questions I often ask my direct reports:</strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Are you interested in developing additional skills?</li><li>What do you love most and least about your job?</li><li>What projects have you enjoyed working on recently?</li><li>Would you like to be part of different projects?</li><li>Would you benefit from more mentoring?</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>One-on-ones can also be a place where the employee can open up about problems and challenges they're facing.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Some things to ask your report include:</strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>What changes could be made to help your productivity?</li><li>What are your most time-consuming tasks right now?</li><li>Are you encountering any roadblocks?</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Also, don't hesitate to ask for their feedback.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Here are a few questions to ask:</strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Do you find these meetings helpful?</li><li>Do you feel empowered in your role?</li><li>What can I change to help you work more efficiently?&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>If you are not careful, 1:1s can end up being status updates. Or the manager can take over the meeting. This isn’t their purpose. It’s important to make sure the employee and their needs stay front-and-center.</p><cite>Bronwyn Smith, VP of Business Operations at Influitive </cite></blockquote>
<!-- /wp:quote -->
<!-- wp:heading {"level":3} -->
<h3>End the Meeting on a Positive Note</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let's get to the final tip for effective one-on-one meetings:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You want to end the meeting in a similar way as you began it—with positive things.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If the best way to start an effective one-on-one meeting is to share a small win, the ideal way to end it is to show your appreciation and gratitude.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Don't worry. I'm not saying you should recite an Oscar speech, thanking your direct report for all of their hard work and dedication until you hear the play-off music.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Say something like, "<strong>Thank you for your time. Keep up the good work</strong>."</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It's short, it's clear, it's powerful.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Final Conclusion: Do's and Don'ts</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Congrats! You made it to the end of this extensive post.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Hopefully, you found it insightful and discovered a few great strategies for effective one-on-one meetings.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>To sum up, this long post boils down to these do's and don'ts.&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Do's:</strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Tailor your meeting to each unique individual.&nbsp;</li><li>Start your meetings by sharing a win.&nbsp;</li><li>Create a psychologically safe environment by demonstrating your vulnerabilities.&nbsp;</li><li>Have a structure for your meetings.&nbsp;</li><li>Add a bit of flexibility to your meetings.</li><li>Experiment with frequency until you find the right rhythm.</li><li>Acknowledge your employee's feedback.&nbsp;</li><li>Discuss different topics.&nbsp;</li><li>End the meeting on a positive note.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p><strong>Don'ts:&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Avoid making the meeting about yourself.</li><li>Don't let the meeting turn into a simple status update.&nbsp;</li><li>Don't hesitate to skip a meeting if there's nothing to discuss.</li><li>Make sure not to dismiss your employee's ideas without an open discussion.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>The most important lesson in entrepreneurship: Embrace the struggle.</p><cite>Ben Horowitz, The Hard Thing About Hard Things</cite></blockquote>
<!-- /wp:quote --> ]]></description>
<category>Workplace</category>
<author>Tosho Trajanov</author>
<pubDate>Tue, 18 May 2021 08:48:47 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Node.js Architecture: Most Common Problems and How to Fix Them ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/most-common-nodejs-architecture-problems-and-solutions ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Get this:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>According to Stack Overflow 2019 survey, Node.js is the most popular tool in the “Frameworks, Libraries, and Tools” category with 50% of answers.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, despite its popularity, it goes without saying that Node.js does come with its own set of problems.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's take a quick look at some of Node.js architecture best practices before we explore the most common problems you can come across.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>What Are the Main Parts of Node.js Architecture?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To handle more than one concurrent client, Node.js makes use of the “<strong>Single Threaded Event Loop</strong>” architecture.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To sum up, each of the parts of Node.js architecture is explained below:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Requests:</strong> in respect to the particular tasks users desire to perform in a web application, incoming requests can either be blocking (complex) or non-blocking (simple).&nbsp;</li><li><strong>Node.js Server:</strong> node.js server, as a server-side platform, does not only take requests from a user. It also processes these requests and ensures that they are returned to the corresponding user.&nbsp;</li><li><strong>Event Queue:</strong> in a node.js server, the Event Queue does the storage of incoming client requests and passes those requests one after the other into the Event Loop.&nbsp;</li><li><strong>Thread Pool:</strong> Thread pool contains all the available threads for performing certain tasks that are needed to fulfill client requests.&nbsp;</li><li><strong>Event Pool:</strong> The event pool does receive requests randomly, process them and ensure the responses are returned to the corresponding client.&nbsp;</li><li><strong>External Resources:</strong> whether external resources are used for computation, data storage, etc., they are resources needed for dealing with blocking client requests.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>How Does Node.js Work?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Node contains libraries of functions (packages and modules) that users can import from npm (node package manager) into their code and utilize. This simply means that you have for yourself some installed basic modules when you install on your computer – this simple server is created.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2>Benefits of Using Node.js Architecture</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The Node.js architecture has some interesting benefits that make the server-side platform stand out among every other server-side language. The server you developed using node.js are always faster and better responsive compared to the ones created using other server development technologies</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The advantages are:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Handling multiple concurrent client requests is fast and easy:</strong> the Node.js server ensures the efficient handling of many incoming requests all thanks to the event queue and thread pool.&nbsp;</li><li><strong>No need for creating multiple threads: </strong>you don’t need to create multiple threads because the event loop helps in performing the request one after the other. In conclusion, a single thread is enough to handle a blocking incoming request.&nbsp;</li><li><strong>Requires fewer resources and memory: </strong>due to the way node.js server handles the incoming requests; it doesn’t really require many resources and memory. This is made possible because the overall process doesn’t tax the memory that much due to the fact that the requests are being processed one after the other.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>Most Common Problems/Challenges with Node.js Application Architecture</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>As a Node.js developer, your work doesn’t just stop at developing web applications with node.js. Another important phase you should take seriously is the app maintenance part because problems and malfunctions can discourage clients from making use of your application.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Therefore, you need to learn how to find these problems and know the right solutions in handling them so that your app can be a success. The common challenges with Node.js application architecture are:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Extensive Stack: </strong>there is no generally accepted convention for developing applications in node.js. If you find a framework that uses node.js, you would discover that it’s unopinionated. What does this mean? This simply means that these frameworks for node.js do not have any certain guidance for writing codes in them. This is the reason why every app needs an individual approach and an experienced developer with good development processes and code maintenance abilities.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li><strong>Technical Debt:</strong> the lack of good practices could be the reason for many problems in node.js today. As a newbie in this field, having the luxury of many ways of developing apps from the opensource community could be a problem thereby leading to application structure incongruency. This is why it’s advisable to make use of well-tested design patterns from more traditional environments (such as java) for code maintenance.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li><strong>Scalability Challenges: </strong>scaling in node.js doesn’t come easy and this is due to the fact that it’s a single-threaded process. You might need to divide building many complex applications into smaller microservices that handle different operations.&nbsp;You must never forget to always relatively keep your performant and scalable Node.js application small and scalable any time you are architecting it.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:list -->
<ul><li><strong>Poor Documentation:</strong> the importance of documentation in the world of tech can't be over-emphasized. Documentation gives developers a hint of how an app operates. That's not all, it also tells you what its main components are made of and their relationship in respect to each other without leaving out the purpose why the app is built. In short, poor documentation could increase development time and make the entire process not an easy one to do. Once poor documentation occurs, your app could have performance issues or there could be a problem implementing new features.&nbsp;&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2>How Do You Solve These Problems?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Here are some of the Node.js architecture best practices for dealing with the problems outlines above:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Conducting code review any time you notice that something is not working properly in the application</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Irrespective of the stack you use, the first thing you must do is to run a review of your code. Code review gives information about code’s quality, the stack, and the application in general. A successfully run code review gives you a hint if the real problem lies within the performance, scalability, architecture, or flexibility.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Improving code quality</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Always clean up the file structure by dividing it into logical units once you notice that the overall code quality is relatively low or inconsistent. It’s always a good practice to implement both static code analysis tools (such as Codebeat) and a type systems (Typescript, Flow). Always perform code optimization on a regular basis and don’t forget to include code refactoring in your everyday development process. Lastly, always make it a habit to drive the deployment process with a properly configured Continuous Integration.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Updating stack</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You benefit a lot from keeping your node.js up to date. An up-to-date node.js helps you to boost the performance of your app. Not only does it do that, it gives you an opportunity to work with modern native solutions (such as async/await and other ES6/7 features) that can help to fasten development processes. Lastly, once you upgrade node.js, you won’t need to work with many third-party libraries anymore.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I<strong>mproving documentation</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>An app with good documentation is easily understood and it contains correct information that users need to get the best out of the software application. Ensure your app documentation is up to date and always endeavor to make it easily accessible to everyone in your team because good app documentation covers both good communication (among team members) and an efficient app development process.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Checking the roots of the problem if your app is not performing as it should.&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Investigate correctly if the problem lies with the architecture or some parts of the code are not written very well. At times, all you might need do is to implement autoscaling. Everything boils down to dig into the roots of the situation.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>By now, you must be wondering:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Why do I need to know all these things about Node.js architecture?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Well, for one, being equipped with this knowledge can help you land a job at a great company.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's imagine that a tech company is looking to <a href="http://hire nodejs developer" target="_blank" rel="noreferrer noopener">hire a Nodejs developer.</a> Do you think you'll have better chances of landing the job by knowing everything there is to know about Node.js or by wishing not too many candidates apply to the job?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Yes, it's the former!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With that being said, it's time you use the knowledge you gained from this article to write reusable, testable, and efficient code. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Good luck!</p>
<!-- /wp:paragraph --> ]]></description>
<category>Node.js</category>
<author>Tosho Trajanov</author>
<pubDate>Thu, 06 May 2021 10:16:40 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Top 6 Expert Skills Every Node.js Developer Should Have ]]></title>
<link><![CDATA[ https://adevait.com/nodejs/top-6-nodejs-developer-skills ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Believe it or not, Indeed reported that the number of job searches for Node.js rose by 57% last year. It just goes to show how quickly the popularity of Node.js has shot up. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The problem, however, is that the demand for Node.js developers has actually made it harder for CTOs to hire their own.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Finding a good developer is already challenging enough because you have to ensure that they have relevant experience and the background necessary to be a good fit. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In addition, each Node.js developer has different supporting skills, and you have to find the one whose skills best match your needs.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Regardless, everyone still wants a Node.js developer, and for good reason. It's one of the most popular backend technologies and can be used to create applications for social media, messaging, business tools, online gaming, and more.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Want to join the ranks of successful companies using Node.js? Read on to learn all you need to know when hiring a Node.js developer, including top Node.js developer skills.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>What Does It Take to Become a Node.js Developer</strong>?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To become a Node.js developer, it helps to have background knowledge of coding, debugging, and front-end development. An educational background in computer science or familiarity with HTML5 and CSS goes a long way.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The js in Node.js stands for JavaScript – the language used. As such, Node.js users should be well-acquainted with the JavaScript programming language.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And, like all developers, they need to remain up-to-date on all the software involved in their projects.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As a result of Node being open-source, many colleges don't teach it. To overcome this barrier, developers interested in learning Node.js often have to educate themselves with online sources. Once they feel proficient in Node, they can take an online certification exam to become an official Certified Node Developer.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Committing to this path does take a lot of hard work and motivation, making it ideal for self-starters.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>The 6 Node.js Developer Skills Most Wanted By CTOs</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Not all Node.js developers are made equal. While all are required to have some Node.js skills, others have areas of expertise or extra skills that help them stand out from the crowd. Here are 6 Node.js developer skills that the best and most competitive Node.js developers have.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>1. Valuable Experience</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Experience functions as proof that a developer has been in the field long enough to be familiar enough with the skills, knowledge, and processes necessary to be a good employee. The more experience a developer has, the more employers can trust that they have senior Node.js developer skills, and it's a good investment to pick them.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Several years in the career, though, isn't the only way to show off experience. A developer can also utilize a portfolio to showcase their best and most impressive projects.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>2. Database Management</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Database management is an important skill set, especially when working with businesses or applications that take in a lot of data. Node.js developers should be able to handle several databases and even integrate them if necessary. Perhaps most importantly, they need to be able to maintain database security the entire time.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>3. Managing Errors</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the biggest skills required for Node.js developers is error handling. Errors will always occur no matter what. Great developers have problem-solving skills and know how to handle minor and major errors and bugs quickly and efficiently.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>4. Time Management</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Time management is vital to every project. Developers especially need this skill because they work on many projects or many parts of the puzzle for one project, all at once.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A good Node.js developer will know how to prioritize their tasks, provide accurate time estimations until completion, and get things done by their deadlines.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>5. Efficient, Readable, and Compliant Code</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Code should be efficient and compliant so that it works quickly, effectively, and doesn't pose threats. Non-bloated code will also help applications run their best.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Readable code is important so that other developers can edit the code if necessary.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>6. Understanding of API Communications</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>No development environment is 100% perfect on its own, and every business and application has different needs. These needs also change over time.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is why developers with an understanding of API communications are in high demand. They can use APIs to integrate tools and projects into Node that will make development more efficient, saving time and effort.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Can a Node.js Developer Work on Projects Not Based on Node?</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Node.js is faster than other JavaScript languages and is more agile and versatile than many options. Even so, sometimes your project requires a different language or environment.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Fortunately, a good developer is always educated in multiple languages. Studies show that <a href="https://www.techrepublic.com/article/the-10-programming-languages-developers-use-most-with-node-js/#:~:text=js.,popular%20languages%20used%20alongside%20Node." target="_blank" rel="noreferrer noopener">60% of developers</a> spend their time in Node.js. This percentage is because the other 40% is spent in other languages or environments. Developers also need to be informed about software updates and other tools because the field is always changing.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This all goes to show that any good Node.js developer will still be able to handle projects that don't use Node.js. Of course, whether they have the background in the tools you need will depend on the developer.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Hire the Right Node JS Developer</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Hiring Node.js developers is tough to do because the demand is high and the supply is low. It's also hard because developers have such wide-ranging skills and scopes of knowledge, so it's difficult to ensure you're picking the one perfect for your projects.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>While there are Node.js developer skills that make a Node.js developer a particularly strong candidate, you want to ensure they can also handle other tools when needed. If you're looking to <a href="https://adevait.com/nodejs" target="_blank" rel="noreferrer noopener">hire Node.js developers</a>, we help companies hire the best talent in software development. Check out our services for <a href="https://adevait.com/enterprise" target="_blank" rel="noreferrer noopener">hiring enterprise talent</a> or <a href="https://adevait.com/startups" target="_blank" rel="noreferrer noopener">hiring startup talent</a> today.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Node.js</category>
<author>Tosho Trajanov</author>
<pubDate>Thu, 06 May 2021 10:15:20 +0000</pubDate>
</item>
<item>
<title><![CDATA[ 5 Best and Worst Practices in Java Coding ]]></title>
<link><![CDATA[ https://adevait.com/java/5-best-and-worst-practices-in-java-coding ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Are you a junior Java developer who wants to land his first job? Are you eager to discover how you can develop sophisticated solutions with your team?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You're in luck!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This post contains the top 5 best practices when coding in Java, as well as the most common mistakes Java developers make in their daily coding activities.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's begin!</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"feb480e2","classMigrate":true,"mappingHeaders":[true,true,true,false,true,true]} /-->
<!-- wp:heading -->
<h2 id="5-best-practices-when-coding-in-java"><strong>5 Best Practices When Coding in Java</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>As a Java developer, these are some of the best practices you should try out while writing codes for your next projects:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Using Naming Conventions</li><li>Ordering Class Members by Scopes</li><li>Class Members should be private</li><li>Using Underscores in Numeric Literals</li><li>Avoid Redundant Initialization (0-false-null)</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="using-naming-conventions"><strong>Using Naming Conventions</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You must be intentional in how you handle the naming convention for your codes and this is even what you do before starting to write a single line of code. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For instance, using naming conventions cover everything that has to do with rightfully naming a variable, constant, method, class and interface, etc.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When naming identifiers (methods, classes, and variables), it's a good practice for you to let the respective things you name them with to be self-explanatory, distinct, and pronounceable. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Most importantly, you must always ensure to write readable codes that are easily understood by humans (and not just write codes for the sake of satisfying the compiler).&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="ordering-class-members-by-scopes"><strong>Ordering Class Members by Scopes</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Organizing member variables of a class through their scopes is another good coding practice you should always try to implement while coding. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>That’s to say that, as a Java developer, it would be nice of you to sort each member by the visibility of the access modifiers: private, default (package), protected, and public. And a blank line separates each of the groups.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="class-members-should-be-private"><strong>Class Members Should Be Private</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>It's a good coding practice in Java programming to try as much as possible to reduce the accessibility of class members to the barest minimum possible. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When trying to protect the class members, you should make use of the least possible access modifier.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Why is it highly recommended to make class members (identifiers) private?</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The only logical reason for practicing this is to bring out the usefulness of encapsulating information in software development.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="using-underscores-in-numeric-literals"><strong>Using Underscores in Numeric Literals&nbsp;</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You can now write lengthy numeric literals that have a great readability score many thanks to the update done in Java 7.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><em>Before using Underscore:</em></h4>
<!-- /wp:heading -->
<!-- wp:code -->
<pre class="wp-block-code"><code>int minUploadSize = 05437326;
long debitBalance = 5000000000000000L;
float pi = 3.141592653589F;</code></pre>
<!-- /wp:code -->
<!-- wp:heading {"level":4} -->
<h4><em>After making use of Underscore:</em></h4>
<!-- /wp:heading -->
<!-- wp:code -->
<pre class="wp-block-code"><code>int minUploadSize = 05_437_326;
long debitBalance = 5_000_000_000_000_000L;
float pi = 3.141_592_653_589F;</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The above-written declarations in Java show the importance of using underscores in numeric literals to improve the readability of codes. When you compare the two declarations above, you would be able to deduce that the one with included underscores is more readable compared to the other one.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="avoid-redundant-initialization-0-false-null"><strong>Avoid Redundant Initialization (0-false-null)</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>As a developer, you should always avoid initializing member variables with values such as null, false, and 0. In Java, you don't necessarily need to do this because these values are the default initialization values of member variables.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, the initialization done below is not needed hence it is redundant:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>public class Person {
string name = null;
private int age = 0;
private boolean isGenius = false;
}</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2 id="5-worst-practices-when-coding-in-java"><strong>5 Worst Practices When Coding in Java</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>These are some of the worst practices you should try as much as possible to avoid while you write code for your next project:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Neglecting Existing Libraries</li><li>Using Raw Type Instead of a Parameterized One</li><li>Ignoring Exceptions</li><li>Excessive Garbage Allocation</li><li>Forgetting to Free Resources</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="neglecting-existing-libraries"><strong>Neglecting Existing Libraries&nbsp;</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>It’s not a good idea to always neglect numerous amounts of libraries written in Java. It’s always advisable for anyone in this regard to try and search for available libraries before getting too deep with a task (project).&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What makes these existing libraries special? </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A lot of these particular libraries have been reworked on and improved over the years. That's not all, they are also free to use. These existing libraries could come in form of network-related libraries (such as Akka, Netty, etc.) or logging libraries (such as Log4j, logback, etc.)&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="using-raw-type-instead-of-a-parameterized-one"><strong>Using Raw Type Instead of a Parameterized One</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In general, Raw Types are either not parametrized, or non-static members of class R that are not inherited from the superclass or superinterface of R. Not until generic types were introduced in Java, raw types never had an alternative.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Though raw types have had support for generic programming since version 15 an inadequacy has been discovered to possibly breakdown the system as a result of backward compatibility reasons.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>List listOfNumbers = new ArrayList();
listOfNumbers.add(20);
listOfNumbers.add("Forty");
listOfNumbers.forEach(n -&gt; System.out.println((int) n * 2));</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>For instance, in the above lines of codes, we defined a list of numbers as a raw “<strong>ArrayList</strong>". Any object can be added to it since the type of the "<strong>ArrayList</strong>" wasn't specified with the type parameter.&nbsp; </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you check the last line in the above codes, you will see that we cast elements to int, double it, and print the doubled number to standard output. The truth is that there won’t be errors in it during compilation time but during runtime the reason because we tried to cast a string to an integer.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>How can this be corrected?</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The only way out is by defining the collection by specifying the type of data getting stored in the collection. The lines of codes below show that:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>List&lt;Integer&gt; listOfNumbers = new ArrayList&lt;&gt;();
listOfNumbers.add(20);
listOfNumbers.add("Forty");
listOfNumbers.forEach(n -&gt; System.out.println((int) n * 2));</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Nevertheless, the above-corrected version won't compile well because we tried to add a string into a collection that is expected to store integers only. Where we tried to add the string “<strong>Forty</strong>”, the compiler will show and point at an error.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Above all, parameterizing generic types is the best way out of this. By this, the compiler can see and make all the possible types hence reducing the chances of runtime exceptions.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="ignoring-exceptions"><strong>Ignoring Exceptions</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Leaving exceptions unhandled might be tempting but always try as much as possible to handle them. Addressing these exceptions when they appear is the only way out of this because they are intentionally thrown.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>But how do you address them?</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Either by:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>rethrowing them.</li><li>showing an error dialog to the user.</li><li>adding a message to the log.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>At least it’s better to let other developers know the reason behind leaving out the exceptions.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>By encoding:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>“try { selfie.delete(); } catch (NullPointerException unimportant) { }” </code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>into the exceptions’ variable name is one of the best ways of highlighting an exception’s importance.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="excessive-garbage-allocation"><strong>Excessive Garbage Allocation</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Creating many short-lived objects may result in excessive garbage allocation. This is never a good practice in Java programming because the performance of an application is affected negatively anytime the garbage collector tries to remove an unneeded object from memory.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code> StringBuilder oneMillionHelloSB = new StringBuilder();
for (int i = 0; i &lt; 1000000; i++) {
oneMillionHelloSB.append("Hello!");
}
System.out.println(oneMillionHelloSB.toString().substring(0, 6));</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Strings are immutable in so that is why we used a mutable StringBuilder in the above example so that our code will execute very fast within a second.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="forgetting-to-free-resources"><strong>Forgetting to Free Resources</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You should always try to free resources any time they are done using them. Also, similar caution needs to be taken any time an exception is thrown during an operation on such particular resources too.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="conclusion"><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this tutorial, we've explored the best and worst practices when coding in Java. We say how organizing member variables of a class through their scopes is a great coding practice you should always try to implement while coding.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We also saw how leaving exceptions unhandled might be tempting but it a practice we should avoid as much as possible. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>All in all, all of the practices mentioned above lead to one thing: making our code cleaner and better. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On the plus side, a developer who constantly strives to improve stands a good chance to be contacted by a client looking to <a href="https://adevait.com/java" target="_blank" rel="noreferrer noopener">hire Java developers</a>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Good luck!</p>
<!-- /wp:paragraph --> ]]></description>
<category>Java</category>
<author>Tosho Trajanov</author>
<pubDate>Sun, 25 Apr 2021 20:14:19 +0000</pubDate>
</item>
<item>
<title><![CDATA[ 5 Java Trends to Watch in 2021 ]]></title>
<link><![CDATA[ https://adevait.com/java/top-5-java-trends-to-watch-in-2021 ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>When you hear about Java, the first thing that most probably crops up in your mind is that it's the oldest programming language. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But is it still popular today? Most importantly, is it a good fit for your software development solutions? </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's take a look at the 5 new trends in Java that may inspire you to build your next big product.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Why Is Java Still Popular Today</strong>? </h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>With the constant updates, Java can keep up with the trends in technology and software development and can support many languages across its platform. It has enabled Java to become one of the most used programming languages in disruptive technologies like the IoT and AI.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Java also enables you to build software on modern application pillars which are secure, scalable, and robust. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As a result, everything from scientific computers to gaming consoles will continue relying on its versatility. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Additionally, through its reactive function, it provides developers with exceptional support for advanced streaming applications.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Java Trends to Watch in 2021</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In 2021, experts are confident that Java will remain the most preferred programming language in the future. Due to the evolving technological changes, there will be a continuous demand for Java developer skills in the years to come. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now bear with me as we go through the top 5 Java trends for 2021. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's begin!</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Java Releases</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Even before the release of Java SE 15, Java 8 was the most popular version among developers. Many tech experts devoted themselves to Java 8 due to the available public updates for private and commercial use. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The long-term support version was also a critical factor, although there were no more commercial and public use updates as of December 2020. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Today, many serious production applications are moving to Java 11.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, since there are constant upgrades in Java trending versions, it's an opportunity to fill your Java knowledge. The SE 15 is a non-long term version with various enhancements, including:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Hidden classes</strong> – The hidden classes are usually dynamically generated at runtime and can't be accessible by name. Additionally, you cannot directly link them to the byte code of other classes.</li><li><strong>Records</strong> – You can use them to declare a class, and it's added automatically: getters, hashCode, equals methods, toStrings, and constructor.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>You also need to watch out for <a href="https://blogs.oracle.com/java-platform-group/the-arrival-of-java-16" target="_blank" rel="noreferrer noopener">JDK 16</a>, released on 16th March 2021, making it the latest Java trend on the SE platform. It has 17 new enhancements grouped into futureproofing your work, JVM improvements, incubator and preview features, improving productivity, and new tools and libraries category.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Spring</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>As a CTO, you are most likely familiar with the Spring framework in Java. You can use it in diverse ways, from online shopping and streaming platforms to banking and insurance platforms. It's ideal for creating a backend for Java applications to the Java Enterprise Edition platform.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It's also an excellent solution when building an organization's applications in Java. It can include cloud applications, microservices, complex data processing systems, or responsive, safe, and fast web applications.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You should expect the popularity of Spring to be even stronger throughout 2021, owing to it being lightweight and its ease of implementation. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In other words, if you're looking for a <a href="https://adevait.com/java" target="_blank" rel="noreferrer noopener">Java developer for hire</a>, make sure to look for someone with good coding skills in Spring Boot or Spring MVC.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Big Data</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>With the growth in information and computing power, more organizations have turned their attention to big data calculations. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Java is the most preferred language in big data projects due to various open-source tools such as Apache Hadoop, JFreechart, Deeplearning4j, and Apache Mahout – all of which help you attain more efficiency.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You'll also find Xplenty, a data integration service that assists in processing, transforming, and moving data faster. This way, it minimizes set-up time to allow companies to unlock data quickly.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With extensive data amounts, you can also rely on Cassandra. It's a data management tool that handles your large data that are across multiple servers. One great advantage of this tool is that it will continue functioning even when one server fails.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Integration Testing</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>When writing codes, testing is an essential procedure. It helps you to reduce misprints or errors while also proving that you have a viable code. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This way, you save time that you would have used in rewriting or searching for mistakes. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, when building a complex app in Java, you would have to spend a considerable amount of time creating tests manually. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For this reason, developers can now use frameworks, test libraries, and tools such as Hamcrest, Robot Framework, Cucumber, JUnit, REST-Assured, Mockito, Selenium, and more.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Serverless Architecture</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The move to serverless architecture is another trend expected to be more prevalent in 2021. It's a cloud service model that enables you to focus solely on coding instead of infrastructure.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When using serverless architecture, you don't have to update the operating systems, scaling the application, setting up machines, or network configuration. You will also enjoy greater flexibility and a reduction in operating costs leading to faster value delivery.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2><strong>Key Takeaway</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Keeping a close eye on the latest trends in Java can come in handy when hiring developers. For one, you'll get to tailor your solutions accordingly and build a competitive product that's on par with the competition.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With all the new developments happening in Java, it's safe to say that the programming language is going to remain an important player in the technology world – at least in 2021. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>So, if you're thinking about developing a robust and effective solution for your business, then Java can be a great pick.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Java</category>
<author>Tosho Trajanov</author>
<pubDate>Sat, 17 Apr 2021 19:04:48 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Pros of the Laravel Framework Compared to Other Frameworks ]]></title>
<link><![CDATA[ https://adevait.com/laravel/pros-of-laravel-framework ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Every business has a web application, it seems. If your company is lagging, or you want to update what you have, you may feel stuck. Dynamic web applications require a powerful back-end and an intuitive front-end.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>PHP is the language of choice for data-heavy, quick-running apps. Hand-coding PHP is tedious and provides too many opportunities to introduce errors.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Using a framework is the answer to this problem, but which one?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel is a step up from many PHP frameworks available today. The intuitive design makes Laravel easy to pick up and use. An online Laravel framework tutorial is enough to get you started but to really create, you may want to bring in the pros.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Ready to get started?</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"631aae46","classMigrate":true,"mappingHeaders":[true,true,false,false,true,true]} /-->
<!-- wp:heading -->
<h2 id="understanding-php"><strong>Understanding PHP</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Using PHP allows you to program dynamic web applications that use a database. As you can imagine, this makes up a huge amount of the web applications currently in use. PHP is one of the <a href="https://www.w3schools.com/php/" target="_blank" rel="noreferrer noopener">most popular programming languages</a>, and nearly 80 percent of websites use the language.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One of the reasons PHP is so popular is due to its flexibility. Developers have a wide range of choices in deciding how to create their application, and PHP supports many databases.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Building complex web applications that are responsive to the user and pull from a database would be a monumental task if the coding were in bare PHP. To make the building process a less demanding and more intuitive process, PHP frameworks were developed. These frameworks are template libraries that speed up the programming process.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Related: <a href="https://adevait.com/laravel/laravel-overwriting-default-pagination-system" target="_blank" rel="noreferrer noopener">Laravel Pagination Example </a></strong></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="php-frameworks"><strong>PHP Frameworks</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>PHP frameworks make quick work of creating web applications. The libraries built into the framework allow the developer to forgo much of the repetitive processes that are part of building an app.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Frameworks are also easy to customize. While the developer can use some or all of the code from a library, they can also write their own code, making the design process as hands-on as needed.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Even experienced web developers benefit from libraries. In addition to reducing the repetitive tasks needed to create an application, these libraries follow best practices. Testing ensures they are reliable and error-free.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When using a PHP library, you can be confident that the code will work. While testing is part of the building process, using established libraries cuts down on errors and helps ensure you are using architecturally-sound code.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Finally, building with PHP libraries ensures that once you hand off a project, your code is easy to read and understand for other developers when it is time to update or add features to the application.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="what-to-look-for-in-a-framework"><strong>What To Look For in a Framework</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are several different PHP frameworks to choose from. How to choose the one that is best for your project?</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>MVC Structuring</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Model-View-Control is a frequently used and established design pattern. Using MVC to build your app saves time as you won’t need to create the architecture. It also ensures that your project design makes sense.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel modules add another step of organization, ensuring that your code is consistent and easy to manage. You aren't limited when creating them, you can add CSS and javascript to the modules.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>The Testing Features Available on the Framework You Choose</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Using established libraries makes the building process more error-proof, but testing throughout the design process is still important. Automated testing saves time and allows you to avoid the mind-numbing process of debugging your code.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Perhaps the Most Important Feature in a PHP Framework Is Its Libraries</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>A framework with an extensive choice of libraries cuts down on the amount of time you spend coding. If you have a specific project in mind that doesn’t have much complexity, a framework with more limited libraries may be fine, however, greater access provides greater flexibility.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Related: <a href="https://adevait.com/laravel/using-corcel-in-laravel" target="_blank" rel="noreferrer noopener">How to Use Laravel Together With Corcel </a></strong></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="what-to-look-for-in-a-framework"><strong>What Is the Laravel Framework?</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>An open-source framework designed to build PHP web applications, Laravel follows the model-view-controller, or MVC, architectural pattern. This cuts down on the amount of time needed to create a web application, eliminating much of the repetitive work of building web apps.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel is designed to make it easy to create the web application you want without the need to create your code from scratch.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you are familiar with other frameworks, such as Ruby on Rails, you may recognize some similarities. Having existing knowledge of any PHP framework will make the transition to Laravel much easier.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Comparing Laravel and CMS like WordPress highlight the strengths of Laravel. Building your application on Laravel provides stability and security while allowing endless ways to customize.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once you get in front of the keyboard, you will notice that Laravel is designed for easy, intuitive creation. The goal of this framework is to speed the app development process. Simplicity and accessibility make it hard to beat Laravel if you are looking for a functional, stable framework.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="laravel-framework-tutorial"><strong>Laravel Framework Tutorial</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The Laravel framework is designed to get you up and running quickly. Use Composer to download the Laravel installer. The command “laravel new” gives you a new installation, and you are ready to go.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Wondering how to install Laravel on Windows? As long as you have Docker Desktop, you are good to go.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>An online Laravel tutorial will get you started. Use the <a href="https://laravel.com/docs/8.x" target="_blank" rel="noreferrer noopener">official documentation</a> to familiarize yourself with the syntax.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="11-pros-of-using-laravel">11 <strong>Pros of Using Laravel</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Laravel isn't the only PHP framework. CodeIgniter, CakePHP, Yii, and Symfony are some of the other choices. When compared to other frameworks, Laravel stands out in several specific ways.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Laravel Allows the User To Easily Utilize the Latest PHP Features</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Probably the greatest of the benefits of Laravel and the reason why Laravel is so popular is the ability to use the latest developments in a lightweight framework.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you are interested in overloading, interfaces, namespaces, anonymous functions, and a shorter array syntax, PHP Laravel is the choice for you.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Easy To Use Documentation</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Documentation is the heart of development, and <a href="https://laravel.com/docs/4.2/quick" target="_blank" rel="noreferrer noopener">Laravel’s documentation</a> makes it easy to find the information you need on methods, style, classes, and coding.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Documentation makes it easy to answer any questions you may have, but you have another tool available as well. The online Laravel community is large and generous. Finding some help when you are stumped is only a click away.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Easy To Use Command-Line Tool</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Repetitive programming tasks take up time and increase the odds of introducing errors to your code. Artisan is a Laravel command-line tool that makes creating skeleton code and running the database as painless as possible.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Mail Service Integration</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>It is hard to think of a recent web application that doesn’t use mail services to promote offers and updates to its users. Laravel’s use of API makes it easy to stay in touch. Web apps developed using Laravel can send emails through both cloud-based and local services.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Laravel Is Fast</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Laravel’s queue management system removes unnecessary tasks from the workflow. By running some tasks in the background, the user gets an immediate response to their request, improving their experience.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Makes Quick Work of Resource and Asset Revisioning</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Laravel allows you to take advantage of packages such as bower and npm. The composer helps find dependencies. The combination adds stability to your web app.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Offers Popular Backend Cache Support</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Memcached and Redis, two of the most used cache backends are supported out of the box with Laravel. The support of cache backends speeds up your app and improves the experience for your users.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Easy Updates</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One feature that really sets Laravel apart is the ability to update links in seconds. Once the user creates a link, Laravel will insert the needed URL. To update or change the route later, the user only needs to change it once. Laravel will automatically update everywhere it is used.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Manage Inversion of Control</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>IoC allows you to generate objects without the need to bootstrap. Accessing these objects from your coding environment adds stability and flexibility.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Implementing ActiveRecord Is a Breeze</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The MVC model you construct will have a matching database table. With this feature, changing a table automatically changes the related data. Laravel supports a variety of relationships here, including one-to-one, one-to-many, many-to-many, and more.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><strong>Authentication and Testing Is a Straightforward Process</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Laravel’s authentication process works straight out of the box. A dedicated file for testing is already set up and PHP comes with Laravel. Testing capabilities also include the ability to troubleshoot common issues such as common user actions.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And if you run into trouble?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Laravel has integrated logging, allowing you to document and review exceptions and errors.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="laravel-is-the-pros-choice"><strong>Laravel Is the Pro’s Choice</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now you know how it works, are you ready to get started? You need more than an online Laravel framework tutorial to build a killer app. <a href="https://adevait.com/laravel" target="_blank" rel="noreferrer noopener">Hire a Laravel developer</a> to handle the building and get your web application up and running.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Laravel</category>
<author>Ivica Jangelovski</author>
<pubDate>Tue, 06 Apr 2021 20:52:38 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Top 7 Shopify Problems and How to Solve Them Effectively ]]></title>
<link><![CDATA[ https://adevait.com/shopify/top-7-shopify-problems-and-their-solutions ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>Here's an overview of the top 7 Shopify problems and tips for how to solve them effectively. A must-read for every online store owner.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It’s always a dream come true for every business person to own an independent store. Spotify comes second to none when the questions about establishing an online store arise.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It is true that developing and making use of a web store comes with a pleasant experience and at the same time with a range of problems that cause you a headache.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On your road to finding answers to these challenging problems, first of all, it’s required of you to know the fundamentals of managing a store.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In addition, it’s also necessary for you to have a clear knowledge about working around every aspect of selling something online effectively.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Above all, challenging tasks such as importing products to Shopify, maintaining an excellent conversion rate, having to create a solid customer base just to mention a few of them are some of the key things we have carefully provided an answer here for Shopify users aiming to maximize profits with their online stores.</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"9fe738ed","classMigrate":true,"mappingHeaders":[true,true,true,false,false,false],"headerLinks":"[{\u0022tag\u0022:3,\u0022text\u0022:\u0022What are the Common Shopify Problems?\u0022,\u0022link\u0022:\u0022what-are-the-common-shopify-problems\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eWhat are the Common Shopify Problems?\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022ERP Integration\u0022,\u0022link\u0022:\u0022erp-integration\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eERP Integration\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Solutions to Shopify-ERP Integration\u0022,\u0022link\u0022:\u0022solutions-to-shopify-erp-integration\u0022,\u0022content\u0022:\u0022\u003cem\u003eSolutions to Shopify-ERP Integration\u003c/em\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Multi-Channel Integration\u0022,\u0022link\u0022:\u0022multi-channel-integration\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eMulti-Channel Integration\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Simple Ways on How to Deal with Shopify Multi-Storefront Challenge\u0022,\u0022link\u0022:\u0022simple-ways-on-how-to-deal-with-shopify-multi-storefront-challenge\u0022,\u0022content\u0022:\u0022\u003cem\u003eSimple Ways on How to Deal with Shopify Multi-Storefront Challenge\u003c/em\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Shopify Store Integration with Ruby on Rails Application\u0022,\u0022link\u0022:\u0022shopify-store-integration-with-ruby-on-rails-application\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eShopify Store Integration with Ruby on Rails Application\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022But How Is This Done?\u0022,\u0022link\u0022:\u0022but-how-is-this-done\u0022,\u0022content\u0022:\u0022\u003cem\u003eBut How Is This Done?\u003c/em\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Getting Products on Store\u0022,\u0022link\u0022:\u0022getting-products-on-store\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eGetting Products on Store\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022The Best Way to Solve this Shopify Issue…\u0022,\u0022link\u0022:\u0022the-best-way-to-solve-this-shopify-issue\u0022,\u0022content\u0022:\u0022\u003cem\u003eThe Best Way to Solve this Shopify Issue…\u003c/em\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Finding Customers\u0022,\u0022link\u0022:\u0022finding-customers\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eFinding Customers\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022So, What’s the Easiest Way of Getting the Attention of Customers to Your Products?\u0022,\u0022link\u0022:\u0022so-whats-the-easiest-way-of-getting-the-attention-of-customers-to-your-products\u0022,\u0022content\u0022:\u0022\u003cem\u003eSo, What’s the Easiest Way of Getting the Attention of Customers to Your Products?\u003c/em\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022No Increase in Sale\u0022,\u0022link\u0022:\u0022no-increase-in-sale\u0022,\u0022content\u0022:\u0022N\u003cstrong\u003eo Increase in Sale\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022The Solution to this Issue…\u0022,\u0022link\u0022:\u0022the-solution-to-this-issue\u0022,\u0022content\u0022:\u0022\u003cem\u003eThe Solution to this Issue…\u003c/em\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Managing Marketplaces\u0022,\u0022link\u0022:\u0022managing-marketplaces\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eManaging Marketplaces\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022To Get this Solved…\u0022,\u0022link\u0022:\u0022to-get-this-solved\u0022,\u0022content\u0022:\u0022\u003cem\u003eTo Get this Solved…\u003c/em\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Conclusion\u0022,\u0022link\u0022:\u0022conclusion\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eConclusion\u003c/strong\u003e\u0022,\u0022level\u0022:0}]"} /-->
<!-- wp:heading -->
<h2 id="what-are-the-common-shopify-problems"><strong>What Are the Common Shopify Problems?</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In order to help you ease your understanding and performance while working with Shopify, we have provided for you in this article the common Shopify issues with the right solutions to overcome them.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can choose to overcome these issues yourself or you can hire an experienced <a href="https://adevait.com/shopify" target="_blank" rel="noreferrer noopener">Shopify developer</a> to handle the job for you.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These common Shopify problems include:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>ERP Integration</li><li>Shopify Store Integration with Ruby on Rails Application</li><li>Multi-channel Integration</li><li>Getting products on store</li><li>Finding customers</li><li>No increase in sale</li><li>Managing marketplaces</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="erp-integration"><strong>ERP Integration</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>A Shopify merchant that constantly deals with high-volume data or complex back-office processes would benefit greatly from the ERP system integration.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you are consistently having a significant increase in order volume or delays in financial reporting, it’s a good sign that you need a Shopify integration with an ERP system.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>That’s not all, other indications that could show that you need this integration include:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Having lots of suppliers to manage.</li><li>Low employee productivity as a result of doing tasks manually.</li><li>Late shipping of products.</li><li>Wrong shipping of products due to high volume.</li><li>Having to manage more than one B2B customer relationship.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>And whatever ERP system you have decided to choose at the end of the day, you must pass it through the right factors in order to make it worthwhile.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Solutions to Shopify-ERP Integration</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>It’s possible for you to indirectly get your business limited if your preferred ERP system doesn’t integrate well with Shopify.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And on the other end, it’s also not compulsory for you to implement this integration but you would be left with the only choice of moving your data back and forth yourself with your Shopify online store and ERP systems if you decide not to integrate it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The consequences of doing your tasks manually result in time wastage and most likely human errors.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>During your evaluation of an ERP’s integration proficiencies, it would be nice of you to distinguish how your ERP system sends and receives data, or how it tends to communicate with another system. If your system struggles to easily connect with other systems, it would limit what processes you can automate between it and Shopify.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Above all, you should consider a cloud-based ERP system that has an open and well-documented API&nbsp;because it’s very simple to integrate. That’s not the only thing that makes it stand out, it’s generally very easy to access and it’s a more affordable option for small to medium-sized businesses. Cloud-based ERPs offer reduced IT infrastructure costs, pay-per-use pricing models, and lower upfront investment.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="multi-channel-integration"><strong>Multi-Channel Integration</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Having multiple channels linked with your Shopify comes with its own goodies. When you sell on multiple Shopify stores, you are open to seeing your business expand and it also allows you to serve your customers better. This said and put to one side, the actual management of developing many Shopify stores can be so stressful and difficult to do.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When this occurs, you begin to think separately for every account, order, item and inventory data. You will need to provide answers to questions like maintaining a 360-degree view of customers across each of your stores and also getting the right way of decimating inventory when the same items are sold on two separate stores.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Simple Ways on How to Deal with Shopify Multi-Storefront Challenge</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Though it might be tricky managing more than one Shopify shop, don’t give in to the fear of doing it if it’s necessary you have to try it out. Each for each, you must specially optimize all your sites. In order words, it’s highly recommended for you to be conversant with the language of your customers.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another thing you have to do here is to centralize all your orders into one system. By doing this, you can easily manage every of your site's orders consistently without any mismatch or issues that would leave you confused and frustrated.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="shopify-store-integration-with-ruby-on-rails-application"><strong>Shopify Store Integration with Ruby on Rails Application</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>It becomes easier and better to develop a Shopify app with the Ruby on Rails framework since Shopify itself is built with it. Why do you need a Shopify app? Shopify apps act as a plugin for Shopify stores in situations merchants are looking to improve their store functionality.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>How Is This Done?</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>It’s quite simple, all you need to do is to follow the provided steps below to create a Shopify app with Ruby on Rails:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>First and foremost, you will need to have a <a href="http://shopify.com/partners" target="_blank" rel="noreferrer noopener">Shopify Partner account</a>.&nbsp;</li><li>Secondly, <a href="https://help.shopify.com/en/api/tools/partner-dashboard/your-apps" target="_blank" rel="noreferrer noopener">create a custom Shopify app</a> within the partner dashboard.</li><li>Inside the app, set up URLs.&nbsp;</li><li>Lastly, obtain the API key and API secret key from the app.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Mind you, you will need an SSL certificate if you are making use of your own domain immediately after the deployment on the server is completed (<strong>always remember to use https://</strong>).&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="problem-with-getting-products-on-store"><strong>Getting Products on Store</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the biggest Shopify problems is how to get products on Shopify. It becomes stressful to categorically tell the source of this particular issue because the problem could come from your product listings or other marketplaces.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Indeed, you can simply use CSV files to import products but you need to be super careful with it because it could fail with just a single error. Talking about how it’s sensitive to failing: It’s better for it to fail when you are just importing very few products because you can easily perform the uploading one by one.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But the opposite is the case for bulk transfers. For instance, imagine having to upload hundreds or thousands of products in a short limited time.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>The Best Way to Solve this Shopify Issue…</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Inventory management is the answer to the problem here. As a seller that got the intention of managing more than one marketplace, you will need to implement inventory status in real-time. there is nothing as sweet as having the right data because it makes selling less risky and improves business operation irrespective of how you look at it in the long run.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="problem-with-finding-customers"><strong>Finding Customers</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Newbies trying out e-commerce for the first time are very likely to have the problem of finding customers for their products. First-time Shopify users always find it hard to generate traffic for each of their entities.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>What’s the Easiest Way of Getting the Attention of Customers to Your Products?</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the ways out of this is by trying out the right advertisement and promotion for your business. Also, never hesitate the chance of joining a high-rated marketplace that pulls numbers. Make use of their customer base to develop your Shopify store. Lastly, undergo optimization on your store for a better engagement that in turn helps in drawing more customers to your business.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="problem-with-no-increase-in-sale">N<strong>o Increase in Sale</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Note that a huge amount of traffic is not equal to sales. Getting the right customers to your product is one of the common Shopify issues you can easily encounter when owning your online store and it is not always easy to convert prospects into customers.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>The Solution to This Issue…</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Create ad campaigns (on any high conversion rate platform of your choice), provide sure shot cash back guarantee, share customers' experiences, and many other common ones not mentioned here.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="problem-managing-marketplaces"><strong>Managing Marketplaces</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Managing multiple marketplaces comes with working under a great lot of pressure and workload. It even becomes worse if you own a store that demands your optimum attention 24/7 every day of the week.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>To Get This Solved…</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The good news is that Shopify got apps from their official partners such as CedCommerce that would assist you in sharing the burden of getting Inventory status, SKUs check, Shipping and Order management for all marketplaces.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="conclusion"><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The most common Shopify problems and their respective solutions have been provided above for your use and understanding. Note that the problems are not limited to the ones we have rightly answered in this article. Every seller would have to deal with many of these problems (including the ones we have made time to find solutions to on this page) to overcome these processes. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Related: <a href="https://adevait.com/shopify/4-shopify-developer-skills-and-their-practical-application" target="_blank" rel="noreferrer noopener">4 Shopify Developer Skills and Examples of Their Practical Application</a></strong></p>
<!-- /wp:paragraph --> ]]></description>
<category>Shopify</category>
<author>Nikola Matkovski</author>
<pubDate>Tue, 06 Apr 2021 20:51:44 +0000</pubDate>
</item>
<item>
<title><![CDATA[ How to Lead With Empathy in the Remote World ]]></title>
<link><![CDATA[ https://adevait.com/blog/remote-work/empathy-in-the-remote-world ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Empathy is one of the most important soft skills. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It is the ability to understand and put yourself in someone else’s position. It is what makes us human and able to share and connect with others.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When the world took the biggest hit last year, every leader was challenged to review their leadership style and adapt it to the new work environment. They understood that now more than ever, we need to lead with humanity.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But what have been leaders' greatest challenges so far? What are the most notable benefits of leading with empathy? And finally, what are some of the best practices?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s dive in!</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"aae92454","classMigrate":true,"mappingHeaders":[true,true,false,false,true,true]} /-->
<!-- wp:heading -->
<h2 id="the-challenge-of-empathy-in-a-remote-environment">The Challenge of Empathy in a Remote Environment</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are many ways to show empathy. It is easier to do it if the person is in close proximity to you. But what happens when the workplace is based on remote work? It definitely becomes more challenging, but not impossible.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A <a href="https://hbr.org/2020/07/remote-managers-are-having-trust-issues" target="_blank" rel="noreferrer noopener">recent study</a> by Harvard Business Review found that many managers aren’t confident in their ability to <a href="https://adevait.com/guides/distributed-teams" target="_blank" rel="noreferrer noopener">lead remote teams</a>, think negatively about this work practice, and don’t trust their workers.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>More specifically:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>40% of managers are having difficulties adapting to the remote environment and managing their employees</li><li>38% of managers believe that remote workers perform worse than in-office workers</li><li>41% are skeptical whether r<a href="https://adevait.com/blog/startups/motivate-remote-employees-tech-startup" target="_blank" rel="noreferrer noopener">emote workers can stay motivated</a> in the long-term</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>The same study suggests that employees have their own concerns about remote work and how they’re managed by their leaders.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For instance, 21% said their supervisor constantly evaluated their work while 34% said their managers don’t trust their ability to the work. A great deal of workers also said they needed to be constantly available.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The end result? </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Employees struggling with <a href="https://adevait.com/blog/future-of-work/mental-health-future-of-work" target="_blank" rel="noreferrer noopener">high levels of anxiety</a>. Considering people are working in situations with additional pressures—such as children being in the house due to homeschooling—the remote work experience becomes even more challenging for the remote worker.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What do all these numbers and statistics tell us?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It’s simple! </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They confirm the fact that many managers have been caught off-guard with the rapid transition to remote work. In return, many workers are feeling micromanaged and mistrusted by their managers. It’s a recipe for disaster!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But not all is lost! </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There are some things managers can do to improve empathy in the workplace and support their employees.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Bear with me as we go through the top benefits of leading with empathy. </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4272,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/04/understanding-1024x454.png" alt="benefits of empathy" class="wp-image-4272"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="the-benefits-of-empathy-in-the-workplace">The Benefits of Empathy in the Workplace</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Leading is a challenging task to begin with, and adding empathy to the equation might sound as too much of a burden.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, in recent research conducted by Businessolver, <a href="https://www.businessolver.com/resources/state-of-workplace-empathy" target="_blank" rel="noreferrer noopener">76%</a> of employees agreed that empathy inspires more motivated employees. The same research also shows that:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>75% of employees would opt for an employer that offers a strong culture of empathy over an employer that offers a slightly higher salary</li><li>73% would change their role, industry, or career path if it meant working for an empathetic leader</li><li>83% would leave their job for a similar role at a more empathetic company</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>It is not only the employees that think that empathy is crucial. From this study, we see that CEOs also associate the financial achievements of their companies with practices of empathy.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In a rapidly changing world where the advancements of technology and the growing demands, people often forget how important it is to actually take some time to connect with each other. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>More and more we see that empathy has to be elevated and practiced as a core value, which will improve the <a href="https://adevait.com/blog/workplace/build-strong-engineering-culture" target="_blank" rel="noreferrer noopener">workplace culture</a>, productivity, create more innovation and profit.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="the-new-era-of-leadership">The New Era of Leadership</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Leadership means reaching out to people.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>How do you know if the people you are trying to reach are actually reachable? You practice empathy.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With empathy you can strategize and take the correct decisions based on the effects that they will have on the employees. It allows the leaders to nurture and inspire a new generation of leaders.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When putting the empathy in practice, the managers and leaders need to be careful at one very critical aspect. Empathy is putting yourself in someone else’s shoes, however, that means to understand how THEY feel in their shoes and not how WE feel in their shoes.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the new era of work, successful leaders are doing their very best to practice empathy.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Empathy has three main components: cognitive empathy, affective empathy, and empathetic concern.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Cognitive empathy means recognizing that other people have their own way of seeing and thinking about the world. We don’t need to adopt their point of view but just understand it.&nbsp;</li><li>Affective empathy means recognizing how the other person feels and tapping into the emotion and feeling it with them.&nbsp;</li><li>Empathetic concern comes after you have understood the other person’s point of view and recognized how they feel. Acting with empathetic concerns involves adjusting your communication to welcome and support the other person.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Ultimately, practicing empathy can result in a smoother communication, more productive collaboration, and fewer conflicts.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4273,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/04/walk-in-other-peoples-shoes-1024x604.png" alt="how to be an empathetic leader" class="wp-image-4273"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="tips-for-how-to-be-an-empathetic-leader-from-afar">Tips for How to Be an Empathetic Leader From Afar</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Remote teams enable the possibility of working from the comfort of our homes. This benefit might be a bit problematic, when the leaders have to show more empathy. We have to keep in mind that every leader has their own way of leading and most importantly, their specific team to guide.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here you can find some useful tips that will come in handy when you lead a remote team:</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Listen First, and Build an Open Communication Culture</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Leaders believe that their main task is to inspire and motivate their team to do better. Even though this task is a very crucial one, they forget that the main task that they need to cover first is to listen.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>People want to be heard! Therefore, in any leader's agenda, there should be a quiet time, where they focus on listening to <a href="https://adevait.com/software/feedback-for-software-developers" target="_blank" rel="noreferrer noopener">employees' feedback</a>. </p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Never interrupt, while the employee is speaking. Take notes and then give out tips or even guidelines as to how it might be better for them.&nbsp;</li><li>Show the employee that you are listening by getting rid of all distractions, such as silencing your phone and putting away anything that can distract you from the conversation.</li><li>Maintain control over your body language when the employee is sharing information. Do not snap or raise your voice. </li><li>Ask clarifying questions and repeat back what the employee shared with you.</li><li>Express gratitude for the shared information. </li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Be Vulnerable and Show Compassion</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>A leader is a strong figure. They all believe that showing themselves as indestructible is the way of resonating strength. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Unfortunately, they miss one point: we are all human and we all have our bad days. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Being vulnerable doesn’t mean we are lacking strength, it actually means that we are strong enough to show those moments with the people we trust. And trust is the key to strong relationships.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Always make time to share some of your struggles or even mistakes, this will allow the others to open up freely. Listen carefully and show understanding while the others share their issues as well. During the meetings keep the camera open, this way people feel your presence and your attention towards them.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Look for Signs During Meetings</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Video conferencing is a very useful tool for remote work. While it is not the easiest to understand each other over a screen, it is one of the ways that can connect us when we are apart. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The managers can use this as a channel for decoding the employees' emotional states and the process of communication. Take some time and analyze what’s beyond the surface of the call. Don’t rush to conclusions, but instead appreciate the challenges that the others are facing.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you notice someone is getting distracted, not engaging, or doing something else instead, take action and dive deeper. Continue the communication further with them. Find out what has happened and offer them your attention. This is the best way to earn trust and build a positive outcome in the team.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Make Yourself Approachable</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You are a remote leader. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The reality is that employees can not just pop into your office every time they come across a problem.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Neither can they fly a thousand miles to see you in person. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But what they can do is send you a direct message in Slack or a quick email.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Make this easy for them. Have several communication channels open for your remote employees where they can connect with you and chat. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Remember, your goal is to make the other person feel comfortable and encouraged to communicate openly. Employees will grow to trust you more and share with you all kinds of information that can be vital for your company. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's end this article with a quote from Tim Cook who once said:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong><em>People will try to convince you that you should keep your empathy out of your career. Don’t accept this false premise.</em></strong></p>
<!-- /wp:paragraph --> ]]></description>
<category>Distributed Teams</category>
<author>Teuta Reci</author>
<pubDate>Tue, 06 Apr 2021 20:50:50 +0000</pubDate>
</item>
<item>
<title><![CDATA[ 4 Shopify Developer Skills and Examples of Their Practical Application ]]></title>
<link><![CDATA[ https://adevait.com/shopify/4-shopify-developer-skills-and-their-practical-application ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>When thinking about <a href="https://adevait.com/shopify" target="_blank" rel="noreferrer noopener">how to hire a Shopify developer</a>, there's a particular set of skills you would want the new talent to possess.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But do you know which skills in particular should you look for?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Luckily, we have the answer in the post below. Bear with me as we explore the top 4 Shopify developer skills you should look for when hiring new talent and see examples of their practical application.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What's more, if you're a Shopify developer who's looking to expand their set of skills, this post may pique your interest.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's dive in!</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"54c85bd9","classMigrate":true,"mappingHeaders":[true,true,false,true,false,true],"headerLinks":"[{\u0022tag\u0022:3,\u0022text\u0022:\u0022What Is Shopify?\u0022,\u0022link\u0022:\u0022what-is-shopify\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eWhat Is Shopify?\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022What Are the Top Skills Every Shopify Developer Must Have to Tackle a Project? \u0022,\u0022link\u0022:\u0022what-are-the-top-skills-every-shopify-developer-must-have-to-tackle-a-project\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eWhat Are the Top Skills Every Shopify Developer Must Have to Tackle a Project? \u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Top Shopify Developer Skills:\u0022,\u0022link\u0022:\u0022top-shopify-developer-skills\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eTop Shopify Developer Skills:\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Adding New Features to an Existing Shopify Store\u0022,\u0022link\u0022:\u0022adding-new-features-to-an-existing-shopify-store\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eAdding New Features to an Existing Shopify Store\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Migrating the E-commerce Store to Shopify\u0022,\u0022link\u0022:\u0022migrating-the-e-commerce-store-to-shopify\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eMigrating the E-commerce Store to Shopify\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Using Version Control for Shopify Theme Development\u0022,\u0022link\u0022:\u0022using-version-control-for-shopify-theme-development\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eUsing Version Control for Shopify Theme Development\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:4,\u0022text\u0022:\u0022How to Use Git Shopify Theme Development\u0022,\u0022link\u0022:\u0022how-to-use-git-shopify-theme-development\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eHow to Use Git Shopify Theme Development\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Integrating Ads\u0022,\u0022link\u0022:\u0022integrating-ads\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eIntegrating Ads\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Which Soft Skills Should They Possess?\u0022,\u0022link\u0022:\u0022which-soft-skills-should-they-possess\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eWhich Soft Skills Should They Possess?\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Conclusion\u0022,\u0022link\u0022:\u0022conclusion\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eConclusion\u003c/strong\u003e\u0022,\u0022level\u0022:0}]"} /-->
<!-- wp:heading -->
<h2 id="what-is-shopify"><strong>What Is Shopify?</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Shopify is simply a web application for creating online stores. It comes with lots of customizable “themes” that experts can tweak to suit their own branding requirements. Shopify is amazing because it can be used to sell either physical or digital products.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>An interesting thing about Shopify is that anyone with little or no coding experience and design skills before can simply jump on it and develop for themselves an online store. That’s not all, it runs on its own servers which means that there is no need for you to buy web hosting or get any software installed anywhere.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Shopify, as one of the best e-commerce platforms, provides you with all the necessary things like a payment processor, a blog, email marketing tools, templates, etc. for you to develop and market an online store. Though Shopify has a traditional content editor that lacks a drag-and-drop functionality. However, it comes with other important tools that you can use to customize the layout of crucial pages.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="what-are-the-top-skills-every-shopify-developer-must-have-to-tackle-a-project"><strong>What Are the Top Skills Every Shopify Developer Must Have to Tackle a Project?&nbsp;</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Every profession has its own set of skills that you must possess before it can be said that you are an expert on it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These are top Shopify challenges that question the proficiency level of every Shopify expert when tackling a task.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="top-shopify-developer-skills"><strong>Top Shopify Developer Skills:</strong></h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>Adding new features to an existing Shopify store.</li><li>Migrating the e-commerce store to Shopify.&nbsp;</li><li>Using version controls for Shopify theme development.</li><li>Integrating ads.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":4} -->
<h4 id="adding-new-features-to-an-existing-shopify-store"><strong>Adding New Features to an Existing Shopify Store</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Every experienced Shopify developer must know how to add a product to an already existing online store. They should also know how to update the price, availability, and the variants of a product.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To make this possible, all one needs to do is to go to their Shopify admin.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Navigate to “<strong>Products</strong> &gt; <strong>All Products”.&nbsp;</strong></li><li>Click on “<strong>Add Product”</strong> from the “<strong>Products”</strong> page.&nbsp;</li><li>Having done that, you can easily enter the title of your product together with the important <a href="https://help.shopify.com/en/manual/products/details" target="_blank" rel="noreferrer noopener">information</a>.&nbsp;</li><li>After ensuring that you have done all the above steps, all you finally need to do is to click “<strong>Save”</strong>.&nbsp;&nbsp;</li></ol>
<!-- /wp:list -->
<!-- wp:heading {"level":4} -->
<h4 id="migrating-the-e-commerce-store-to-shopify"><strong>Migrating the E-commerce Store to Shopify</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Anyone with an already built e-commerce website or running on a different e-commerce platform for their day-to-day business activities can consider putting their product details and other content to Shopify.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For this, you need a developer who can smoothly migrate your store to Shopify.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you're a Shopify developer, all you need to do is follow every step and information you find on <a href="https://help.shopify.com/en/manual/migrating-to-shopify/considerations" target="_blank" rel="noreferrer noopener">store migration considerations</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For store owners: Don’t forget that the unique way you set up your store has a lot to say about the steps you need in migrating it. In addition, your migration process can complicate if your store contains very large data in multiple sets.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4 id="using-version-control-for-shopify-theme-development"><strong>Using Version Control for Shopify Theme Development</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Using version control for theme development is another crucial skill any experienced Shopify developer should possess.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Version control is a class of systems in software engineering considered with the management of changes in computer programs, large websites, documents, or other gatherings of information. Top version control software tools include Git, SVN, Mercurial, CVS, and many more.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":5} -->
<h5><strong>How to Use Git Shopify Theme Development</strong></h5>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Not many people that have heard about Git know how to use it. Git is multidimensional and vast in terms of the way people use it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In general, version controls help in keeping track of every change we make to our codes in a different kind of database. And this is very helpful in the sense that all the important changes we make are well tracked to avoid unnecessary uncertainties from happening.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For an effective way of keeping track of every change you make using Git, a developer needs to work locally on the computer with Theme Kit instead of using the online code editor that could complicate things any time you choose to commit changes to GitHub.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The first thing you can do is to download a copy of your theme to your computer. How is this done? Go to the Shopify admin and click on “<strong>Online Store &gt; Themes &gt; Actions &gt; Download Theme File”</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Alternatively, run “<strong>theme download”</strong> inside the directory that is just created if you have already set up Theme Kit, and the directory you run the command is where your theme will be downloaded into. After you might have synced every change you make to the Git repository, the next thing to do is to initialize your local theme directory with Git.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After initializing Git in your theme folder, the next thing is to link your local directory with your GitHub repository. When you run the "<strong>git status”</strong> command, you will be able to see the file that is yet to be tracked by Git in your theme directory. Note that you can easily track that particular file by running the “<strong>git add”</strong> command.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another thing worth knowing is how to ignore files you don't want to track with Git: name a new file you have just created in your theme directory “<strong>.gitignore”. </strong>In this exact file, add the file type or specific file you desire to ignore together with the break lines for each of them.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Most importantly, always add and commit your “<strong>.gitignore”</strong>&nbsp;file to your repository as soon as possible. Lastly, you must commit frequently so that you can keep track of every change you make in a systematic order.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4 id="integrating-ads"><strong>Integrating Ads</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Using Facebook and Google ads is a great way to grow your business on Shopify. The launched Marketing in Shopify creates an avenue for you to create, launch and measure campaigns.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For this, you need a Shopify developer who can integrate ads into your store.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After that, you will be able to easily set up an ad on Shopify within the twinkle of an eye.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To your advantage, irrespective of whether it’s Google Smart Shopping campaign and Facebook ads you are running, Shopify does help in automatically populating ads with product images, titles, and descriptions from your store. You can track your results in Shopify immediately after your campaign is live.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="which-soft-skills-should-they-possess"><strong>Which Soft Skills Should They Possess?</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>First and foremost, a Shopify expert worth hiring needs to have in-depth knowledge about PHP, JavaScript, and jQuery. In addition to that, they must also understand and know how to work with Shopify APIs.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They must also be familiar with using version control for Shopify theme development.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Most importantly, in addition to hard skills, there are some <a href="https://adevait.com/blog/workplace/7-soft-skills-developers-2019" target="_blank" rel="noreferrer noopener">software developer soft skills</a> you should look for, including communication and teamwork skills. Above all, they must have an extensive portfolio and testimonials of happy clients for them to stand out among others.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="conclusion"><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>A good developer is the one with the Shopify skills we have carefully mentioned and provided practical examples for in this article. They follow trends and possess extensive knowledge about everything that has to do with Shopify development.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you're a Shopify developer who wants to improve her/his skills, here are 30 <a href="https://www.shopify.com/partners/blog/developer-resources" target="_blank" rel="noreferrer noopener">developer resources to diversify your skillset</a>.&nbsp;</p>
<!-- /wp:paragraph --> ]]></description>
<category>Shopify</category>
<author>Nikola Matkovski</author>
<pubDate>Fri, 02 Apr 2021 15:40:36 +0000</pubDate>
</item>
<item>
<title><![CDATA[ 7 How To's Every WordPress Developer Must Know ]]></title>
<link><![CDATA[ https://adevait.com/wordpress/7-how-tos-every-wordpress-developer-must-know ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>WordPress, an imperious easy-to-learn tool, requires a lot of mastered skills for anyone to be a professional in it. Being the most common Content Management System around, it's no brainer that lots of business owners are on the lookout for <a href="https://adevait.com/wordpress" target="_blank" rel="noreferrer noopener">WordPress developers for hire</a> so they can dominate the online market.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But what are the key WordPress how to’s business owners look for?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Aside from knowing the fundamentals of this important tool, you must also be proficiently skilled in using WordPress to create and develop themes, plugins, widgets, a complete website, and a web application through the use of REST API. You will need to be very good with HTML, CSS, PHP, MYSQL, JavaScript, AJAX, and jQuery before you can boldly say you are a WordPress expert.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>By becoming a WordPress developer, it’s your choice to either share your work for free via WordPress repositories or monetize it by finding clients. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this article, we will explain intensively all the essentials you need to know in order to become a proficient WordPress developer.</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"03f16c46","classMigrate":true,"mappingHeaders":[true,true,true,false,false,true]} /-->
<!-- wp:heading -->
<h2 id="wordpress-challenges-you-should-know-how-to-solve"><strong>WordPress Challenges You Should Know How to Solve</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In this section, we have made available for you some possible challenges you must be familiar with and their respective solutions:</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="nstall-wordpress"><strong>Install WordPress</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Installing WordPress is one of the simplest things to do – you are done with its installation in less than 5minutes. Most importantly, there are <a href="https://wordpress.org/support/article/before-you-install/" target="_blank" rel="noreferrer noopener">a few important things you need to pay attention to</a> before proceeding to installing WordPress.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>First and foremost, download and ensure you have a properly unzipped WordPress package. The next thing you have to do is to create an MYSQL database and user for WordPress on your web server.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Try as much as possible to configure the <strong>wp-config.php</strong>&nbsp;file without forgetting to upload WordPress files to your preferred location on your web server. Lastly, by simply having access to the URL in a browser, run the WordPress installation script.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="add-google-analytics"><strong>Add Google Analytics </strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Google analytics comes with advanced features to improve WordPress.com stats. Why is important to do this? If you care so much about how visitors get to your site then you would love everything about funnel reporting.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another interesting thing about Google analytics is its goal conversion that helps in measuring how a visitor complete tasks such as contact form, getting to the product page, etc.,&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To get started on how to make this happen, create an account on the <a href="http://www.google.com/analytics/" target="_blank" rel="noreferrer noopener">Google Analytics site</a>. And if you have used Google Analytics with other sites before, you can simply create a new account in your existing Google account.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>How do you create a new analytics profile? All you need to do is to click “<strong>Admin</strong>" in your google analytics account and click "<strong>Create Account</strong>” to simply have a new analytics profile.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once the aforementioned is properly done, the next thing is to fill the <strong>Property Name</strong>, <strong>Reporting Time Zone</strong>, and <strong>Currency</strong> in the Property Setup. Fill in your business details and click Create after completing everything in the Property Setup.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After all the above steps are done and dusted, you will be provided with your <strong>Measurement ID</strong>. Finally, to get your website connected to Google Analytics and start sending data to Google, copy and paste the whole Measurement ID from the Google Analytics site into the “<strong>Google Analytics Measurement ID</strong>” box.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="backup-wordpress-site"><strong>Backup WordPress Site</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Backing up your <a href="https://adevait.com/wordpress/optimizing-the-core-web-vitals" target="_blank" rel="noreferrer noopener">WordPress site</a> requires two parts: Files and Database. As you are planning to back up your entire website have it at the back of your mind that you are also going to need to backup your database too.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><em>What Differentiates a WordPress Site From a WordPress Database?</em></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>A WordPress site includes key features such as WordPress Core installation, WordPress plugins, WordPress themes Images and files, JavaScript, PHP, and other code files Additional files and static web pages. A WordPress database, on the other hand, exclusively comprises only your posts and lots of generated data on your site.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><strong><em>How Do You Backup Your Site?</em></strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Almost every host makes available software for backing up sites. You can check with your host to discover the service and programs they offer. Programs like WINSCP enable you to sync with your site so that you can have a mirror content copy on your server and hard drive up to date. You can easily compile these files to a folder on your PC many thanks to <a href="https://wordpress.org/support/article/ftp-clients/" target="_blank" rel="noreferrer noopener">FPT Clients</a> or <a href="https://codex.wordpress.org/UNIX%20Shell%20Skills" target="_blank" rel="noreferrer noopener">Unix Shell Clients</a>. You might want to save space by compressing them into a zip file and have more than one version of them. To simply backup your WordPress database, you can go with either <a href="https://wordpress.org/support/article/wordpress-backups/#plesk" target="_blank" rel="noreferrer noopener">Plesk</a>, <a href="https://wordpress.org/support/article/wordpress-backups/#cpanel" target="_blank" rel="noreferrer noopener">cPanel</a>, <a href="https://wordpress.org/support/article/wordpress-backups/#direct-admin" target="_blank" rel="noreferrer noopener">Direct Admin</a>, <a href="https://wordpress.org/support/article/wordpress-backups/#ensim" target="_blank" rel="noreferrer noopener">Ensim</a>, <a href="https://codex.wordpress.org/#vDeck" target="_blank" rel="noreferrer noopener">vDeck</a>, or <a href="https://wordpress.org/support/article/wordpress-backups/#ferozo" target="_blank" rel="noreferrer noopener">Ferozo</a>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="build-a-wordpress-site"><strong>Build a WordPress Site</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Do It Yourself! – you can easily build a WordPress site on your own within a short limited minute. Choosing WordPress as your site platform is the first step you have to accomplish when building a website on your own.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>After that, the next thing is to pick the name of your choice for your site, buy a domain and hosting. The more you interact with the platform the more you become very conversant with the WordPress UI.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You have to pick a theme/design that goes well for your website and get enough plugins to extend the functionalities and abilities of your site. Once you are done practicing the above-mentioned, you can proceed to create a basic page and consider starting a blog.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="update-php-in-wordpress"><strong>Update PHP in WordPress</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>PHP versions are getting updated every ear and there because of these two main reasons: security and speed. In other words, an updated PHP version is much faster, resource-friendly, and more secure than its predecessors.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To simply update the PHP version of your WordPress site, navigate to “<strong>Sites</strong>” and click the particular site you want to change the PHP version on. After that make a click on the “<strong>Tools</strong>” tab. Lastly, click on the drop-down and make a selection on your preferred PHP version under the “<strong>PHP Engine</strong>”.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You will definitely get a prompt after selecting the PHP version of your choice. In order to confirm the particular one you have chosen, click on the “<strong>Modify PHP version</strong>” button.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="increase-memory-limit"><strong>Increase Memory Limit</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>As WordPress overrides the memory_limit setting of PHP, you will have to edit the WordPress <strong>wp-config.php</strong> file in order to get the memory limit of your WordPress app increased.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>The location of the wp-config.php file...</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You will find the <strong>wp-config-</strong>PHP file in the public folder of your app at “<strong>apps/APPNAME/public”.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4><strong>How Do You Increase the Administrative Memory Limit?&nbsp;</strong></h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>For this particular one, WordPress does without the memory limit of PHP and does its own configuration. You must be ready to set WP_MAX_MEMORY_LIMIT in wp-config.php if you desire to change the memory limit to anything entirely different from 256MB.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, add “<strong>define('WP_MAX_MEMORY_LIMIT', '512M') ;</strong>” if you want to increase the memory to 512MB.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Open the <strong>wp-config.php</strong> file of your app and add “<strong>define('WP_MEMORY_LIMIT', '512M') ;</strong> ” if you care to increase the memory limit of your public-facing pages to 512MB. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="speed-up-your-site"><strong>Speed Up Your Site</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The importance of a highly-speedy WordPress site can’t be overemphasized. A WordPress developer must know how to make this happen because search engines rank a fast-loading site higher than the slow-loading ones. Any important reason is that every online buyer prefers sites that their pages load very fast within a second.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Only consider getting hosting from a better hosting provider and make sure you use a lightweight framework/theme. As you are reducing your image sizes, don't forget to minimize your CSS and JS files too.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In addition, make use of advanced caching mechanisms with a caching plugin and don’t hesitate to use CDN (Content Delivery Networks). Lastly, clean up your WordPress database, deactivate unwanted plugins, have minimalistic external scripts and enable GZIP compression.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="conclusion"><strong>Conclusion</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The best <a href="https://adevait.com/wordpress" target="_blank" rel="noreferrer noopener">WordPress developers for hire</a> know how to effortlessly perform the tasks we have mentioned above in the text. You won’t only attract the services of potential clients when you are skilled in all of them. The WordPress How-To’s would also make you stand out among other developers.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Related: </strong></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong><a href="https://adevait.com/laravel/laravel-overwriting-default-pagination-system" target="_blank" rel="noreferrer noopener">Laravel Pagination Example</a></strong></li><li><a href="https://adevait.com/wordpress/optimizing-the-core-web-vitals" target="_blank" rel="noreferrer noopener"><strong>Google Core Web Vitals</strong></a></li><li><strong><a href="https://adevait.com/laravel/using-corcel-in-laravel" target="_blank" rel="noreferrer noopener">Using Corcel in Laravel to CRUD Wordpress Data</a></strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph --> ]]></description>
<category>WordPress</category>
<author>Ivica Jangelovski</author>
<pubDate>Thu, 01 Apr 2021 18:50:34 +0000</pubDate>
</item>
<item>
<title><![CDATA[ How to Optimize the Core Web Vitals of Your WordPress Site ]]></title>
<link><![CDATA[ https://adevait.com/wordpress/optimizing-the-core-web-vitals ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>The Google Core Web Vitals update is coming in May 2021. We know this because Google <a href="https://developers.google.com/search/blog/2020/11/timing-for-page-experience" target="_blank" rel="noreferrer noopener">gave us a heads up on the next algorithm update</a> to help us prepare and adjust so that the site's organic traffic won't be lost. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Rarely has Google given such warnings before, but after 2020, many people depend on their business websites' functionality and visibility. Therefore, we are witnessing how Google tries to help us by explaining this scheduled update's essentials.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To ensure that your WordPress site is ready for the update, all <a href="https://adevait.com/wordpress" target="_blank" rel="noreferrer noopener">WordPress developers</a> need to go over the whole concept explained in this text and follow the optimization tips. Putting some extra work now will undoubtedly pay off later when the update takes place.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"f42f9ad5","classMigrate":true,"mappingHeaders":[true,true,false,false,false,false]} /-->
<!-- wp:uagb/table-of-contents {"block_id":"59fa6b2e","classMigrate":true,"mappingHeaders":[true,true,false,false,false,false],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Are Core Web Vitals?\u0022,\u0022link\u0022:\u0022what-are-core-web-vitals\u0022,\u0022content\u0022:\u0022What Are Core Web Vitals?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022A Closer Approach to the Core Web Vitals\u0022,\u0022link\u0022:\u0022a-closer-approach-to-the-core-web-vitals\u0022,\u0022content\u0022:\u0022A Closer Approach to the Core Web Vitals\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Loading (Largest Contentful Paint) Score\u0022,\u0022link\u0022:\u0022loading-largest-contentful-paint-score\u0022,\u0022content\u0022:\u0022Loading (Largest Contentful Paint) Score\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022How to Fix the LCP Score?\u0022,\u0022link\u0022:\u0022how-to-fix-the-lcp-score\u0022,\u0022content\u0022:\u0022How to Fix the LCP Score?\u0022,\u0022level\u0022:1},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Upgrade your web host plan\u0022,\u0022link\u0022:\u0022upgrade-your-web-host-plan\u0022,\u0022content\u0022:\u0022Upgrade your web host plan\u0022,\u0022level\u0022:2},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Get rid of unnecessary third-party scripts\u0022,\u0022link\u0022:\u0022get-rid-of-unnecessary-third-party-scripts\u0022,\u0022content\u0022:\u0022Get rid of unnecessary third-party scripts\u0022,\u0022level\u0022:2},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Remove large page elements\u0026nbsp;\u0022,\u0022link\u0022:\u0022remove-large-page-elements\u0022,\u0022content\u0022:\u0022Remove large page elements\u0026nbsp;\u0022,\u0022level\u0022:2},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Minify your CSS\u0022,\u0022link\u0022:\u0022minify-your-css\u0022,\u0022content\u0022:\u0022Minify your CSS\u0022,\u0022level\u0022:2},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Interactivity (First Input Delay) Score\u0022,\u0022link\u0022:\u0022interactivity-first-input-delay-score\u0022,\u0022content\u0022:\u0022Interactivity (First Input Delay) Score\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022How to Fix the FID Score?\u0022,\u0022link\u0022:\u0022how-to-fix-the-fid-score\u0022,\u0022content\u0022:\u0022How to Fix the FID Score?\u0022,\u0022level\u0022:1},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Minimise/defer JavaScript\u0022,\u0022link\u0022:\u0022minimisedefer-javascript\u0022,\u0022content\u0022:\u0022Minimise/defer JavaScript\u0022,\u0022level\u0022:2},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Remove third-party scripts you don't need\u0022,\u0022link\u0022:\u0022remove-third-party-scripts-you-dont-need\u0022,\u0022content\u0022:\u0022Remove third-party scripts you don't need\u0022,\u0022level\u0022:2},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Browser cache is a must\u0022,\u0022link\u0022:\u0022browser-cache-is-a-must\u0022,\u0022content\u0022:\u0022Browser cache is a must\u0022,\u0022level\u0022:2},{\u0022tag\u0022:5,\u0022text\u0022:\u0022For the Apache server:\u0022,\u0022link\u0022:\u0022for-the-apache-server\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eFor the Apache server:\u003c/strong\u003e\u0022,\u0022level\u0022:3},{\u0022tag\u0022:5,\u0022text\u0022:\u0022For the NGINNX Server:\u0022,\u0022link\u0022:\u0022for-the-nginnx-server\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eFor the NGINNX Server:\u003c/strong\u003e\u0022,\u0022level\u0022:3},{\u0022tag\u0022:2,\u0022text\u0022:\u0022VIsual Stability (Cumulative Layout Shift) Score\u0022,\u0022link\u0022:\u0022visual-stability-cumulative-layout-shift-score\u0022,\u0022content\u0022:\u0022VIsual Stability (Cumulative Layout Shift) Score\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022How to fix the CLS Score?\u0022,\u0022link\u0022:\u0022how-to-fix-the-cls-score\u0022,\u0022content\u0022:\u0022How to fix the CLS Score?\u0022,\u0022level\u0022:1},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Set size attribute dimensions for any media\u0022,\u0022link\u0022:\u0022set-size-attribute-dimensions-for-any-media\u0022,\u0022content\u0022:\u0022Set size attribute dimensions for any media\u0022,\u0022level\u0022:2},{\u0022tag\u0022:4,\u0022text\u0022:\u0022Ads elements should have a reserved space\u0022,\u0022link\u0022:\u0022ads-elements-should-have-a-reserved-space\u0022,\u0022content\u0022:\u0022Ads elements should have a reserved space\u0022,\u0022level\u0022:2},{\u0022tag\u0022:4,\u0022text\u0022:\u0022The new UI elements should be added below the fold\u0022,\u0022link\u0022:\u0022the-new-ui-elements-should-be-added-below-the-fold\u0022,\u0022content\u0022:\u0022The new UI elements should be added below the fold\u0022,\u0022level\u0022:2},{\u0022tag\u0022:2,\u0022text\u0022:\u0022How to Improve Core Web Vitals Altogether?\u0022,\u0022link\u0022:\u0022how-to-improve-core-web-vitals-altogether\u0022,\u0022content\u0022:\u0022How to Improve Core Web Vitals Altogether?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022To Sum Up\u0022,\u0022link\u0022:\u0022to-sum-up\u0022,\u0022content\u0022:\u0022To Sum Up\u0022,\u0022level\u0022:0}]"} /-->
<!-- wp:heading -->
<h2 id="what-are-core-web-vitals">What Are Core Web Vitals?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Core Web VItals, also known as web vitals, web core vitals, and Google web vitals, are the three factors: loading, interactivity, and visual stability that Google considers essential for the overall user experience of the website. These three factors have three specific page speed and user interaction measurements:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Largest Contentful Paint (LCP)</strong></li><li><strong>First Input Delay (FID)</strong></li><li><strong>Cumulative Layout Shift (CLS)</strong></li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>These three factors will be the main point around which the Google Core Web Vitals algorithm update will revolve and decide Google's page experience score. This score will make or break your website after the update is complete.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To check your current web core vitals data, go to your Google Search Console account and choose the "enhancement" section.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4298,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/04/web_vitals-1024x375.png" alt="" class="wp-image-4298"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="a-closer-approach-to-the-core-web-vitals">A Closer Approach to the Core Web Vitals</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>What is a good or bad score for each of the web vitals, and how can it be improved? Let's have a look.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="loading-largest-contentful-paint-score">Loading (Largest Contentful Paint) Score</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>It measures the perceived load speed of the page. To be more precise, it refers to the point when the main content is loaded according to the view of the actual user. Please note that the LCP speed metric is not like the other two, the TTB and First Contextual Paint, because the latter don't represent the user's viewpoint when opening a webpage. The LCP metric focuses solely on the importance of seeing and interacting with the page, which means it puts the sole focus on the user.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Google has very specific LCP guidelines:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>A Good score is 0-2 s loading time</li><li>Needs improvement is 2-4 s loading time</li><li>A Poor score is more than 4 s loading time</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>How to Fix the LCP Score</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are several things you can do to get rid of this problem.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Upgrade Your Web Host Plan</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>With a better web host plan, you will have a faster overall load time score, including the LCP. More specifically, there are two essential features of a web hosting plan that impacts the website speed and performance - the hard drive and the resources.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If the hard drive is a solid-state drive, you will get a much faster and more reliable service than the standard hard drive. This alone will get you better performance and a faster page load time.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A web host plan with better resources like more bandwidth and RAM will speed and better power your website. A dedicated server or a VPS rather than the shared server will also offer you many more resources and, consequently, a far better performance.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Get Rid of Unnecessary Third-Party Scripts</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Did you know that third-party scripts <a href="https://backlinko.com/page-speed-stats" target="_blank" rel="noreferrer noopener">slow down a page by 34ms</a>? That is why you need to remove all unnecessary third-party scripts. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These include ads, social media sharing buttons, video embeds, etc., whose role is to make the website more interactive, dynamic, and interlinked, but at the same time can pose a threat to slow down the page load time. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Not to be misunderstood — some of these third-party scripts are very important for the website's functionality or monetization. So, when I am talking about getting rid of third-party scripts, I am thinking about the unnecessary ones without which your website will be functional.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Therefore, here is what you need to do:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Decide which third-party scripts are necessary and which are unnecessary</li><li>Use fewer plugins</li><li>Use your own code solutions</li><li>Activate lazy-load third-party JS.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":4} -->
<h4>Remove Large Page Elements&nbsp;</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To check whether your website has an element that is slowing down the LCP on the page, go to <a href="https://developers.google.com/speed/pagespeed/insights/" target="_blank" rel="noreferrer noopener">Google PageSpeed Insights</a>, enter the URL of your website, and see the diagnostics section's result.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4299,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/04/page_speed-1024x725.png" alt="" class="wp-image-4299"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Remove all the large files that are causing the slowing down.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Minify Your CSS</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To minify your CSS on your WordPress Page, you can use the <a href="https://wordpress.org/plugins/bwp-minify/" target="_blank" rel="noreferrer noopener">Better WordPress Minify </a>plugin, which will show as a menu item upon installation. Click on it to go to the settings page and check the first two options to perform an automated minification of JS and CSS files on your WordPress site.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":4301,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/04/minify_css-1024x308.png" alt="" class="wp-image-4301"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="interactivity-first-input-delay-score">Interactivity (First Input Delay) Score</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The second of the three Google Core Web Vitals is the First Input Delay factor, and it refers to your website's interactivity score. More precisely, the FID measures the time the user spends to actually interact with the page (interactions including choosing an option from a menu, clicking on a navigational link, submitting your email, opening "accordion text" on other devices.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is an essential factor because Google evaluates how real-life users interact with websites, and the results directly influence the user experience of that website.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Again, there are specific guidelines by Google for a perfect FID score:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Good score &lt;100 ms&nbsp;</li><li>Needs improvement 100-300 ms</li><li>Poor score &gt;300 ms</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>This score is especially important for a login page, sign-up page, or any other type of page where users are expected to click on something, whereas for content-based pages, the FID score is not that important.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>How to Fix the FID Score</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>First, you need to check your FID Score. You can do that by using one of the following field tools: <a href="https://developers.google.com/web/tools/chrome-user-experience-report" target="_blank" rel="noreferrer noopener">Chrome User Experience Report</a>, PageSpeed Insights, the Core Web Vitals Report from the Search Console, and through the web vitals from the JavaScript library.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now, to fix the FID score, you need to do the following activities.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Minimise/Defer JavaScript</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Website visitors won't be able to interact with the page while at the same time the browser is loading up JS. So, what you need to do is minimize or defer JS on your page. To do so, you can use the Better WordPress Minify plugin mentioned in the previous section, or you can check other plugins or online tools.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Remove Third-Party Scripts You Don't Need</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Again, remove plugins and other third-party scripts that are not key to your site's functionality. These, apart from impacting the LCP score, can negatively impact the FID score as well.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Browser Cache Is a Must</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Your content will load faster by having a browser cache because the visitor's browser will scan over the JS loading tasks much quicker. To enable browser caching in WordPress, you need to put a bit of code in the .htacess file. Here is how:</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":5} -->
<h5><strong>For the Apache server:</strong></h5>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li><strong>Access the website files</strong></li><li><strong>Add this browser caching code in the .htacess file</strong></li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>#Customize expires cache start - adjust the period according to your needs
&lt;IfModule mod_expires.c&gt;
FileETag MTime Size
AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript
ExpiresActive On
ExpiresByType text/html "access 600 seconds"
ExpiresByType application/xhtml+xml "access 600 seconds"
ExpiresByType text/css "access 1 month"
ExpiresByType text/javascript "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/javascript "access 1 month"
ExpiresByType application/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresDefault "access 1 month"
&lt;/IfModule&gt;
#Expires cache end
</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li><strong>Add cache-control headers via Apache:</strong></li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code># BEGIN Cache-Control Headers</code></pre>
<!-- /wp:code -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&lt;IfModule mod_expires.c&gt;
&lt;IfModule mod_headers.c&gt;
&lt;filesMatch "\.(ico|jpe?g|png|gif|swf)$"&gt;
Header append Cache-Control "public"
&lt;/filesMatch&gt;
&lt;filesMatch "\.(css)$"&gt;
Header append Cache-Control "public"
&lt;/filesMatch&gt;
&lt;filesMatch "\.(js)$"&gt;
Header append Cache-Control "private"
&lt;/filesMatch&gt;
&lt;filesMatch "\.(x?html?|php)$"&gt;
Header append Cache-Control "private, must-revalidate"
&lt;/filesMatch&gt;
&lt;/IfModule&gt;
&lt;/IfModule&gt;
</code></pre>
<!-- /wp:code -->
<!-- wp:list -->
<ul><li>Turn Etags off&nbsp; by adding this piece of code</li></ul>
<!-- /wp:list -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&lt;IfModule mod_headers.c&gt;
Header unset ETag
&lt;/IfModule&gt;
FileETag None
</code></pre>
<!-- /wp:code -->
<!-- wp:heading {"level":5} -->
<h5><strong>For the NGINX Server:</strong></h5>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The pieces of code are a bit different for this type of a server simply because there isn’t a .htaccess file. What you need to do instead is go to /etc/nginx/sites-enabled/default and paste this code:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
location ~* \.(pdf)$ {
expires 30d;
}
}
Add Cache-Control Headers (NGINX)
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 90d;
add_header Cache-Control "public, no-transform";
}
</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2 id="visual-stability-cumulative-layout-shift-score">Visual Stability (Cumulative Layout Shift) Score</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The final of the three Google web vitals is the CLS score, which gives insight into whether the annoying and unexpected page content movement is prevented. Or, in simpler terms, the CLS score shows how stable a page is while loading. This means that if the page's elements move around as the page loads, your CLS score will be high - which is pretty bad.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The specific criteria by Google for this core web vital is:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Good score &gt;0.1</li><li>Needs improvement 0.1-0.25</li><li>Poor score &gt;0.25&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>How to Fix the CLS Score</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To check your CLS score, use the Chrome User Experience Report, the PageSpeed Insights tool, or the Core Web Vitals report by the Search Console.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To fix it, do the following activities.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Set Size Attribute Dimensions for Any Media</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Your video, images, GIFs, infographics, etc., must have a predetermined size dimension so that the user's browser can figure out exactly how much space the elements will take up on the page. And the best of all is that it won't change it while in motion as the page loads completely.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>Ads Elements Should Have a Reserved Space</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>By ensuring this, the ads won't pop suddenly up on the page and push the content down or to the side.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":4} -->
<h4>The New UI Elements Should Be Added Below the Fold</h4>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Hence, the new UI elements won't push the content where the user doesn't expect it to appear.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="how-to-improve-core-web-vitals-altogether">How Can You Improve Core Web Vitals Altogether?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>As you've read so far, each factor can be approached and dealt with individually. However, there are several actions you can take to improve the scores altogether. Here are some of them.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Make sure the above-the-fold content loads fast</li><li>Minimize long tasks to optimize main thread activity</li><li>Make sure the mobile responsiveness is fast</li><li>Check the security of your website looking for issues</li><li>Serve forms &amp; embedded resources over HTTPS</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="to-sum-up">To Sum Up</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Optimizing the Core Web Vitals should be your priority before the Google Algorithm Update rolls out. That way, you will make sure that your WordPress website will be ready to tackle the outcome of the new update and maintain its rankings and positions on the Search Engine Page Results. Given that Google warned us about the upcoming update back in May 2020, now is the best time to take action and improve the scores of the three Google web core vitals.&nbsp;&nbsp;</p>
<!-- /wp:paragraph --> ]]></description>
<category>WordPress</category>
<author>Milan Savov</author>
<pubDate>Thu, 25 Mar 2021 10:08:58 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Functional and Non-Functional Requirements: Differences and Best Practices ]]></title>
<link><![CDATA[ https://adevait.com/software/functional-non-functional-requirements ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>The end goal of every project across all industries is the same: build a high-quality product that appeals to the customer.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But here's the catch:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In order to build a high-quality product, everyone in the process needs to understand their requirements clearly.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For instance, unclear functional requirements can lead to poorly defined scope.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On the other hand, ignoring non-functional requirements can greatly lower the quality of the product.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The truth is that delivering high-quality software is a delicate process that takes time, skills, and proper communication between different stakeholders.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But what exactly is the difference between functional and non-functional requirements? How are they written? And most importantly, what are some of the best practices when writing your requirements?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Bear with me because I'm going to answer all of these questions in the post below.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's get started!&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"c794a878","classMigrate":true,"mappingHeaders":[true,true,false,true,true,true],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Are Functional Requirements?\u0022,\u0022link\u0022:\u0022what-are-functional-requirements\u0022,\u0022content\u0022:\u0022What Are Functional Requirements?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Are Non-Functional Requirements?\u0022,\u0022link\u0022:\u0022what-are-non-functional-requirements\u0022,\u0022content\u0022:\u0022What Are Non-Functional Requirements?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Is the Difference Between Functional and Non-Functional Requirements?\u0022,\u0022link\u0022:\u0022what-is-the-difference-between-functional-and-non-functional-requirements\u0022,\u0022content\u0022:\u0022What Is the Difference Between Functional and Non-Functional Requirements?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022How Are Functional and Non-Functional Requirements Written?\u0022,\u0022link\u0022:\u0022how-are-functional-and-non-functional-requirements-written\u0022,\u0022content\u0022:\u0022How Are Functional and Non-Functional Requirements Written?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Requirements Specification Document\u0022,\u0022link\u0022:\u0022requirements-specification-document\u0022,\u0022content\u0022:\u0022Requirements Specification Document\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Use Cases\u0022,\u0022link\u0022:\u0022use-cases\u0022,\u0022content\u0022:\u0022Use Cases\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022User Stories\u0026nbsp;\u0022,\u0022link\u0022:\u0022user-stories\u0022,\u0022content\u0022:\u0022User Stories\u0026nbsp;\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Functional Decomposition\u0026nbsp;\u0022,\u0022link\u0022:\u0022functional-decomposition\u0022,\u0022content\u0022:\u0022Functional Decomposition\u0026nbsp;\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Are Some of the Best Practices?\u0026nbsp;\u0022,\u0022link\u0022:\u0022what-are-some-of-the-best-practices\u0022,\u0022content\u0022:\u0022What Are Some of the Best Practices?\u0026nbsp;\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Final Word\u0022,\u0022link\u0022:\u0022final-word\u0022,\u0022content\u0022:\u0022Final Word\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-c794a878" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#what-are-functional-requirements">What Are Functional Requirements?</a></li><li><a href="#what-are-non-functional-requirements">What Are Non-Functional Requirements?</a></li><li><a href="#what-is-the-difference-between-functional-and-non-functional-requirements">What Is the Difference Between Functional and Non-Functional Requirements?</a></li><li><a href="#how-are-functional-and-non-functional-requirements-written">How Are Functional and Non-Functional Requirements Written?</a></li><li><a href="#what-are-some-of-the-best-practices">What Are Some of the Best Practices?&nbsp;</a></li><li><a href="#final-word">Final Word</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="what-are-functional-requirements">What Are Functional Requirements?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Functional requirements form the behavior of the system. If someone is giving you functional requirements for a project, they're giving you information on how the project's product is going to work. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These requirements describe the interactions between a system and its environment.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's say that you already have a product that's out on the market, called Product 1.0. Now, your project is to work on Product 2.0. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The new features of the Product 2.0 would be functional requirements. The bugs that you will be fixing from Product 1.0 are also your functional requirements. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The new behavior you're building in the product is also a functional requirement.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="what-are-non-functional-requirements">What Are Non-Functional Requirements?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Non-functional requirements, also known as quality attributes, describe the general software characteristics.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The list of primary non-functional requirements includes:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Usability</strong>: the ability of a user to easily interact with a product</li><li><strong>Reliability</strong>: the product should be secure enough to handle users' sensitive information</li><li><strong>Performance</strong>: how a product reacts to user's actions&nbsp;</li><li><strong>Error handling</strong>: how the product handles errors&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>For example, let's say that your <a href="https://adevait.com/laravel" target="_blank" rel="noreferrer noopener">Laravel developers</a> are building a ride-hailing app. One implicit expectation from the app is to load as soon as possible. When users land on your app, they shouldn't wait 5 minutes for the app's content to load.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="what-is-the-difference-between-functional-and-non-functional-requirements">What Is the Difference Between Functional and Non-Functional Requirements?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The major difference between functional and non-functional requirements is that functional requirements explain <em>What</em> the system does, while non-functional requirements explain <em>How</em> the system works.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Functional requirements are easier to define as they're driven by the business idea. They involve all the features of the project and the ways users engage with those features.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On the other hand, non-functional requirements are driven by experience. The best way to identify non-functional requirements is to analyze your product's performance and make it useful and convenient for users.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To draw a line between functional and non-functional requirements, it'll be simpler to look at an example. We'll take Instagram as an example and assume how a development team would write their documentation.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Functional requirements:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>User stories</strong>: Instagram users want to upload image and video content, write captions, and publish the update. They also want to react to content published by other accounts.&nbsp;</li><li><strong>Use cases</strong>: when a user opens their Instagram, the first page is the feed. Here, the user can interact with the content, leaving likes and comments.&nbsp;</li><li><strong>Additional functionality</strong>: push notifications, automated location tagging, automated expiration of user stories, photo filters, search bars, etc.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Non-functional requirements:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Performance</strong>: content loading is a priority as users spend more time viewing content than uploading content.</li><li><strong>Usability</strong>: users should be able to intuitively navigate between profiles and their subscriptions.</li><li><strong>Reliability and scalability</strong>: the system should work well in low-latency conditions, showing media content with the smallest delay possible.</li><li><strong>Safety</strong>: Instagram has detailed authentication protocols, photo upload, API integration, photo embedding, and encryption of direct messages.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="how-are-functional-and-non-functional-requirements-written">How Are Functional and Non-Functional Requirements Written?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There are a few different ways to write functional and non-functional requirements. Here are the most common:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Requirements Specification Document</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This document is one way to formalize functional and non-functional requirements. It describes the functions and capabilities the product must provide. It can also contain constraints and assumptions. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The document is usually written in a textual form, although it's recommended it contains visual elements as well so that non-technical stakeholders understand the scope.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A requirements specification document generally contains the following elements:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Purpose (definitions, system overview, and background)</li><li>Overall description (assumptions, constraints, business rules, and product vision)</li><li>Specific requirements (system attributes, functional requirements, database requirements)</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Use Cases</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Use case document is a document that describes the interactions between the system and the external users in a generalized, impartial way. It's a written description of how users will perform tasks in the system. It outlines a system's behavior as it responds to a request. Each use case contains a sequence of steps, starting with a user's goal and finishing when that goal is completed.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>User Stories&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>User stories describe the functionality from the perspective of the end-user. They include what exactly the end-user wants the system to do. <a href="https://adevait.com/software/estimations-the-other-way" target="_blank" rel="noreferrer noopener">Agile teams</a> organize user stories in a backlog, which is an ordered list of product functions.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, a user story may be the following:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong><em>As Jane, I want to invite my friends to join the app to experience it together.&nbsp;</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Functional Decomposition&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Functional decomposition is a document in which complex functionality is broken down into structural parts. This document aims to help simplify the development process early on and <a href="https://adevait.com/software/estimations-the-other-way" target="_blank" rel="noreferrer noopener">estimate project duration and costs</a>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example,</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Reserve a room -&gt; Log in -&gt; Select hotel and date -&gt; Confirm reservation</strong></p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="what-are-some-of-the-best-practices">What Are Some of the Best Practices?&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Requirements should be clear and easy to understand</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Whether it's a use case or a functional decomposition, requirements should be written in a way that is clear and easy to understand. Keep in mind that some stakeholders won't be well-versed in the technological language, making the document as easy to understand as possible. Always choose the active voice over the passive and keep your sentences short.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Requirements should be written accurately.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Make sure your requirements document is written accurately, using consistent terminology and format. Avoid giving irrelevant information that may just confuse the reader.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Use requirement imperatives correctly.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Many requirements documents contain imperatives such as "shall," "will," and "should." Some people will say that "shall" is a requirement, while others that "should" and "must" is a requirement. Your company should outline what each of these means and how to use them correctly when writing requirements.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Don’t use weak phrases and subjective words.</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For instance, if you write "something bad happened to the system," "something bad" can mean different things to different people. It's critical not to use these words. If you use them, make sure they're going to be interpreted in the same way by everyone.</p>
<!-- /wp:paragraph -->
<!-- wp:table {"hasFixedLayout":true,"className":"is-style-stripes"} -->
<figure class="wp-block-table is-style-stripes"><table class="has-fixed-layout"><tbody><tr><td><strong>Functional Requirement&nbsp;</strong></td><td><strong>Non-functional Requirements</strong></td></tr><tr><td>- Functional requirements form the behavior of the product.</td><td>- Non-functional requirements describe the general software characteristics.</td></tr><tr><td>- They explain “What the system does.”</td><td>- They explain “How the system works.”</td></tr><tr><td>- Helps you verify the functionality of the software.</td><td>- Helps you verify the performance of the software.</td></tr><tr><td>- They are captured in use cases.</td><td>- They are captured as a quality attribute.</td></tr><tr><td>- Easy to define.</td><td>- Difficult to define.</td></tr><tr><td>- Focus on user requirement.</td><td>- Focus on the user's expectation and experience.</td></tr><tr><td><br>- Examples (Netflix):<br><br>Users should be able to play any video by pushing the play button. The platform’s search bar should allow users to filter results by genres. The platform frequently updates the suggestions list by using data analytics. </td><td>- Examples (Netflix):<br><br>The interface should be desktop and mobile friendly. Every user should fill a form with personal details and provide financial data for paid subscriptions. The platform should comply with copyright laws. </td></tr></tbody></table></figure>
<!-- /wp:table -->
<!-- wp:heading -->
<h2 id="final-word">Final Word</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Knowing the difference between functional and non-functional requirements can be challenging. But understanding the difference can also set up the foundation for a successful project.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Remember that both requirements are equally vital, despite the name one of them carries. After all, a website can meet its functional requirement to load in 30 seconds, but it will still be unusable.&nbsp;</p>
<!-- /wp:paragraph --> ]]></description>
<category>Software</category>
<author>Tosho Trajanov</author>
<pubDate>Mon, 15 Mar 2021 12:04:29 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Improving Software Engineering Velocity ]]></title>
<link><![CDATA[ https://adevait.com/software/improving-software-engineering-velocity ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>Software engineering velocity is a metric that measures the amount of work a team completes during a sprint. But what do you do when you notice a development velocity problem at your company? I'll share my experiences in this post below.&nbsp;</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You've implemented and have been following all of the “<a href="https://adevait.com/blog/agile-work/agile-processes-distributed-teams" target="_blank" rel="noreferrer noopener">agile best practices</a>”. You're doing retrospectives, daily standups, and sprint planning. <a href="https://adevait.com/software" target="_blank" rel="noreferrer noopener">Your engineers are spectacular</a>, and you're using all the top-notch tools.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Despite this, you and your team often find yourself stuck in a project that takes too long to complete.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What may be the root cause of this?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You may not want to hear it, but here it goes: <strong>there's a high chance the fault is not to be found in a single source</strong>. It's not your engineers. Or your tools. It's definitely not in the remote nature of your company.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Instead, it's a set of interconnected elements that may be contributing to the slowness of your team or the quality of your products.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this story, I'll try to share a few tips on how to get a better and more consistent velocity from your engineering team without overworking them. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As a CTO with years of experience managing teams of engineers, I have found that the issues I'll mention in the text are the most common when working on a development project. I'll share my experience of how we have handled these types of issues in our company.</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"f39fb613","classMigrate":true,"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022Why Should We Care About Software Engineering Velocity?\u0022,\u0022link\u0022:\u0022why-should-we-care-about-software-engineering-velocity\u0022,\u0022content\u0022:\u0022Why Should We Care About Software Engineering Velocity?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022How Can We Detect a Velocity Problem?\u0022,\u0022link\u0022:\u0022how-can-we-detect-a-velocity-problem\u0022,\u0022content\u0022:\u0022How Can We Detect a Velocity Problem?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Can You Do?\u0026nbsp;\u0022,\u0022link\u0022:\u0022what-can-you-do\u0022,\u0022content\u0022:\u0022What Can You Do?\u0026nbsp;\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Set Expectations\u0022,\u0022link\u0022:\u0022set-expectations\u0022,\u0022content\u0022:\u0022Set Expectations\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Test Rigorously\u0026nbsp;\u0022,\u0022link\u0022:\u0022test-rigorously\u0022,\u0022content\u0022:\u0022Test Rigorously\u0026nbsp;\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Set Up a Fast Recovery Process\u0022,\u0022link\u0022:\u0022set-up-a-fast-recovery-process\u0022,\u0022content\u0022:\u0022Set Up a Fast Recovery Process\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Help Engineers See the Impact of Their Work\u0022,\u0022link\u0022:\u0022help-engineers-see-the-impact-of-their-work\u0022,\u0022content\u0022:\u0022Help Engineers See the Impact of Their Work\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Organize Engineers Into Functional Teams\u0022,\u0022link\u0022:\u0022organize-engineers-into-functional-teams\u0022,\u0022content\u0022:\u0022Organize Engineers Into Functional Teams\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Make Smaller Pull Requests\u0026nbsp;\u0022,\u0022link\u0022:\u0022make-smaller-pull-requests\u0022,\u0022content\u0022:\u0022Make Smaller Pull Requests\u0026nbsp;\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Key Takeaways\u0022,\u0022link\u0022:\u0022key-takeaways\u0022,\u0022content\u0022:\u0022Key Takeaways\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-f39fb613" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#why-should-we-care-about-software-engineering-velocity">Why Should We Care About Software Engineering Velocity?</a></li><li><a href="#how-can-we-detect-a-velocity-problem">How Can We Detect a Velocity Problem?</a></li><li><a href="#what-can-you-do">What Can You Do?&nbsp;</a></li><ul class="uagb-toc__list"><li><a href="#set-expectations">Set Expectations</a></li><li><a href="#test-rigorously">Test Rigorously&nbsp;</a></li><li><a href="#set-up-a-fast-recovery-process">Set Up a Fast Recovery Process</a></li><li><a href="#help-engineers-see-the-impact-of-their-work">Help Engineers See the Impact of Their Work</a></li><li><a href="#organize-engineers-into-functional-teams">Organize Engineers Into Functional Teams</a></li><li><a href="#make-smaller-pull-requests">Make Smaller Pull Requests&nbsp;</a></li></ul><li><a href="#key-takeaways">Key Takeaways</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="why-should-we-care-about-software-engineering-velocity">Why Should We Care About Software Engineering Velocity?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Team leaders (or CTOs and Engineering Managers) should care about engineering team velocity because it's a perfect planning method. It can make delivery dates more predictable and allow the company to prioritize projects and milestones, and set customer/end-user expectations.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can see velocity as a unit of work/time. The higher the number, the more milestones you can reach in a given amount of time.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Software engineering velocity is also an effective tool for detecting organizational inefficiencies. However, it's best if you don't use it&nbsp;as a sole tool for measuring overall engineering efficiency.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="how-can-we-detect-a-velocity-problem">How Can We Detect a Velocity Problem?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The best way to identify engineering velocity issues is to look at the entire organization. Ask yourself the following questions:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Are you getting plenty of interruptions, such as meetings, helping engineers, urgent code reviews, etc.?</li><li>Do you often need to revisit requirements for more clarification (undefined edge cases, unexpected design issues, missing requirements, scope creep?)</li><li>Are you missing any resources that can speed up development, such as documentation, clean code, better architecture, better tools, faster machines, etc.?</li><li>Do you often have to delay progress due to another team or department?</li><li>Are there any challenges that stem from a lack of consensus within your team? (loose or undefined architectural guidelines, not everyone on the same page, or conflicts about how something should be done?)</li><li>Does the organization handicap engineering? (years-long backlog of tech debt, no time allotted to keep dependencies, unable to use new components/architecture, imbalance where too many juniors require more attention from few seniors/leads?)</li><li>Can you notice a lack of motivation and engagement from engineers in your meetings?</li><li>Does the team want to see the impact of their work?</li></ol>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="what-can-you-do">What Can You Do?&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3 id="set-expectations">Set Expectations</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong><em>If engineers don't understand the scope of the work.</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You expect everyone on the team to understand the big picture and what good code looks like. Failing to do so might result in burning cycles on unnecessary or useful work.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>So, make sure you set expectations right with your engineers in terms of the scope and features of the project. Once everyone on the team has a clear understanding of the problem, they'll be better equipped to build the right thing, in the right way.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="test-rigorously">Test Rigorously&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong><em>If you are faced with regular code errors.&nbsp;</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For many strong companies, automated testing is a cornerstone of engineering processes. Engineering teams rely heavily on automated checks to inspect whether the software they're building meets the quality level that's expected by customers and stakeholders.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Automated testing can be regarded as an investment in preventing future unwanted and unexpected costs. By utilizing automated tests on every move, your team will be able to catch bugs and get rid of them before the software goes into production.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Even better, your engineers will finally have the mental room to focus on more important decisions than catching bugs.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="set-up-a-fast-recovery-process">Set Up a Fast Recovery Process</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong><em>If bugs find their way into production.&nbsp;</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The sad truth is that even if you have the best test suites in place, issues will inevitably find their way into production.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As there's a significant difference between mitigating an outage in five or fifty minutes, you and your team must be prepared for this scenario beforehand.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Having a fast recovery process in place is one of the most effective strategies for dealing with a broken software application or system.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In fact, many of the best companies such as Dropbox, Facebook, and Google have well-defined recovery processes such as assigning on-call engineers and runbooks.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://increment.com/on-call/when-the-pager-goes-off/" target="_blank" rel="noreferrer noopener">One study conducted by Stripe</a> found that many of these companies follow similar incident response processes. They decide to mitigate before they resolve. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Meaning, when an incident occurs, the on-call engineers mitigate the impact the incident is having on internal and external clients without even root-causing. Once the incident is mitigated, the engineers work to determine the root causes and then work on a solution.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Debugging is time-consuming, and it can be costly. Mitigating reduces the impact of the incident and saves the company a great deal of money.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="help-engineers-see-the-impact-of-their-work">Help Engineers See the Impact of Their Work</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong><em>If engineers are unmotivated.&nbsp;</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Software engineers want to do meaningful work. If they don't see the impact of their work, they may, in turn, become detached and disengaged.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you want to motivate your team to give their 100%, you should lead in a way that helps them see the meaning of the value you're delivering.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, some companies have their engineers sit in a tech support chair to support customers. This can help developers understand how the product gets used by customers.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Even if it's just for a few weeks, seeing how people are using the product they've developed can be a <a href="https://adevait.com/blog/remote-work/remote-teams-employee-morale" target="_blank" rel="noreferrer noopener">huge boost to morale</a> and motivation to do even better.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="organize-engineers-into-functional-teams">Organize Engineers Into Functional Teams</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong><em>If there are regular conflicts.&nbsp;</em></strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In my experience, smaller sized teams of 4 to 7 members is the ideal team structure. If you're a larger company, hire the number of engineers you need and divide them into several small cross-functional teams led by a team lead.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It's more productive to have an independent team of five developers than a dysfunctional team of 10 that doesn't have context into what others are doing.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Each team can attend daily standups where they will share their work and discuss any existent conflicts.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="make-smaller-pull-requests">Make Smaller Pull Requests&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>If engineers are bothered by complicated processes.&nbsp;</strong></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Break your work into smaller pieces to speed up your review time. Smaller pull requests are faster to review, push, and they can speed up the product development process.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On the other hand, large pull requests take longer to be reviewed and can demotivate the reviewer. Also, the larger the pull request, the less chance it will pass the initial code review, meaning it will need to go through several code reviews.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There's also the risk that the requirements will change before the code is released or halt other stories in the sprint and mess up the schedule.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This will cost plenty of money.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With that being said, a good pull request should not have more than 250 lines of code, although the number can vary from one team to another.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Find your team's optimal pull request size by doing experiments and keeping track of the changes in your velocity.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3953,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2021/01/Screenshot_1.png" alt="pull requests" class="wp-image-3953"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="key-takeaways">Key Takeaways</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>When project speed at your company goes slow, the easiest way is to blame it on the software engineers.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In reality, it's not that simple.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There can be a number of factors contributing to your slow velocity, starting from disengagement and unclear expectations to large pull requests and dysfunctional teams.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The first thing you want to do is get to the root cause of the problem. Once you find what's blocking your progress, you can continue implementing the needed measures to speed up your software engineering velocity.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You may be required to divide your sizable dysfunctional team of 10 into two teams of five engineers or implement more rigorous testing. In some cases, you may also need to establish a fast and reliable recovery process in place.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Hopefully, this post gave you clear and straightforward instructions on how to boost your team engineering velocity and ultimately manage to ship software with precision, speed, and quality.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Software</category>
<author>Tosho Trajanov</author>
<pubDate>Fri, 29 Jan 2021 14:03:21 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Here's Why Mental Health Will Be a Key Player in the Future of Work ]]></title>
<link><![CDATA[ https://adevait.com/blog/future-of-work/mental-health-future-of-work ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>The world of work is rapidly changing. From March 2020 and onward, billions of people have been affected by the devastating pandemic. The whole world went on lockdown, and by the end of April 2020, 1.6 billion workers lived with the fear of losing everything. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Businesses—in an attempt to survive the "apocalypse"—shifted to <a href="https://adevait.com/guides/distributed-teams" target="_blank" rel="noreferrer noopener">remote work</a>. Employees—used to the sounds of the coffee machine and keyboard typing sounds—were encouraged to work from their homes. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This was the "new normal," and everyone had to adapt to it in order to survive.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But in addition to a change in our working environment, people have also experienced a change in their well-being.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Even before the pandemic, people's mental health was already cracking. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Around 60% of 18 to 34 year-olds in the UK said they often feel lonely. In the US, 46% of the entire population feels lonely regularly.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Lockdowns and social isolation only made things worse.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As an issue worth investigating, in this post, we'll dive deep into the concept of mental health and see how it can be critical in the future of work. We'll touch upon why self-care makes better leaders and offer a few tips on how employers can instill mental health into the company culture.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s jump right into it!&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"80eaa824","classMigrate":true,"mappingHeaders":[true,true,false,true,true,true],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Is Mental Health?\u0022,\u0022link\u0022:\u0022what-is-mental-health\u0022,\u0022content\u0022:\u0022What Is Mental Health?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Mental Health Helps Reduce Burnouts\u0022,\u0022link\u0022:\u0022mental-health-helps-reduce-burnouts\u0022,\u0022content\u0022:\u0022Mental Health Helps Reduce Burnouts\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022What Can Employers Do?\u0022,\u0022link\u0022:\u0022what-can-employers-do\u0022,\u0022content\u0022:\u0022What Can Employers Do?\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Self-Care Makes Better Future Leaders\u0022,\u0022link\u0022:\u0022self-care-makes-better-future-leaders\u0022,\u0022content\u0022:\u0022Self-Care Makes Better Future Leaders\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022What Can Leaders Do?\u0022,\u0022link\u0022:\u0022what-can-leaders-do\u0022,\u0022content\u0022:\u0022What Can Leaders Do?\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022The World of Work May Change Forever\u0022,\u0022link\u0022:\u0022the-world-of-work-may-change-forever\u0022,\u0022content\u0022:\u0022The World of Work May Change Forever\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022What Does This Mean?\u0022,\u0022link\u0022:\u0022what-does-this-mean\u0022,\u0022content\u0022:\u0022What Does This Mean?\u0022,\u0022level\u0022:1}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-80eaa824" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#what-is-mental-health">What Is Mental Health?</a></li><li><a href="#mental-health-helps-reduce-burnouts">Mental Health Helps Reduce Burnouts</a></li><li><a href="#self-care-makes-better-future-leaders">Self-Care Makes Better Future Leaders</a></li><li><a href="#the-world-of-work-may-change-forever">The World of Work May Change Forever</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="what-is-mental-health">What Is Mental Health?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We can find thousands of definitions about mental health, and none of them will even approach the surface. Some say it's a coping mechanism, while others say it's a state of well-being in which we realize our abilities.&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In other words, mental health is a combination of our emotional, social, and psychological well-being, which determines our relationships and contributes to our work.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When we consider this, having a work environment that enables and offers mental health support can be a major driver of employee work performance.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="mental-health-helps-reduce-burnouts">Mental Health Helps Reduce Burnouts</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>When employees were instructed to start working from home, some were relieved they didn’t lose their job while others panicked, clueless about how working from home will affect their productivity.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What the majority of employees failed to consider is the sense of utter loneliness that came from working alone. Protected from outside threats, yes, but completely cut out from the rest of the world.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The truth is, it hasn’t been easy.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As the pandemic showed no signs of slowing down, people’s well-being took a toll. <a href="https://www.cnbc.com/2020/07/28/remote-work-burnout-is-growing-as-coronavirus-pandemic-stretches-on.html" target="_blank" rel="noreferrer noopener">According to a study by Monster</a>, 69% of employees are <a href="https://adevait.com/blog/workplace/burnout-tech-industry" target="_blank" rel="noreferrer noopener">suffering from burnout</a> while working from home. What’s more, 59% are taking less time off than they normally would.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Phrases like “depressing monotony,” “on the verge of a panic attack,” and “added pressure” get thrown around a lot.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another report from <a href="https://www.bloomberg.com/news/articles/2020-04-23/working-from-home-in-covid-era-means-three-more-hours-on-the-job" target="_blank" rel="noreferrer noopener">NordVPN</a> confirmed the same. US employees that have switched to working from home were noticed to log three hours more per day. Employees in European countries like France, Spain, and the UK have seen an increase in overtime work of 2 hours per day.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another interesting fact emerged: peak email time has moved an hour, from 10 a.m. to 9 a.m. Employees were also logging in hours late at night, with spikes in usage from midnight to 3 a.m.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>What Can Employers Do?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Employees are beginning to look at mental health as a business value. Thus, it has never been more important for employers to invest in their employees' well-being. Employers who will prioritize employee well-being will be those who can expect to avoid a drop in employee engagement and productivity.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Failing to do so can potentially lead to high turnover rates, and you'll witness your best employees leaving your company for the competitor. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Even before the pandemic, <a href="https://www.benefitnews.com/news/avoidable-turnover-costing-employers-big?brief=00000152-14a7-d1cc-a5fa-7cffccf00000&amp;utm_content=socialflow&amp;utm_campaign=ebnmagazine&amp;utm_source=twitter&amp;utm_medium=social" target="_blank" rel="noreferrer noopener">companies were seeing</a> huge turnovers that were caused due to reasons such as work-life balance (12%), well-being (9%), work environment (6%), and management behavior (11%). </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But potential turnover is easily avoidable.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here are some inexpensive strategies that can make a huge difference:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Don't hesitate to engage in conversations about mental health with employees. Senior leaders should encourage open discussions by sharing their personal stories regarding mental health.</li><li>Check-in with your employees regularly. A quick "what's everyone doing today" message in Slack can go a long way.</li><li>Encourage employees to take time off if they need it. </li><li>Take advantage of <a href="https://adevait.com/blog/remote-work/agile-games-distributed-teams" target="_blank" rel="noreferrer noopener">team-building activities</a>. What's stopping you from setting up virtual movie nights? </li><li>Give mental health days to let employees log off and focus on their well-being.</li><li>Provide clear instructions on working hours. </li><li>Don't contact employees on their days off or over the weekend. </li><li>Rethink your benefits package and consider including programs and resources that address mental health.</li></ol>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="self-care-makes-better-future-leaders">Self-Care Makes Better Future Leaders</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Leadership is a tough task to live up to. A leader is the one that everyone looks up to and reaches out to if they need anything. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But behind that strong picture, one person is doing their very best to keep it together. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They dedicate their time and energy to take care of their team, their superiors, clients, and even their partners. Unfortunately, somewhere along the way, they forget to take care of themselves.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>How are leaders expected to lead others if they start suffering from burnout, disengagement, and exhaustion themselves? </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Only a highly-functioning leader can lead highly-functioning teams. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>What Can Leaders Do?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>They should lead by example.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If a leader is taking care of themselves mentally and physically, they will inspire their entire team to do so. Self-care should be seen as an investment that can lead to an increase of a leader’s productivity and effectiveness.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With that said, here are a few things leaders can do to remain able to lead:</p>
<!-- /wp:paragraph -->
<!-- wp:list {"ordered":true} -->
<ol><li>Always respect your need to sleep. Sleeping is very crucial to our day-to-day activities. It leads to increased focus, improved cognitive function, and improved empathy, among other things. </li><li>Maintain a healthy diet. Although this may seem like new-age nonsense, a balanced diet is related to higher energy levels, better moods, and lower levels of depression.</li><li>Stay active. Dedicating one hour every day to jogging, walking, or lifting weights can increase your blood flow and boost your learning and memory. </li><li>Set a daily reminder for a quick loving-kindness meditation.</li><li>Reach out to your family and friends to increase your social connectedness. </li></ol>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="the-world-of-work-may-change-forever">The World of Work May Change Forever</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that the majority of teams experienced it first-hand how it feels to be working remotely, a question arises: will companies continue to operate remotely, or will they ask their employees to return to the office?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Many of the tech giants have already announced they're sticking to the remote work arrangement.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Google will let its employees work remotely until 2021.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Twitter's CEO announced that his employees can continue to work from home even after shelter-in-place orders end.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Facebook has issued a statement saying the company is planning on having 50% of its employees work remotely in the next 5-10 years.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And it’s not just the tech giants. A <a href="https://www.pwc.com/us/covid-19-survey?WT.mc_id=CT1-PL52-DM1-TR1-LS4-ND30-PRG6-CN_CFOPulseSurvey-&amp;eq=CT1-PL52-DM1-CN_CFOPulseSurvey" target="_blank" rel="noreferrer noopener">PwC US CFO Pulse Survey</a> found that 49% of leaders say they're planning to make remote working a permanent option for roles that allow.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It’s also highly likely that there's going to be a shift in leaders' thinking about remote work. Leaders might recognize the advantages of <a href="https://adevait.com/blog/remote-work/distributed-teams-the-future" target="_blank" rel="noreferrer noopener">distributed teams</a> in other future business situations. Chances are, remote work will be openly embraced.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Employers are not the only ones who may get seduced by the remote work concept. Employees have also got a chance to taste the fantastic work-life balance remote work brings. As a result, we can expect to see the best talent shifting towards more flexible organizations and avoiding rigid ones.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It seems like COVID-19 will reshape the world of work, forever.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>What Does This Mean?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This means that leaders should rethink their attitudes towards mental health. Whether leaders opt to implement the fully distributed work model or the hybrid (a combination of remote work and office work), employee mental health should be placed in the spotlight.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the new workplace of the future, all kinds of mental health issues may appear, ranging from depression and burnout to trauma and anxiety. Mental health experiences will likely vary, depending on job type, gender, parenting and caregiving obligations, economic opportunity, and other factors.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you’re a leader who’s planning to transition their team to being 100% remote or hybrid, don’t just wait until or if issues arise. Be proactive and have mental health initiatives ready in place. Nurture an environment of open communication, camaraderie, and recognition, and you may not even need those special mental health initiatives.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There’s no going back. The future of work is here. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Are you willing to take the recommended steps or will you risk losing your best talent? </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The choice is yours to make. </p>
<!-- /wp:paragraph --> ]]></description>
<category>Future Of Work</category>
<author>Teuta Reci</author>
<pubDate>Mon, 28 Dec 2020 18:20:59 +0000</pubDate>
</item>
<item>
<title><![CDATA[ The CTO’s Framework for Delivering Secure Software Applications ]]></title>
<link><![CDATA[ https://adevait.com/qa/delivering-secure-software-applications ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>Delivering secure applications is a must in the competitive market of the 21st century. This framework that aims to provide generic guidance for building safe products can help. </em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To understand how the private sector cybercrime landscape is evolving and help businesses fight e-crime, EY annually conducts in-depth research into the phenomenon. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This year’s so-called ‘Global Information Security Survey’ is based on the answers of 1,750+ respondents across 25 industries in 60+ countries.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>It found that the largest part of the cybercrime burden is borne by businesses—in the case of the UK, private sector enterprises face 78% (~£21 billion) of the total cost.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Many businesses are not capable of maintaining their products and designing security requirements for each aspect, and this issue can be presented in the following diagram:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3880,"sizeSlug":"large"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2020/12/Screenshot_3.png" alt="cybersecurity maturity" class="wp-image-3880"/><figcaption><a href="https://www.consultancy.uk/news/2917/active-defense-vital-for-battling-cybersecurity-threat" target="_blank" rel="noreferrer noopener">Source</a></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>In other words, companies without dedicated Cyber Security teams are designing and delivering products and <strong>matching the basic security criteria (which leaves the product to be vulnerable from multiple aspects)</strong>, at the same time.<strong><br></strong><br>Since cyber-experts are rare and expensive to be hired,&nbsp;there is a trade-off solution: Incorporating a framework for delivering secure software applications that will provide generic guidance into the company culture.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As a security professional with 10 yrs experience in IT, I have been presenting my own framework to my clients. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They have submitted massive positive feedback that this framework worked for their businesses, and they have successfully delivered safe products.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With this framework, every CTO will be able to:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Plan security requirements from all aspects of all projects.</li><li>Get better estimates of the Return on Investment.</li><li>Roll-out a precise strategy and roadmap which is reusable in every project and domain.</li><li>Deliver safe and maintained products while leaving room for improvement.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Note: If you have an existing product(s), you might try to adapt to the framework and eventually be compliant—and see the real value of it. On the other hand, you can start from scratch and make sure that you are setting security requirements first and then evolve on the practical side.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let’s jump right into it!&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"74647170","classMigrate":true,"mappingHeaders":[true,false,true,false,false,false],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022The 12 Aspects of the Framework\u0022,\u0022link\u0022:\u0022the-12-aspects-of-the-framework\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eThe 12 Aspects of the Framework\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Authentication\u0022,\u0022link\u0022:\u0022authentication\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eAuthentication\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Input and Output Handling\u0022,\u0022link\u0022:\u0022input-and-output-handling\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eInput and Output Handling\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Access Control\u0022,\u0022link\u0022:\u0022access-control\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eAccess Control\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Session Management\u0022,\u0022link\u0022:\u0022session-management\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eSession Management\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Data Protection \u0026amp; Storage\u0022,\u0022link\u0022:\u0022data-protection-storage\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eData Protection \u0026amp; Storage\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Configuration\u0022,\u0022link\u0022:\u0022configuration\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eConfiguration\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Error Handling \u0026amp; Logging\u0022,\u0022link\u0022:\u0022error-handling-logging\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eError Handling \u0026amp; Logging\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Code Quality \u0026amp; Build Process\u0022,\u0022link\u0022:\u0022code-quality-build-process\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eCode Quality \u0026amp; Build Process\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Platform\u0022,\u0022link\u0022:\u0022platform\u0022,\u0022content\u0022:\u0022\u003cstrong\u003ePlatform\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Network\u0022,\u0022link\u0022:\u0022network\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eNetwork\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Cryptography\u0022,\u0022link\u0022:\u0022cryptography\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eCryptography\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Architecture\u0022,\u0022link\u0022:\u0022architecture\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eArchitecture\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Tooling \u0026amp; Technologies\u0022,\u0022link\u0022:\u0022tooling-technologies\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eTooling \u0026amp; Technologies\u003c/strong\u003e\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Visual Representation \u0026amp; Measuring of Progress\u0022,\u0022link\u0022:\u0022visual-representation-measuring-of-progress\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eVisual Representation \u0026amp; Measuring of Progress\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Code Quality\u0022,\u0022link\u0022:\u0022code-quality\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eCode Quality\u003c/strong\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Summary\u0022,\u0022link\u0022:\u0022summary\u0022,\u0022content\u0022:\u0022\u003cstrong\u003eSummary\u003c/strong\u003e\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-74647170" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#authentication">Authentication</a></li><li><a href="#input-and-output-handling">Input and Output Handling</a></li><li><a href="#access-control">Access Control</a></li><li><a href="#session-management">Session Management</a></li><li><a href="#data-protection-storage">Data Protection &amp; Storage</a></li><li><a href="#configuration">Configuration</a></li><li><a href="#error-handling-logging">Error Handling &amp; Logging</a></li><li><a href="#code-quality-build-process">Code Quality &amp; Build Process</a></li><li><a href="#platform">Platform</a></li><li><a href="#network">Network</a></li><li><a href="#cryptography">Cryptography</a></li><li><a href="#architecture">Architecture</a></li><li><a href="#visual-representation-measuring-of-progress">Visual Representation &amp; Measuring of Progress</a></li><li><a href="#code-quality">Code Quality</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="the-12-aspects-of-the-framework"><strong>The 12 Aspects of the Framework</strong></h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3 id="authentication"><strong>Authentication</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Authentication is the first thing that you need to think about. You need to define requirements for identifying each entity and use that data in the desired context. To start, please be sure that you:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Do not hardcode any credentials in the code.</li><li>Develop a strong reset password system.</li><li>Implement a Strong password Policy.</li><li>Implement an Account Lockout mechanism to prevent brute-force attacks.</li><li>Don’t disclose too much information in the error message.</li><li>Store all database credentials securely.</li><li>Run external applications and middleware with minimal privileges.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="input-and-output-handling"><strong>Input and Output Handling</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>After you identify a certain entity, you need to make sure that the form in which you are handling its input or output is expected (which improves your overall security by 50%—it's mostly validation).</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Conduct Contextual Output Encoding before sending any data to the user.</li><li>Choose white-listing input/output instead of Black-listing.</li><li>Use Parameterized SQL Queries (Preventing SQL Injection).</li><li>Use tokens to prevent Forging of the requests.</li><li>Set general encoding for your application.</li><li>Validate uploaded Files (extension, content).</li><li>Use the “Nosniff” Header for uploaded content.</li><li>Validate the Source of Input (HTTP Verb).</li><li>Use the X-Frame-Options Header.</li><li>Use Secure HTTP Response Headers (CSP, X-XSS-Protection, Public-Key-Pin).</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="access-control"><strong>Access Control</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>If Authentication is identifying the entity, I/O is validating the input/output to be in the expected form; the third thing that needs to happen is Authorization.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is what you need to do:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Apply Access Control Checks Consistently.</li><li>Apply the principle of Least Privilege.</li><li>Don’t use Direct Object References for Access Control Checks.</li><li>Don’t use Invalidated Forwards or Redirects.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="session-management"><strong>Session Management</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>After our entity is Authenticated (Identified) and Authorized (Allowed to do actions in our application), we would need a box in which we can contain it. We would need to have control over the time and actions that are happening in that isolated box, which can be called a session.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here, be sure to:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Ensure that session identifiers are sufficiently random.</li><li>Regenerate session tokens.</li><li>Implement an idle session timeout.</li><li>Implement an absolute session timeout.</li><li>Destroy sessions at any sign of tampering.</li><li>Invalidate the session after user logout.</li><li>Use secure Cookie Attributes (HttpOnly &amp; Secure).</li><li>Set the Cookie domain and path correctly.</li><li>Set the Cookie expiration time.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="data-protection-storage"><strong>Data Protection &amp; Storage</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>With our previous aspects, we have created the context for our entities. Now the next step is to protect the content in each of the entities—the data itself.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>System credential storage facilities need to be used to store every sensitive data.</li><li>No sensitive data should be stored outside of the app container.</li><li>No sensitive or PII Data needs to be written to application logs.</li><li>No sensitive data is shared with third-parties unless it’s a necessary part of the architecture.</li><li>The keyboard cache is disabled on text inputs that processes sensitive data.</li><li>No sensitive data is exposed via IPC mechanisms.</li><li>No sensitive data such as passwords is exposed through the UI.</li><li>Use HTTPS everywhere.</li><li>Disable HTTP Access for all protected resources.</li><li>Use the Strict-Transport-Security Header.</li><li>Store user passwords using a Strong, Iterative &amp; Salted hash.</li><li>Securely exchange encryption keys.</li><li>Setup Secure Key Management Process.</li><li>Turn off weak TLS Configuration on the servers.</li><li>Use Valid HTTPS Certificates from a reputable CA.</li><li>Disable Data Caching using Cache Control Headers.</li><li>Limit the use and storage of sensitive data.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="configuration"><strong>Configuration</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Configuration is always dependent on the use case (the functional aspects as well), so here you should define the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Define profiles for “Development”, “Testing”, “Pre-Production”, “Production”.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="error-handling-logging"><strong>Error Handling &amp; Logging</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Logging and error handling is a crucial part of your software. It’s really important to keep relevant logs that can help in recovering from incidents or detecting the issue that is happening. Please make sure to log in:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>all authentication activities</li><li>all privilege changes</li><li>administrative activities</li><li>access to sensitive data</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Don't:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>log inappropriate data (PII or confidential)</li><li>reveal generic error messages</li><li>allow unhandled exceptions</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="code-quality-build-process"><strong>Code Quality &amp; Build Process</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You should also roll-out a code quality and build a process to make sure that your application is developed properly and released with proper configuration. Every misconfiguration helps attackers bypass your application and exploit your components. Consider <a href="https://adevait.com/qa">hiring QA engineers</a> for this process. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Please make sure to do the following:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>The product is signed and provisioned with a valid certificate, of which the private key is properly protected.</li><li>The app has been built in release mode, with settings that are appropriate for a release build.</li><li>Debugging symbols have been removed from native binaries.</li><li>Debugging code and developer assistance code have been removed.</li><li>All used libraries and frameworks are identified and checked for known vulnerabilities.</li><li>The app catches and handles possible exceptions.</li><li>Error handling logic in security controls denies access by default.</li><li>In unmanaged code, memory is allocated, freed and used securely.</li><li>Security features by the toolchain are activated by default.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="platform"><strong>Platform</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The platform should take care of providing a generic layer of abstraction in which you can set certain validations on a high-level. This is usually a good place to define with consulting software architects or security architects.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>The app requests the minimum set of permissions necessary.</li><li>All inputs from external sources and the user are validated and, if necessary, sanitized.</li><li>The app does not export sensitive functionality via custom URL schemes.</li><li>Uploading &amp; downloading resources is validated by extension.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="network"><strong>Network</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>On the network level, there are certain things that can be done to protect you and make the transit of data obfuscated and optimized.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Data needs to be encrypted on the network using TLS.</li><li>The TLS setting needs to follow the current best practices.</li><li>The app needs to verify the X.509 certificate on the remote endpoint.</li><li>Network compression can be implemented if possible.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>From a cryptography aspect, you need to set up good obfuscation approaches so you can prevent decoding sensitive data. If someone steals the information, they would have the information in an obfuscated form, which doesn’t mean anything to them without the key (and that’s how you will protect yourself in-depth).</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="cryptography"><strong>Cryptography</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The app:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>does not rely on symmetric cryptography with hardcoded keys</li><li>uses proven implementations of cryptographic primitives</li><li>does not use deprecated protocols for security purposes</li><li>does not re-use the same cryptographic key for multiple purposes</li><li>All random values are generated using a sufficiently secure random number generator.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="architecture"><strong>Architecture</strong></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The highest layer needs to be properly set up, so the project is scalable and allows optimized performance while implementing security controls.</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>All app components are identified and known to be needed.</li><li>Security controls are enforced on the respective remote endpoints.</li><li>A high-level architecture has been defined and documented.</li><li>Data considered sensitive in the context of the app is clearly identified and documented.</li><li>The app should comply with privacy laws and regulations.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="tooling-technologies"><strong>Tooling &amp; Technologies</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Certain tools and third-party solutions can help in better management, measurement and propagating the framework requirements to the teams:</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3 id="visual-representation-measuring-of-progress"><strong>Visual Representation &amp; Measuring of Progress</strong></h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li><a href="https://app.diagrams.net/" target="_blank" rel="noreferrer noopener">https://app.diagrams.net/</a>: Free Web application that allows you to create diagrams.</li><li>Azure DevOps or Jira: Bug Management systems that can reflect the framework as tasks propagated to the teams.</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3 id="code-quality"><strong>Code Quality</strong></h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>SonarQube: Tool that can be integrated on code-level that will validate certain rules.</li><li>Checkmarx: Static Code Analysis tool.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="summary"><strong>Summary</strong></h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Cyber Security professionals have a deeper understanding of every single aspect that we mentioned previously in our text. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As such, they can be a crucial element of any company. The disappointing fact is they're scarce and expensive.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With that being said, following a framework is your second best option.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Having the previously mentioned framework in place is a good option. It will provide general guidance and ensure your company will implement security controls in its culture and minimize the risk from outside and inside attacks.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Thank you for your time. I hope you found this article quite useful.</p>
<!-- /wp:paragraph --> ]]></description>
<category>QA</category>
<author>Dragan Ilievski</author>
<pubDate>Sun, 20 Dec 2020 21:07:37 +0000</pubDate>
</item>
<item>
<title><![CDATA[ How to Build a Strong Engineering Culture That Empowers Engineers ]]></title>
<link><![CDATA[ https://adevait.com/blog/workplace/build-strong-engineering-culture ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>Autonomy, Transparency, and Impact - some of the key ingredients that help make a strong engineering culture. Here's how to build a good culture that gives the power back to the engineers and makes them happy and productive.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Are you happy at your job?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A simple question, yet it can lend a great deal of information.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Most engineers who are happy at their job happen to work at a company with a great engineering culture. Likewise, unhappy engineers happen to be part of a company with a not-so-great engineering culture.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Bad culture is easily noticed. Things are going slow, communication is bad, teams are not in sync, and bosses do micromanagement.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A good culture is equally noticeable. Employees enjoy a great culture that gives the power back to them and makes them appreciated and productive. This culture strives to bring autonomous teams together and inspires engineers to innovate and create better products.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But how do you build a great engineering culture?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this post, I'll discuss every component I believe is critical for building and sustaining a strong engineering culture that will empower developers to innovate and thrive.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"26a72940","classMigrate":true,"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022Make People Feel Closer to Each Other\u0022,\u0022link\u0022:\u0022make-people-feel-closer-to-each-other\u0022,\u0022content\u0022:\u0022Make People Feel Closer to Each Other\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Autonomy and Trust Is Key\u0022,\u0022link\u0022:\u0022autonomy-and-trust-is-key\u0022,\u0022content\u0022:\u0022Autonomy and Trust Is Key\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Create Transparency\u0026nbsp;\u0022,\u0022link\u0022:\u0022create-transparency\u0022,\u0022content\u0022:\u0022Create Transparency\u0026nbsp;\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Bring the Impact Closer to the Engineers\u0022,\u0022link\u0022:\u0022bring-the-impact-closer-to-the-engineers\u0022,\u0022content\u0022:\u0022Bring the Impact Closer to the Engineers\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Key Takeaways\u0022,\u0022link\u0022:\u0022key-takeaways\u0022,\u0022content\u0022:\u0022Key Takeaways\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-26a72940" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#make-people-feel-closer-to-each-other">Make People Feel Closer to Each Other</a></li><li><a href="#autonomy-and-trust-is-key">Autonomy and Trust Is Key</a></li><li><a href="#create-transparency">Create Transparency&nbsp;</a></li><li><a href="#bring-the-impact-closer-to-the-engineers">Bring the Impact Closer to the Engineers</a></li><li><a href="#key-takeaways">Key Takeaways</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="make-people-feel-closer-to-each-other">Make People Feel Closer to Each Other</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>People in your company must feel a sense of respect and appreciation for one another. They need to trust that their coworkers and engineering managers want what's best for them and are transparent with both good and bad news.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One way of making people feel closer to each other is by organizing <a href="https://adevait.com/blog/remote-work/agile-games-distributed-teams" target="_blank" rel="noreferrer noopener">team-building activities</a>. For example, you can create different channels on Slack where people will connect and interact in meaningful ways outside of regular meetings. From #travel and #food channels to #petowners and #moviefreaks, let yourself be creative when creating these channels.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Apart from team-building activities, another idea is to celebrate your team's small wins. You’ve just completed a sprint, burned all of the items, and had a smooth production updated. Always dedicate time to reflect and celebrate even the smallest achievements. That creates a culture of appreciation and making continuous improvement, day by day. Or even better, on your next production release, organize a virtual party and ask everyone to grab their favorite drink and celebrate.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>What these activities will do is they will help you build a great culture. Your engineers will learn about their coworkers' strengths and weaknesses, who they can trust in really stressful situations, and who they can reach out to for a quick drink after work.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3870,"sizeSlug":"large"} -->
<div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://static.adevait.com/2020/12/Make-People-Feel-Closer-to-Each-Other-1024x541.jpg" alt="how to build an engineering culture" class="wp-image-3870"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="autonomy-and-trust-is-key">Autonomy and Trust Is Key</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>“Control leads to compliance; autonomy leads to engagement.”</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Probably the most famous autonomy model of all time is Spotify's.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Spotify's model supports autonomy and creativity by letting employees complete their tasks in the way they see fit. Do you need to work on <a href="https://adevait.com/software/technical-debt" target="_blank" rel="noreferrer noopener">resolving technical debt</a>? That's up to the team. Do you need to change direction? That's up to the team.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One team can have daily meetings, while other engineering teams can meet only when necessary. One team can be using one project management tool, while the other can be using a completely different one.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In brief, the Spotify's model decentralized decision-making and transfers that responsibility to its Squads, Tribes, Chapters, and Guilds.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In addition to this, teams at Spotify have such a high level of autonomy that one team can change another team's code. For example, if team A wants to access team B's codebase, team A has to ask for the change first. If team B says "go" but is too busy to do the change, team A has the complete autonomy to change the code itself.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This high level of autonomy can lead to better products, more engaged employees, and happier customers.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To encourage more autonomy at your company, determine which decisions can be trusted to your teams instead of being mandated by departments that are disengaged from the everyday engineers' work.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="create-transparency">Create Transparency&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Transparency at the workplace indicates an environment where employees can communicate openly and honestly with their team members and managers, cultivating a culture where information flows freely between people, development teams, and departments.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One of the main cornerstones of transparency is feeling like you can safely <a href="https://adevait.com/software/feedback-for-software-developers" target="_blank" rel="noreferrer noopener">give and receive feedback</a>. Transparency creates trust, inspires innovation, and supports healthy work environments. When every team member is up-to-date with what is happening on their team and why, they will, in return, be more engaged in their work and more creative in solving problems. On the flip side, a lack of open communication can lead to mistrust and harm your team's projects.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>One great example of a transparent workplace is <a href="https://buffer.com/" target="_blank" rel="noreferrer noopener">Buffer.</a>&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In fact, Buffer is so transparent that you can see how much each employee makes (<em>the CEO made $218,000 in 2016</em>).</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Apart from salaries, code, revenues, and diversity stats are all published on <a href="https://buffer.com/about#transparency" target="_blank" rel="noreferrer noopener">Buffer’s transparency page</a>. By being fully transparent, trust between team members has increased drastically, which has helped create a healthy and sustainable work environment.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Transparency also includes sharing your wins, decisions, failures, and challenges. Sharing your failures is more challenging than sharing wins, but it has the power to increase trust and unity on a team. So, instead of sugar coating things, share with your team how you failed, why you failed, and how you plan to move forward.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3871,"width":461,"height":427,"sizeSlug":"large"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://static.adevait.com/2020/12/Create-Transparency.png" alt="" class="wp-image-3871" width="461" height="427"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="bring-the-impact-closer-to-the-engineers">Bring the Impact Closer to the Engineers</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Why do <a href="https://adevait.com/software">software engineers</a> write code?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Is it because creating great software makes them happy?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This is not really true.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In reality, the bulk of engineers are most passionate when they're making customers happy. They want to know that what they do is useful for the people who are using the product. Put yourself in their shoes. They spend day in, day out coding, and it's only understandable they would want to see the outcome of their work.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Unfortunately, many tech companies overlook the sense of purpose employees crave. Consequently, employees are left feeling like they're just working for a paycheck and aren't contributing to anything greater than themselves.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here are a few ways how you can bring the impact closer to the employee:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Share the company vision.</li><li>Offer recognition.&nbsp;</li><li>Express gratitude.&nbsp;</li><li>Let employees sit down with customer service and listen to customer's feedback.&nbsp;</li><li>Share customer success stories.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="key-takeaways">Key Takeaways</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We'll finish this post with a quote by the business management guru Peter Drucker, who said:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>Culture eats strategy for breakfast</em>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Meaning, regardless of how strong your strategic plan is, it's bound to fail if the people driving the strategy aren't passionate about the job and your company.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>With that said, the goal of any technical leader should be to build a strong engineering culture that focuses on making employees happy and productive by giving them autonomy and creating transparency. A culture that will make them feel appreciated and included, help them see the impact of their work, and inspire them to always innovate and create better code.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Workplace</category>
<author>Tosho Trajanov</author>
<pubDate>Fri, 11 Dec 2020 12:18:06 +0000</pubDate>
</item>
<item>
<title><![CDATA[ How to Create Elegant HTML Reports in Postman ]]></title>
<link><![CDATA[ https://adevait.com/qa/how-to-create-elegant-html-reports-in-postman ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>Are you wondering what is the best way to create elegant HTML reports in Postman? Wonder no more because I have the answer in the blog post below! </em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Postman can be a powerful tool when it comes to testing. Every time we introduce a new code, we have to create a new test to ensure that our API is working properly.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In Postman, you can add Tests to verify the results of the response and verify them in the Test Results tab.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>But what if we want to create an effective HTML report that shows those results?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this tutorial, I will give clear instructions on how to create elegant HTML reports in Postman, quickly and easily.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's dive in!</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"c4536c87","classMigrate":true,"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022Why We Should Generate HTML Reports\u0022,\u0022link\u0022:\u0022why-we-should-generate-html-reports\u0022,\u0022content\u0022:\u0022Why We Should Generate HTML Reports\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Installing NodeJS and npm\u0022,\u0022link\u0022:\u0022installing-nodejs-and-npm\u0022,\u0022content\u0022:\u0022Installing NodeJS and npm\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Checking the Success of the Installation\u0022,\u0022link\u0022:\u0022checking-the-success-of-the-installation\u0022,\u0022content\u0022:\u0022Checking the Success of the Installation\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Installing Newman and HTML Reporters\u0022,\u0022link\u0022:\u0022installing-newman-and-html-reporters\u0022,\u0022content\u0022:\u0022Installing Newman and HTML Reporters\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Exporting Postman’s Collections and Environments\u0022,\u0022link\u0022:\u0022exporting-postmans-collections-and-environments\u0022,\u0022content\u0022:\u0022Exporting Postman’s Collections and Environments\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Running Our JSON Files\u0022,\u0022link\u0022:\u0022running-our-json-files\u0022,\u0022content\u0022:\u0022Running Our JSON Files\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022To Sum Up\u0022,\u0022link\u0022:\u0022to-sum-up\u0022,\u0022content\u0022:\u0022To Sum Up\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-c4536c87" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#why-we-should-generate-html-reports">Why We Should Generate HTML Reports</a></li><li><a href="#installing-nodejs-and-npm">Installing NodeJS and npm</a></li><li><a href="#checking-the-success-of-the-installation">Checking the Success of the Installation</a></li><li><a href="#installing-newman-and-html-reporters">Installing Newman and HTML Reporters</a></li><li><a href="#exporting-postmans-collections-and-environments">Exporting Postman’s Collections and Environments</a></li><li><a href="#running-our-json-files">Running Our JSON Files</a></li><li><a href="#to-sum-up">To Sum Up</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="why-we-should-generate-html-reports">Why We Should Generate HTML Reports</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>HTML reports are a great way to show to the rest of the team the results of our current test execution.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They are clear and they contain results written in a way that everybody who accesses the file can see the information clearly.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Also, HTML reports look more professional. There's no comparison between a word document and an HTML!</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="installing-nodejs-and-npm">Installing NodeJS and npm</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The first step in creating reports in Postman is to install NodeJS.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This step is simple.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We can download NodeJS from the official site (<a href="https://nodejs.org/" target="_blank" rel="noreferrer noopener">https://nodejs.org/</a>). Just make sure to install the version that matches your OS.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>During the installation setup, confirm that the npm package manager is selected as we will be using this package in the next step.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="checking-the-success-of-the-installation">Checking the Success of the Installation</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We can check that NodeJS and npm were successfully installed by opening cmd and typing:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>node-v</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>NodeJS version should come up.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm -v</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Npm version should come up.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="installing-newman-and-html-reporters">Installing Newman and HTML Reporters</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Newman is the collection runner that allows us to run and test a Postman Collection from the command line. Installing it is pretty simple.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Use cmd once again and type:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install -g newman</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Once Newman installation is completed we can install the reporters by typing:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>npm install -g newman-reporter-html
npm install -g newman-reporter-htmlextra</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Finally, we are ready to create the HTML reports!</p>
<!-- /wp:paragraph -->
<!-- wp:image {"id":3816,"sizeSlug":"large"} -->
<figure class="wp-block-image size-large"><img src="https://static.adevait.com/2020/11/Exporting-Postman-1024x430.png" alt="Creating Elegant Postman HTML Reports" class="wp-image-3816"/></figure>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="exporting-postmans-collections-and-environments">Exporting Postman’s Collections and Environments</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We have completed the reporters installation, but we still need the collections that we want to execute and translate to our HTML reports.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This can be done using Postman by just selecting Export in the collection folder and then saving them as a *json file.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We also have to export the environment and save it as a *json file.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="running-our-json-files">Running Our JSON Files</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This is our last step in creating the HTML reports.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>First, we need to open the cmd and access the folder where we saved our JSON files (for example, cd C:\Users\YourName\ExportedJSONs).&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once we access this folder, we can execute the files inside it by using this command:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>newman run YourCollectionName.json -e YourEnvironment.json -n 2 -r htmlextra
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Please note that you will have to replace <em>YourCollectionName</em> and <em>YourEnvironment</em> with the name of your exported files.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Keep in mind that <em>-n 2</em> refers to the number of iterations you want. For example, you can try <em>-n 5</em> if you want 5 iterations. This will be shown in your HTML dashboard.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once we execute the command, a folder called <em>Newman</em> will be created in our collections folder origin. Open it by using your favorite web browser and you will find your test results in an elegant HTML file. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="to-sum-up">To Sum Up</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Congrats! You have successfully managed to create elegant HTML reports in Postman.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>I hope this tutorial helped you and I wish you good luck with your testing!</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can find additional information about the HTML reporter in:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://www.npmjs.com/package/newman#html-reporter" target="_blank" rel="noreferrer noopener">https://www.npmjs.com/package/newman#html-reporter</a></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>And if you need to <a href="https://adevait.com/qa" target="_blank" rel="noreferrer noopener">hire QA engineers</a>, get in touch with us today. </p>
<!-- /wp:paragraph --> ]]></description>
<category>QA</category>
<author>Ezequiel Dellavechia</author>
<pubDate>Sat, 28 Nov 2020 09:26:02 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Data Visualization: Best Tips and Practices ]]></title>
<link><![CDATA[ https://adevait.com/data-science/data-visualization-best-practices ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>Data visualization: the art of communicating information through visuals.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Businesses today should rely on the biggest amount of data available to make the smartest and most well-informed business decisions. <em>How do customers move through my digital store? What's the performance of my sales team?</em>&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These complex systems are hard to understand, much less fix, if you are not able to have a clear picture of the processes underneath.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Thanks to data visualization, making information understandable and actionable can now be an easy and affordable task for everyone.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, there's a catch! </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Putting complex numbers and other pieces of information into graphs is not enough. Anyone working with data needs to follow data visualization best practices to present that data in a way that's easier and understandable for the audience.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In a nutshell, data visualization should be easy to understand, on-point, appealing, and never misleading.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"68bdb119","classMigrate":true,"mappingHeaders":[true,true,false,false,false,false],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022Exploratory and Explanatory Analysis\u0022,\u0022link\u0022:\u0022exploratory-and-explanatory-analysis\u0022,\u0022content\u0022:\u0022Exploratory and Explanatory Analysis\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Understanding the Context\u0022,\u0022link\u0022:\u0022understanding-the-context\u0022,\u0022content\u0022:\u0022Understanding the Context\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Choosing an Effective Visual\u0022,\u0022link\u0022:\u0022choosing-an-effective-visual\u0022,\u0022content\u0022:\u0022Choosing an Effective Visual\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Simple Text\u0022,\u0022link\u0022:\u0022simple-text\u0022,\u0022content\u0022:\u0022Simple Text\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Table\u0022,\u0022link\u0022:\u0022table\u0022,\u0022content\u0022:\u0022Table\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Heatmaps\u0022,\u0022link\u0022:\u0022heatmaps\u0022,\u0022content\u0022:\u0022Heatmaps\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Scatterplot\u0022,\u0022link\u0022:\u0022scatterplot\u0022,\u0022content\u0022:\u0022Scatterplot\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Line Graph\u0022,\u0022link\u0022:\u0022line-graph\u0022,\u0022content\u0022:\u0022Line Graph\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Slope Graph\u0022,\u0022link\u0022:\u0022slope-graph\u0022,\u0022content\u0022:\u0022Slope Graph\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Bar Chart\u0022,\u0022link\u0022:\u0022bar-chart\u0022,\u0022content\u0022:\u0022Bar Chart\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Stacked Vertical Bars\u0022,\u0022link\u0022:\u0022stacked-vertical-bars\u0022,\u0022content\u0022:\u0022Stacked Vertical Bars\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Horizontal Bars\u0022,\u0022link\u0022:\u0022horizontal-bars\u0022,\u0022content\u0022:\u0022Horizontal Bars\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Stacked Horizontal Bars\u0022,\u0022link\u0022:\u0022stacked-horizontal-bars\u0022,\u0022content\u0022:\u0022Stacked Horizontal Bars\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022⚠️ Avoid Pie Charts ⚠️\u0022,\u0022link\u0022:\u0022⚠️-avoid-pie-charts-⚠️\u0022,\u0022content\u0022:\u0022⚠️ Avoid Pie Charts ⚠️\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022How to Make Your Visuals Simpler, Lighter, and On-Point\u0022,\u0022link\u0022:\u0022how-to-make-your-visuals-simpler-lighter-and-on-point\u0022,\u0022content\u0022:\u0022How to Make Your Visuals Simpler, Lighter, and On-Point\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Step-by Step Tips\u0022,\u0022link\u0022:\u0022step-by-step-tips\u0022,\u0022content\u0022:\u0022Step-by Step Tips\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Preattentive Attributes\u0022,\u0022link\u0022:\u0022preattentive-attributes\u0022,\u0022content\u0022:\u0022Preattentive Attributes\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Shapes\u0022,\u0022link\u0022:\u0022shapes\u0022,\u0022content\u0022:\u0022Shapes\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Text\u0022,\u0022link\u0022:\u0022text\u0022,\u0022content\u0022:\u0022Text\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Additional Design Tips\u0022,\u0022link\u0022:\u0022additional-design-tips\u0022,\u0022content\u0022:\u0022Additional Design Tips\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Key Takeaways\u0022,\u0022link\u0022:\u0022key-takeaways\u0022,\u0022content\u0022:\u0022Key Takeaways\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-68bdb119" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#exploratory-and-explanatory-analysis">Exploratory and Explanatory Analysis</a></li><li><a href="#understanding-the-context">Understanding the Context</a></li><li><a href="#choosing-an-effective-visual">Choosing an Effective Visual</a></li><li><a href="#how-to-make-your-visuals-simpler-lighter-and-on-point">How to Make Your Visuals Simpler, Lighter, and On-Point</a></li><li><a href="#preattentive-attributes">Preattentive Attributes</a></li><li><a href="#additional-design-tips">Additional Design Tips</a></li><li><a href="#key-takeaways">Key Takeaways</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="exploratory-and-explanatory-analysis">Exploratory and Explanatory Analysis</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>One of the first things one should consider when preparing a presentation using data visualizations is to understand the purpose.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>What is the primary goal of the data visualization?</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>There are two basic types of data visualization: exploratory and explanatory.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The purpose of exploratory analysis is to allow users to explore the data and look for patterns and trends without setting a specific prior end goal.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>An explanatory analysis, on the other side, is the kind of data visualization that we create when we have an end goal in mind. There's something specific we want to convey to our audience.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this article, I'll focus on the explanatory type of analysis and share best practices for creating this kind of data visualizations.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="understanding-the-context">Understanding the Context</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Before rushing ahead to start creating the data visualizations, it's important to take a step back and understand the context.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You should be able to answer the following questions:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Who? </strong>Who is our audience? Are they high-level people; is the audience biased or not; do they have all the background information needed, etc;</li><li><strong>What? </strong>What is the point your audience needs to understand, what are the points we want them to look at so they can take action afterward, etc;&nbsp;</li><li><strong>How? </strong>How can I pass the intended message as clearly as possible to my audience?</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="choosing-an-effective-visual">Choosing an Effective Visual</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Once we have a clear idea of what we want to transmit and know the audience well, it's time to choose the most effective visual.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh4.googleusercontent.com/fXXJjZamebT7ezrfMJxY2fFDTqnS5hdBrPX4oJPokTHY-b0m7JB_R28De-uWtZdojsyeA20FhP2K27K3euQ2T82KtQK257y3ZSWn_8HsQeE-puM-BDEZK4geEbo86yT6ZHCwqp76" alt="data visualization simple text"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Simple Text</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>When there are only a few numbers to convey, simple text can be a great way to emphasize the message.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Rather than choosing bars, lines or any other kind of over-complicated visualization that can distract our audience from the main purpose, opting for simple text-only gives more emphasis to the specific numbers and messages we want to transmit.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: When opting for simple text, think about whether you should highlight the main number, make it bigger or smaller, and how much size and/or color difference should it have in relation to the surrounding words and numbers so that it is as easy as possible to interpret its value and importance.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh4.googleusercontent.com/bv_b3bE2YsMkAELgBjqFuFCP8BF7xoeyBp7uD1OF2l4otc2MT7pXXHkbNqsLWr2269K3z3LWCzcNdTd_DXEwXFSduvPQ4mJMcx1EPeOvbvC0f-l1MFMfp20z0TgpQyvwqhhGBdGk" alt="data visualization table"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Table</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Tables are a great visualization tool to succinctly communicate multiple messages to a mixed audience with different goals. The emphasis should be put on the data and not on the design. As the table is quite heavy by itself, you want to take the attention away from the table and lure your audience's attention to the data.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: Consider going with a more minimal design in order not to distract your audience.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh6.googleusercontent.com/Ni8tIw9WtXsUPRMl5ObAbVSSGYV9KBQW9VwkoQZ6ZzX-ASnAgVw4IWqu_3qgY29_NETHYoU7h2VCET_QdSRP4vzVhmG6bO_1LKfOWXyUnoumjzeSMg0VrfYTkmOepNKY3qYBuyyY" alt="data visualization heatmaps"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Heatmaps</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Heatmaps are a powerful alternative to tables. They're a great tool if we want our audience to compare or understand the differences in values quickly.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: Create a heatmap using a color scheme with just one color and different saturation levels for each order of magnitude. Alternatively, you can opt by using multiple colors, which will bring more attention to the differences in the numbers' magnitude.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh3.googleusercontent.com/n-FpwsDWdeCQnMTUQaYe7-56oPkEuoowq5HNp9r1s5uXreBICnseIdcbBtBBEi4y1nisMgITJRe24mXEfnzc961eanxlHvNv1p4utgJ4zet0Es9HlVm-nrawMRZsgjzsTD0gpZho" alt="data visualization scatterplot"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Scatterplot</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Scatterplots are a great way to show the relationship between two variables. Using this type of tool, you can easily show the relationship between two variables, if they're proportional, not proportional, semi-proportional, or if there's no obvious correlation between the two.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: If there are more than two variables, you can use color to show the relationship to the third dimension, but if there are more than three variables, a scatterplot isn't the best option.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh4.googleusercontent.com/JNls9rpbuRoOaGMGT61AwH6o87SUwoTBoV3H3S-edb4y_vHzcTJdjvy1rX0nXPuGI0iukLe6jJoUsoeiHZ7EUO1UQg6i6n-DIEBaKgPo_Vdtiz5SWMhamkvDnjNMjzB0Dibf0nno" alt="data visualization line graph"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Line Graph</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Line graphs are quite common as they're one of the best ways to show change over time. They make it easy to see whether your measures are going up or down and can be incredibly powerful if you have more than one category to compare over time.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, try not to add too many categories at once to avoid the "spaghetti" effect, where categories become hard to distinguish.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: Avoid using too many different colors at once, but instead look for the category you wish to highlight and choose a different color for that one only.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh3.googleusercontent.com/H_8TdqfedCmOLP-IUZfN-UrWIorbot6ZaYscoN08VKsmSuDp8utfFbNMtdvIUw0e0QkwevVE12UlYAEdEeuxv3SIRUChpk3y3NCNo2oOXh-ELXg_YsXdLmzbN2I3KDuH88kfkDvR" alt="data visualization slope graph"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Slope Graph</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Slope graphs are best used to show the relative variation of multiple categories across two time periods or points of comparison. They make it easy for your audience to see the relative increase or decrease of a category over a period of time. The same "spaghetti" effect can appear in a slope graph, so avoid adding too many categories of colors in one graph.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: Highlight the category you want your audience to pay attention to the most.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh5.googleusercontent.com/oksiRysxD0puloJqa7i8WwnLlPlhV_R9Iv0k7ZcM-BVxPmuFA00ZrMyCmpmbwHMQCqzxsJV_rFi8sPYyQRAFsNDEGWB-YCXXj28qdWscPhQs0axRBtFrQmx0niIZhQsPS8J3wt7R" alt="data visualization bar chart"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Bar Chart</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Bar charts are among the most common and popular types of charts, making it one of the easiest ways for an audience to compare categories. Often, people are tempted to use more complicated visuals to make data look fancier and more elaborate, but sometimes, and almost always, the simpler option is the better option. The greatest thing about bar charts is that they convey data straightforwardly, making it easy for your audience to understand what you're trying to convey without wasting mental effort to make sense of the graph itself.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: The chart should always have a zero baseline to allow an accurate comparison.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh4.googleusercontent.com/R3Qy3xszkhLsJsFC283g8G5WMwilYtS1IPC7oA36E183LF4sOZVgMj7pQANAr8UoKZsK6jjhR39ugOF2U-nj0GPr5F509UqIy6WexONNLhJczlPfn5v9fUpwCsECbW2I6NtlTV4y" alt="data visualization stacked vertical bars"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Stacked Vertical Bars</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Stacked vertical bars allow the comparison between totals across categories and to see each sub-component's contribution to the total. You can structure them as absolute numbers or with columns summing to 100%.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: Pay attention to the order of categories. A good practice is to always put the category you want to highlight right after the zero axis, so it's easier to compare with other categories.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh4.googleusercontent.com/GCSPHIpdN-VJ-LT1GfYB1YXZOsK3CQlH3KB5VnH7L1eFXBiKZn0pgDpbpqEL3wGiRABTa5-w6KIUSKW-wLgNBJED4lF97yDvhO0fVlDMwQE-xt-ridHc-_GDFGT1x5ErKK1wmN6_" alt="data visualization horizontal bars"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Horizontal Bars</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Horizontal bars are the best visuals for comparing categorical data. One thing to take in mind is that the data is processed in "z" shapes, meaning, the first place people look when looking at this type of graph will be the top left.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: Place the most relevant category at the top to make it more visible to your audience.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3778,"sizeSlug":"large","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter size-large"><img src="https://content.adevait.com/wp-content/uploads/2020/11/Screenshot_1.png" alt="stacked horizontal bars" class="wp-image-3778"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Stacked Horizontal Bars</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Stacked horizontal bars are best used to show the totals across different categories, giving a sense of the subcomponents. Help readers visualize the key part of your large data set more easily by placing it on the top since it will be the first place to be screened as users look at your visual.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Tip</strong>: Equivalent subsections should be in the same color in each bar, so that they can be easily compared across categories.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3779,"sizeSlug":"large","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter size-large"><img src="https://content.adevait.com/wp-content/uploads/2020/11/Screenshot_2.png" alt="pie charts" class="wp-image-3779"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>⚠️ Avoid Pie Charts ⚠️</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Pie charts make it difficult to understand each category's magnitude, especially when there are several categories or limited variation.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The one time a pie chart can be helpful is if we only have one category and want to show the percentage out of the total.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="how-to-make-your-visuals-simpler-lighter-and-on-point">How to Make Your Visuals Simpler, Lighter, and On-Point</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>There's a quote by Antoine de Saint-Exupéry that goes:</p>
<!-- /wp:paragraph -->
<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><em>Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away</em>.</p></blockquote>
<!-- /wp:quote -->
<!-- wp:paragraph -->
<p>When preparing a data visualization, the designer or the client may be put off by the large white spaces on the presentation and feel tempted to fill in the blanks with more visualizations. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, the more things you add, the more difficult it will be for your users to process the information and find the key insights you are trying to convey.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As a rule of thumb, a good tip is to remove everything that doesn't add value.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, let's take a look at the chart below and try to simplify it:</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Step-by Step Tips</h3>
<!-- /wp:heading -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh3.googleusercontent.com/eIiTz46mb_ZabatC60EzmcOtAhyZFOXnwF_K2dFzG5be25fjryxpqIqa2xkl1MvpIOELRXnpmRPi1abZVGwse5mtabq-m7zVl5O3Bz2n5Q1AThWqrIzbI9ux49Tf7sl3fscc0vqR" alt="data visualization best practices"/></figure></div>
<!-- /wp:image -->
<!-- wp:list {"ordered":true} -->
<ol><li>The first tip for making the graph easier to understand is to <strong>remove the borders</strong> to make it less cluttered.&nbsp;</li><li>The second tip is to <strong>remove the gridlines</strong>. This can be a matter of taste, depending on the client or the data analyst, or on the graph's purpose, but in general, removing the gridlines can make the graph easier to absorb.&nbsp;</li><li><strong>Remove the data markers</strong>. If you want to show a trend, in this case, an increase in sales over time, there's no need for data markers. When you have a data marker for every possible point it creates too much information, and it can confuse your users.&nbsp;</li><li><strong>Clean the axis</strong>. As we can see from the example, on the x-axis, we have numbers repeating, in this case, the year 2019. On the y-axis, we have all the numbers displayed in a longer form, which doesn't bring any value to your audience. There's a way to <strong>make the axes simpler</strong>, and that's by converting the numbers into a shorter form (10, 000 --&gt; 10K) and the dates from numerical values into the name of months (01-2019 --&gt; Jan), placing the year only once underneath.</li><li>Also, <strong>keep an eye on the colors you add to your graph</strong>. In the example, one category is colored in yellow, while the second is in blue. Doing so will make it easier for your audience to compare the two categories.&nbsp;</li><li>Finally, <strong>label your data correctly</strong> to make it easier for your audience to read and understand the data visualization. In our example, instead of having the categories shown on the top left side, it's better to add them at the end of the graph lines in a matching color to make it easier to compare the data.&nbsp;</li></ol>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Our graph now looks like this:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh3.googleusercontent.com/FU0HqIHcC1AMHnL1V2sytpadbMyfbixNJJtx_sBUCm3Vq3UTP2sBZRr7oMZWxn64KqQgfZ61FoXUk2Rn3U3amg1k1AE7VLBZ55P-ZtMbXTm4Ir8cEFC6O28wXZNCpgYPQ4gRyovT" alt="data visualization best practices"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Simpler, lighter, and on-point.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="preattentive-attributes">Preattentive Attributes</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Preattentive attributes are visual properties that our mind processes effortlessly. According to science, it takes less than 500 milliseconds for the eye and the brain to process a preattentive property of any image.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For data analysts and <a href="https://adevait.com/designers" target="_blank" rel="noreferrer noopener">graphic designers</a>, this means that these preattentive attributes can be used to make it easier for users to understand what is presented through the design. Instead of consciously processing all the data, users can now find valuable insights unconsciously.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can play with these preattentive attributes to draw attention to which element you want your audience to look at and focus on.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Let's look at the example below:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh3.googleusercontent.com/s79ok-mACv8jUSqbqZLYrgw-vaczJ28_BkeSE1UI6nBI1CfJouNl-bWc1HZmPvM2-YOKGteiJDjgF6V0bzn8CTsO3VK3u6z_rYEJB-Bea-wcLZwCnrlo8K2lQSt3tGu9fRrE0lDy" alt="data visualization preattentive attributes"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>If you look on the left side of the image, and someone asks you: <em>how many eighths are there in the photo? </em>Will you be able to tell?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now, look on the right side of the photo and imagine someone asks you the same question. It's easier, right?&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you want to make a clear point to your audience, make the job easier for them, rather than make them process all the numbers one by one and expect them to arrive at the same conclusion.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Some of the most effective preattentive attributes that you can use in your data visualizations include:</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter"><img src="https://lh4.googleusercontent.com/thyeE8pDieB8fSvIFqcIv-MXpkVfE48Shnish6QCpb8zi2SCXEbK7uqpLJWq6Q6N1HvM2Z3XqBJ-rDO92Hy8NdoDR0lDWmft4_9CF7ppOefpSOZVDKCuR49qqNjSTTN1_Yz7h1ih" alt="data visualization shapes"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Shapes</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>With shapes, you can manipulate, for example, an object's size to indicate its importance in a data set, making it larger. In the same way, you can make it smaller and reduce its importance.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3780,"sizeSlug":"large","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter size-large"><img src="https://content.adevait.com/wp-content/uploads/2020/11/Screenshot_4.png" alt="data visualization text" class="wp-image-3780"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Text</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You can do something similar with text, too. For example, you can add text in bold, italic, underlined, in a different color, or use spatial separation to make it stand out. However, be sure not to use all of the techniques at once as you may confuse your audience.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="additional-design-tips">Additional Design Tips</h2>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>Colors should be used in moderation, or they will lose their preattentive value.&nbsp;</li><li>Different colors affect humans' emotions differently. For example, red conveys boldness, while purple conveys wisdom.&nbsp;</li><li>A set of colors should be chosen, and each color used consistently for the same purpose.&nbsp;</li><li>Use white space strategically. Having white space in your data visualization is like making a pause while talking. It's a great way to avoid overwhelming users and giving them space to process relevant information.&nbsp;</li><li>Take advantage of contrast. If you use it wisely, it can be super powerful in drawing attention to where you want people to look at.&nbsp;</li><li>Make sure your elements are aligned. Alignment creates clean lines that help establish a sense of cohesion and unity, making the visualization easier to process overall.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="key-takeaways">Key Takeaways</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To start data visualization without knowing the best practices is like packing for a trip without knowing where you're going.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Knowing the climate of the country where you're traveling will help you pick the most suitable clothes. Knowing your audience and your purpose will help you create data charts and graphs that are most useful and understandable.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Should I use a scatterplot or a slope graph? How many colors are too many? Should I remove the gridlines? Do I have to start my y-axis at zero?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Your data visualization efforts will prove far more successful once you educate yourself on the best practices. So set yourself up for success by learning as much as you can about "visual grammar" and offer data visualizations that are both useful and visually appealing.</p>
<!-- /wp:paragraph -->
<!-- wp:html -->
<iframe width="600" height="350" src="https://www.youtube.com/embed/Q00I9Z1_bp8?controls=0" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<!-- /wp:html -->
<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph --> ]]></description>
<category>Data Science</category>
<author>Rita Viegas</author>
<pubDate>Mon, 09 Nov 2020 23:27:20 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Change Management in Software Development Projects ]]></title>
<link><![CDATA[ https://adevait.com/software/change-management-software-development-projects ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>Here's how to practice effective change management in software development projects, every time, any time.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Customers change their minds. The competitive landscape shifts. New and better technology enters the market.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In the <a href="https://adevait.com/blog/remote-work/adopting-agile-the-latest-reports-about-the-popular-mindset" target="_blank" rel="noreferrer noopener">Agile development</a> world, change is constant. New <a href="https://adevait.com/software/functional-non-functional-requirements" target="_blank" rel="noreferrer noopener">non-functional and functional requirements</a> can appear unexpectedly, while established requirements can shift multiple times. Failing to manage those new requirements can lead to project failure. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To avoid this scenario and build a high-quality product, <a href="https://adevait.com/software" target="_blank" rel="noreferrer noopener">software development teams</a> must deal with the dynamic work environment.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>How?</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>By using a streamlined approach to change management.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In this article, we'll take a look at what change management is and why it is important. Then, we'll talk about the importance of establishing a framework for managing the change process, and offer a few tips for effective change management in software development projects.</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"af5598da","classMigrate":true,"mappingHeaders":[true,true,false,true,true,true],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022What Is Change Management?\u0026nbsp;\u0022,\u0022link\u0022:\u0022what-is-change-management\u0022,\u0022content\u0022:\u0022What Is Change Management?\u0026nbsp;\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Why Is Change Management Important?\u0022,\u0022link\u0022:\u0022why-is-change-management-important\u0022,\u0022content\u0022:\u0022Why Is Change Management Important?\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Establishing a Framework to Manage the Change Process\u0026nbsp;\u0022,\u0022link\u0022:\u0022establishing-a-framework-to-manage-the-change-process\u0022,\u0022content\u0022:\u0022Establishing a Framework to Manage the Change Process\u0026nbsp;\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Identify the Change Type\u0022,\u0022link\u0022:\u0022identify-the-change-type\u0022,\u0022content\u0022:\u0022Identify the Change Type\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Discuss and Prioritize the Changes\u0026nbsp;\u0022,\u0022link\u0022:\u0022discuss-and-prioritize-the-changes\u0022,\u0022content\u0022:\u0022Discuss and Prioritize the Changes\u0026nbsp;\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Review the Current Workload and Organizational Structure\u0022,\u0022link\u0022:\u0022review-the-current-workload-and-organizational-structure\u0022,\u0022content\u0022:\u0022Review the Current Workload and Organizational Structure\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Review and Communicate the Risks to the Stakeholders\u0026nbsp;\u0022,\u0022link\u0022:\u0022review-and-communicate-the-risks-to-the-stakeholders\u0022,\u0022content\u0022:\u0022Review and Communicate the Risks to the Stakeholders\u0026nbsp;\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Incorporate Testing of Changes to Avoid Incidents\u0022,\u0022link\u0022:\u0022incorporate-testing-of-changes-to-avoid-incidents\u0022,\u0022content\u0022:\u0022Incorporate Testing of Changes to Avoid Incidents\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Use the Right Tools to Track Changes and Collect Data\u0022,\u0022link\u0022:\u0022use-the-right-tools-to-track-changes-and-collect-data\u0022,\u0022content\u0022:\u0022Use the Right Tools to Track Changes and Collect Data\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Review, Analyze and Improve the Process\u0026nbsp;\u0022,\u0022link\u0022:\u0022review-analyze-and-improve-the-process\u0022,\u0022content\u0022:\u0022Review, Analyze and Improve the Process\u0026nbsp;\u0022,\u0022level\u0022:1}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-af5598da" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#what-is-change-management">What Is Change Management?&nbsp;</a></li><li><a href="#why-is-change-management-important">Why Is Change Management Important?</a></li><li><a href="#establishing-a-framework-to-manage-the-change-process">Establishing a Framework to Manage the Change Process&nbsp;</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="what-is-change-management">What Is Change Management?&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Change management is a systematic approach towards dealing with a change. It involves coordinating resources, applying tools and managing knowledge in order to effectively drive organizational success.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="why-is-change-management-important">Why Is Change Management Important?</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Operational excellence</strong>. In many cases, organizations focus on doing many things at once, instead of focusing on the right things. Change management helps organizations focus on doing the right thing in accordance with the business strategy.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Management of risk</strong>. Managing change is really about managing risk. When deciding on implementing a change, the team involved in the process has to assess whether the change would bring any business value to the company. If it doesn't, then that's a risk it shouldn't be taken.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Overall strategy</strong>. The change has to support the overall strategy of the business. The change manager has to understand the direction the business is going in to know whether a change needs to be implemented or added to the "skip" list.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="establishing-a-framework-to-manage-the-change-process">Establishing a Framework to Manage the Change Process&nbsp;</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Change management in software development projects doesn't have to be challenging, expensive, and process-heavy.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If you take a framework approach to change management, you can quickly and easily reduce incidents while keeping processes agile and minimizing work disruptions.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here are seven items I'd like to recommend that should be part of your change management framework:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Identify the Change Type</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The first thing that should be on the agenda during your first change advisory board (CAB) meeting is identifying the change type.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Generally, there are three major types of changes: standard, urgent, and normal changes.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><strong>Standard changes</strong> are changes to a service or to the IT infrastructure. The risks and the implementation process of this type of change are known upfront.&nbsp;</li><li><strong>Urgent changes</strong>, on the other hand, are the opposite of standard changes. They indicate a crisis or an opportunity that should be addressed as soon as possible, with as little risk as possible. Before you implement an urgent change, you need to get specific approvals and authorization from stakeholders. Urgent changes follow a similar change management process flow as normal changes, but at an accelerated timescale. So, at the end of the day, how well you can manage urgent changes will depend on the organization's agility.</li><li><strong>Normal changes</strong> are not a standard or an urgent change. Although they're quite common, they require unique and novel approaches. These changes have to go through a change process before they can be approved and implemented.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Identifying the type of change is critical for establishing communication with everyone involved in the change management process, getting authorization, calculating the risks, etc. The whole team needs to be on the same page so that proper steps are taken for the organization's health.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Discuss and Prioritize the Changes&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Don't introduce too much change at once. Sometimes, your organization can't support too many changes, or your customers can't accept too much change.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, if you apply a change to your application twice every month and ask your customers to test it, they may not be fans of so much change in such a short period. They may prefer changes that happen twice a year, or once a year, so they can consume them correctly.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If a user opens your app and sees a new update every time, they may eventually get frustrated and even stop using your app altogether.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Assess the risks and impact of each change, communicate with the stakeholders, and finally come to a decision about which change should be prioritized and which one should be put on the "postpone" list.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Review the Current Workload and Organizational Structure</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>People are the most important ingredient in the change management process. Sometimes, your developers might be against the change from taking place, whether because they don't understand it or because their current workload doesn't allow for it.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, getting collaboration from them is critical.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Your developers are key to delivering and supporting the change. That's why you have to make sure they're on-board. They don't just have to be compliant with the change process but believe in it so they can do their best work.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Next, do know your resources. Understand the capabilities and resources you have in your organization: the infrastructure, the people, the financial budget, and everything else.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Review and Communicate the Risks to the Stakeholders&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Change management shouldn't happen in a silo.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Coordination and collaboration across the organization when change management is taking place is crucial. You want to make sure the stakeholders are aware of the change that's about to take place and inform them of the risks associated with the change.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Not communicating the risks to stakeholders can lead to incidents and overall disruptions to the business at the end of the day.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Incorporate Testing of Changes to Avoid Incidents</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Deploying to all regions at the same time has many risks. A breaking change can potentially bring every region down and the customer impact can be substantial. That's a scenario you want to avoid.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A better alternative is to deploy in stages, with a fair amount of testing, to avoid incidents.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>For example, what many companies like to do is to first deploy the change to an internal production-like environment, then to a specific region in production, and when they're confident that the change is safe, to deploy it to all regions.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>You can be confident that the change is working seamlessly in all environments and regions by monitoring, anomaly detection, and alerting. In case something goes wrong, the monitoring tools will detect the failure and trigger an automatic alert.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Use the Right Tools to Track Changes and Collect Data</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To take some of your team's burden off their back, using the right tools and technologies to track changes and collect data can be of great help.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Change management tools offer a structure for the often chaotic process of change that affects teams, businesses, and organizations.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Change management tools and technologies can replace the unnecessary six-layer approval process and weeks of back-and-forth with compliance approval boards. They will ensure non-compliant changes don't see the light of day.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Review, Analyze and Improve the Process&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>After the change is implemented, a good tip is to discuss how the change went, discuss any bottlenecks, and see how you can improve the process.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Ask questions such as:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Which changes were successful?</li><li>What were the most common changes?</li><li>What was the average time to implement the changes?</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Learn from your processes so that you can continuously improve your <a href="https://adevait.com/software/improving-software-engineering-velocity" target="_blank" rel="noreferrer noopener">velocity in software development</a> and do better for your company and your customers next time.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Software</category>
<author>Katerina Trajchevska</author>
<pubDate>Sun, 18 Oct 2020 08:56:45 +0000</pubDate>
</item>
<item>
<title><![CDATA[ No Office, No Problem: How to Onboard New Developers Remotely ]]></title>
<link><![CDATA[ https://adevait.com/blog/agile-work/how-to-onboard-new-developers ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>When it comes to how to onboard new developers remotely, there's not a magical strategy you can put in place. Instead, it's a set of best practices that will help your new hire feel included, meet your company culture, and get up to speed with how work is performed.</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In 2017, a young developer posted a query on Reddit on the <em>computer science career questions </em>subreddit. He intriguingly wrote: <em>Accidentally destroyed the production database on the first day of a job, and was told to leave, on top of this I was told by the CTO that they need to get legal involved, how screwed am I?</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Right after the story went viral, the tech news site <a href="https://www.theregister.com/2017/06/05/dev_accidentally_nuked_production_database_was_allegedly_instantly_fired/" target="_blank" rel="noreferrer noopener">The Register ran a poll</a> asking who should be fired. <strong>A whopping 45% voted to fire the CTO</strong>.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The Reddit commenters were right; if a new employee can cause such chaos into your company, it's your fault and not his.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To be more precise, <strong>the main fault is in your employee onboarding process</strong>.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://www.saplinghr.com/10-employee-onboarding-statistics-you-must-know-in-2020#:~:text=Research%20by%20Glassdoor%20found%20that,productivity%20by%20over%2070%20percent.&amp;text=A%20strong%20employee%20onboarding%20process,they%20can%20be%20productive%20sooner." target="_blank" rel="noreferrer noopener">Studies show</a> that organizations with a strong onboarding process <strong>improve new hire retention by 82%</strong> and <strong>productivity by over 70%</strong>. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>When it comes to onboarding remote employees, the lack of in-person communication can make things even more challenging.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>However, with the right best practices in place, you'll manage to equip the new developer with the knowledge and confidence they need to get started as a new team member and get them excited about their new position.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Here are step-by-step instructions for how to onboard new developers remotely and make them feel like a part of the team even before their first day of work:</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"a2a8cf6c","classMigrate":true,"mappingHeaders":[false,true,false,true,true,true],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022Pre-Onboarding Checklist\u0022,\u0022link\u0022:\u0022pre-onboarding-checklist\u0022,\u0022content\u0022:\u0022Pre-Onboarding Checklist\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Welcome the New Developer on Zoom\u0026nbsp;\u0022,\u0022link\u0022:\u0022welcome-the-new-developer-on-zoom\u0022,\u0022content\u0022:\u0022Welcome the New Developer on Zoom\u0026nbsp;\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Help the Developer Learn About the Company Culture\u0022,\u0022link\u0022:\u0022help-the-developer-learn-about-the-company-culture\u0022,\u0022content\u0022:\u0022Help the Developer Learn About the Company Culture\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Help Them With the HR Paperwork\u0022,\u0022link\u0022:\u0022help-them-with-the-hr-paperwork\u0022,\u0022content\u0022:\u0022Help Them With the HR Paperwork\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Work Out Logistics\u0022,\u0022link\u0022:\u0022work-out-logistics\u0022,\u0022content\u0022:\u0022Work Out Logistics\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Give Access to Your Tools and Software\u0022,\u0022link\u0022:\u0022give-access-to-your-tools-and-software\u0022,\u0022content\u0022:\u0022Give Access to Your Tools and Software\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Send Them a Welcome Package\u0022,\u0022link\u0022:\u0022send-them-a-welcome-package\u0022,\u0022content\u0022:\u0022Send Them a Welcome Package\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022First-Day Checklist\u0022,\u0022link\u0022:\u0022first-day-checklist\u0022,\u0022content\u0022:\u0022First-Day Checklist\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Share a New Hire Announcement\u0022,\u0022link\u0022:\u0022share-a-new-hire-announcement\u0022,\u0022content\u0022:\u0022Share a New Hire Announcement\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Start by Giving Them Small, Non-Critical Tasks\u0022,\u0022link\u0022:\u0022start-by-giving-them-small-non-critical-tasks\u0022,\u0022content\u0022:\u0022Start by Giving Them Small, Non-Critical Tasks\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Set up Knowledge Sharing\u0022,\u0022link\u0022:\u0022set-up-knowledge-sharing\u0022,\u0022content\u0022:\u0022Set up Knowledge Sharing\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022First-Week Checklist\u0022,\u0022link\u0022:\u0022first-week-checklist\u0022,\u0022content\u0022:\u0022First-Week Checklist\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Arrange Weekly 1-on-1 Meetings\u0022,\u0022link\u0022:\u0022arrange-weekly-1-on-1-meetings\u0022,\u0022content\u0022:\u0022Arrange Weekly 1-on-1 Meetings\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Arrange Daily Check-in Meetings With the Tech Team\u0022,\u0022link\u0022:\u0022arrange-daily-check-in-meetings-with-the-tech-team\u0022,\u0022content\u0022:\u0022Arrange Daily Check-in Meetings With the Tech Team\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Assign a Buddy\u0022,\u0022link\u0022:\u0022assign-a-buddy\u0022,\u0022content\u0022:\u0022Assign a Buddy\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022First-Month Checklist\u0022,\u0022link\u0022:\u0022first-month-checklist\u0022,\u0022content\u0022:\u0022First-Month Checklist\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Have Regular One-on-One Manager Meetings\u0022,\u0022link\u0022:\u0022have-regular-one-on-one-manager-meetings\u0022,\u0022content\u0022:\u0022Have Regular One-on-One Manager Meetings\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Make Room for Some Fun\u0022,\u0022link\u0022:\u0022make-room-for-some-fun\u0022,\u0022content\u0022:\u0022Make Room for Some Fun\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Collect Feedback\u0022,\u0022link\u0022:\u0022collect-feedback\u0022,\u0022content\u0022:\u0022Collect Feedback\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Finally\u0022,\u0022link\u0022:\u0022finally\u0022,\u0022content\u0022:\u0022Finally\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-a2a8cf6c" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#pre-onboarding-checklist">Pre-Onboarding Checklist</a></li><li><a href="#first-day-checklist">First-Day Checklist</a></li><li><a href="#first-week-checklist">First-Week Checklist</a></li><li><a href="#first-month-checklist">First-Month Checklist</a></li><li><a href="#finally">Finally</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="pre-onboarding-checklist">Pre-Onboarding Checklist</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Welcome the New Developer on Zoom&nbsp;</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The first step of an effective onboarding process is to welcome the new hire to the team via an e-conferencing platform like Meet and Zoom.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>They're probably anxious about their first day at work, and a Zoom call can be an excellent way for you to answer all their concerns.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>During the call, inform the new hire of:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>their tasks for the first few weeks at work</li><li>normal working hours</li><li>their team</li><li>your coding standards</li><li>your expectations</li><li>the communication and collaboration tools you'll be using</li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Help the Developer Learn About the Company Culture</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Company culture is the "personality" of your company. It's your shared values, goals, attitudes, and practices. It would help if you got the new developer acquainted with your culture so that they can perform well and accelerate at their job.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To help them understand your company culture, share:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Your digital employee handbook.</li><li>Presentation on company values, mission, and vision.</li><li>Videos from your all-hands meetings.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>It can also help if the new developer attends a one-on-one meeting with someone from your company's leadership. Your CEO, for example, can talk about the history of the company, what are its long-term goals, the leading product/service of the company, etc.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Help Them With the HR Paperwork</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Many developers want to start coding right away and wouldn't want to spend their first day signing HR documents. One way of getting HR paperwork out of the way is by sending it to the new hire for signing before the start date.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The new hire can sign employment contracts and other legal documents digitally by using e-signature tools like <a href="https://www.hellosign.com/" target="_blank" rel="noreferrer noopener">HelloSign</a> and <a href="https://www.docusign.com/" target="_blank" rel="noreferrer noopener">DocuSign</a>. </p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Work Out Logistics</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>If you are sending the new hire computers and other equipment for their at-home working station, plan this beforehand. Order the equipment a few weeks before the developer's start date to ensure they get it on time.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Give Access to Your Tools and Software</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>You don't want your new hire to start their first day confused about how to enter the work systems. Get the technical stuff out of the way by sending them login details and invitations to access the company's project management systems, email, chat apps, learning management systems, etc.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Send Them a Welcome Package</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Another optional item on your <em>How to onboard new developers</em> checklist is to send a welcome package. A welcome package can make the new developer feel like a part of the team.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Send the package before the new hire's first day of work and include:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>A welcome letter from the team or the CEO.</li><li>Branded merchandise, such as T-shirts, coffee mugs, note pads, hats, etc.</li><li>Personalized gifts like headphones, gift cards, books, etc.&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:image {"id":3697,"width":366,"height":488,"sizeSlug":"large","className":"is-style-default"} -->
<figure class="wp-block-image size-large is-resized is-style-default"><img src="https://content.adevait.com/wp-content/uploads/2020/09/image_from_ios-768x1024.jpg" alt="how to onboard new developers welcome package" class="wp-image-3697" width="366" height="488"/></figure>
<!-- /wp:image -->
<!-- wp:heading -->
<h2 id="first-day-checklist">First-Day Checklist</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Share a New Hire Announcement</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>When you <a href="https://adevait.com/software" target="_blank" rel="noreferrer noopener">hire a software developer</a>, they may lack the confidence to introduce themselves to the team. Make them feel welcome and excited by sending a new hire announcement.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>A simple message on Slack in a #general channel will work just fine. By doing so, every team member will get the chance to say hello and send a welcome message to the new hire.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Along with sending the new developer's name, share a few fun facts about them as well:&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Where were they born and where do they live now?</li><li>What do they enjoy doing in their free time?</li><li>What's their role?&nbsp;</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>For example, you can say something like:</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>Let's wish a warm welcome to [name of employee]. She will be joining our company as a <a href="https://adevait.com/shopify" target="_blank" rel="noreferrer noopener">Shopify developer</a>. She's a digital nomad currently based in Canggu who loves surfing and reading fantasy books. </em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Introducing them to everyone, along with sharing their interests, can be a fantastic way for remote members with shared interests to bond quickly.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Start by Giving Them Small, Non-Critical Tasks</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Make sure the first task you assign the new developer is an easier task. For example, their task can be to develop a small, well-defined feature.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>If they do it right, the achievement will build their confidence and make them more motivated at the job.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>On the plus side, they'll experience the process of developing at your company, from code review to production deployment phases.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another great idea is to try to reduce the stress and anxiety the developer may be feeling by assigning them tasks for the first few weeks on the job.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Set up Knowledge Sharing</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To provide team members with the information they need to do their jobs effectively, you should set up knowledge sharing. One great way are wikis that contain everything a new employee will need to know in order to join a team.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>From tool guides and contact lists to software tutorials and common bugs, document everything that requires step-by-step instructions to replace long employee orientation meetings. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="first-week-checklist">First-Week Checklist</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Arrange Weekly 1-on-1 Meetings</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Trust is a critical ingredient that has to exist from day one. When you're remote and don't have the chance to connect in-person, one way of building trust is by arranging weekly one-on-one meetings between you and the new hire.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Use the time you have on these meetings to share feedback, discuss difficulties, celebrate milestones, and more.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Arrange Daily Check-in Meetings With the Tech Team</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Daily check-in meetings should be another item on your developer onboarding checklist. You can sync up on what's done, what's happening that day, and the state of the project. The new developer will remain up-to-date with everything important that's happening on the team and feel more connected with other team members.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Assign a Buddy</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>A smart move would be to pair the new developer with a junior developer instead of a senior developer. Junior developers have recently gone through the onboarding experience and can provide better advice to the new hire.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Another idea is assigning a mentor to the new hire who will be their go-to person for everything work and culture-related for at least two months.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Instead of the junior developer fixing the new hire's problems for them, consider introducing pair programming sessions. Pair programming is an amazing opportunity to share knowledge and for developers to collaborate in solving a problem.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="first-month-checklist">First-Month Checklist</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Have Regular One-on-One Manager Meetings</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Regular one-on-one meetings between you and the new hire are a great way to build trust, share feedback, and form a long-lasting relationship with the new developer.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once per month, jump on a call to check whether they're integrating well within the company or facing any difficulties.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Make Room for Some Fun</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We at Adeva like to keep things fun and use <a href="https://help.donut.ai/en/articles/597029-what-are-donut-intros-how-does-donut-work#:~:text=Donut%20intros%20are%20a%20simple,virtual%20coffee%20over%20video%20chat!" target="_blank" rel="noreferrer noopener">the Donut integration</a> for Slack that randomly pairs people across the company. On a regular basis (bi-monthly), Donut will select people from our pairing channel and encourage them to schedule a video call or talk about something cool in their private Slack channel.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><a href="https://adevait.com/blog/remote-work/agile-games-distributed-teams" target="_blank" rel="noreferrer noopener">Team-building activities</a> help our employees feel comfortable with each other to share jokes and opinions.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3704,"sizeSlug":"large","className":"is-style-default"} -->
<div class="wp-block-image is-style-default"><figure class="aligncenter size-large"><img src="https://content.adevait.com/wp-content/uploads/2020/10/slack-desktop@2x-2-1024x571.png" alt="how to onboard new developers donut for Slack" class="wp-image-3704"/></figure></div>
<!-- /wp:image -->
<!-- wp:heading {"level":3} -->
<h3>Collect Feedback</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Providing <a href="https://adevait.com/software/feedback-for-software-developers" target="_blank" rel="noreferrer noopener">feedback for software developers</a> is a critical part of every manager-employee relationship. At the same time, hearing what your software developer has to say about you is equally important. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Your remote onboarding process may be good, but it may not be perfect. To continually improve it, make sure you ask for feedback. Ask them whether they felt confused or frustrated at some stage of the onboarding process. Hopefully, you'll manage to identify major bottlenecks and add more support at those stages. </p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="finally">Finally</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Take the new developer through all of these stages to ensure they don't accidentally destroy the production database on the first day.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Equip them with the tools they need to do their jobs well, assign them their tasks for the first few weeks, and collect feedback to continually improve your onboarding process.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Don't forget to focus on human interaction and the relationship-building aspect of work. Make your new developers feel included, respected, and supported to grow and thrive.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Good luck!</p>
<!-- /wp:paragraph --> ]]></description>
<category>Agile</category>
<author>Tosho Trajanov</author>
<pubDate>Thu, 01 Oct 2020 09:35:17 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Deploying Rust Functions on AWS Lambda ]]></title>
<link><![CDATA[ https://adevait.com/rust/deploying-rust-functions-on-aws-lambda ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p>AWS&nbsp;Lambda&nbsp;is a serverless computing platform that lets you run code without provisioning or managing servers. The platform invokes your code in response to events such as HTTP requests. Currently, there's no official support for&nbsp;Rust&nbsp;programming language on&nbsp;Lambda. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>To run&nbsp;Rust&nbsp;code on&nbsp;Lambda, we will have to build a custom runtime that will run our code. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>This guide will help you build for&nbsp;Lambda&nbsp;in a quick and simple way. It is targeted at developers who have a reasonable understanding of&nbsp;Rust&nbsp;and systems programming, and intend to build serverless function on&nbsp;AWS.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>We will build a simple&nbsp;Rust&nbsp;application and deploy it to&nbsp;AWS&nbsp;Lambda. This guide will cover the following:</p>
<!-- /wp:paragraph -->
<!-- wp:group -->
<div class="wp-block-group"><div class="wp-block-group__inner-container"><!-- wp:uagb/table-of-contents {"block_id":"2a4f0952","classMigrate":true,"mappingHeaders":[true,true,false,false,true,true],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022Requirements\u0022,\u0022link\u0022:\u0022requirements\u0022,\u0022content\u0022:\u0022Requirements\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Getting Started\u0022,\u0022link\u0022:\u0022getting-started\u0022,\u0022content\u0022:\u0022Getting Started\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Installing\u0026nbsp;Rust\u0022,\u0022link\u0022:\u0022installing-rust\u0022,\u0022content\u0022:\u0022Installing\u0026nbsp;Rust\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Creating the\u0026nbsp;Rust\u0026nbsp;Program\u0022,\u0022link\u0022:\u0022creating-the-rust-program\u0022,\u0022content\u0022:\u0022Creating the\u0026nbsp;Rust\u0026nbsp;Program\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Cargo.toml\u0022,\u0022link\u0022:\u0022cargotoml\u0022,\u0022content\u0022:\u0022\u003ccode\u003eCargo.toml\u003c/code\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022main.rs\u0022,\u0022link\u0022:\u0022mainrs\u0022,\u0022content\u0022:\u0022\u003ccode\u003emain.rs\u003c/code\u003e\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Testing the\u0026nbsp;Rust\u0026nbsp;Function\u0022,\u0022link\u0022:\u0022testing-the-rust-function\u0022,\u0022content\u0022:\u0022Testing the\u0026nbsp;Rust\u0026nbsp;Function\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Compiling the\u0026nbsp;Rust\u0026nbsp;Project\u0022,\u0022link\u0022:\u0022compiling-the-rust-project\u0022,\u0022content\u0022:\u0022Compiling the\u0026nbsp;Rust\u0026nbsp;Project\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Statically Linked Compilation\u0022,\u0022link\u0022:\u0022statically-linked-compilation\u0022,\u0022content\u0022:\u0022Statically Linked Compilation\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Dynamically Linked Compilation\u0022,\u0022link\u0022:\u0022dynamically-linked-compilation\u0022,\u0022content\u0022:\u0022Dynamically Linked Compilation\u0022,\u0022level\u0022:1},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Deployment\u0022,\u0022link\u0022:\u0022deployment\u0022,\u0022content\u0022:\u0022Deployment\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022Uploading the Function\u0022,\u0022link\u0022:\u0022uploading-the-function\u0022,\u0022content\u0022:\u0022Uploading the Function\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022And That's It!\u0022,\u0022link\u0022:\u0022and-thats-it\u0022,\u0022content\u0022:\u0022And That's It!\u0022,\u0022level\u0022:0}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-2a4f0952" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#requirements">Requirements</a></li><li><a href="#getting-started">Getting Started</a></li><li><a href="#installing-rust">Installing&nbsp;Rust</a></li><li><a href="#creating-the-rust-program">Creating the&nbsp;Rust&nbsp;Program</a></li><li><a href="#testing-the-rust-function">Testing the&nbsp;Rust&nbsp;Function</a></li><li><a href="#compiling-the-rust-project">Compiling the&nbsp;Rust&nbsp;Project</a></li><li><a href="#deployment">Deployment</a></li><li><a href="#uploading-the-function">Uploading the Function</a></li><li><a href="#and-thats-it">And That's It!</a></li></ul></div></div></div>
<!-- /wp:uagb/table-of-contents --></div></div>
<!-- /wp:group -->
<!-- wp:heading -->
<h2 id="requirements">Requirements</h2>
<!-- /wp:heading -->
<!-- wp:list -->
<ul><li>Rust&nbsp;toolchain.</li><li>Docker.</li><li>AWS&nbsp;Account &amp; CLI.</li></ul>
<!-- /wp:list -->
<!-- wp:heading -->
<h2 id="getting-started">Getting Started</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We will need to install&nbsp;Rust&nbsp;and create a simple&nbsp;Rust&nbsp;project.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="installing-rust">Installing&nbsp;Rust</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>To install&nbsp;Rust, we will use the&nbsp;<code>rustup</code>&nbsp;tool.&nbsp;<code>rustup</code>&nbsp;is a tool that manages our&nbsp;Rust&nbsp;toolchain in a consistent way on every platform&nbsp;Rust&nbsp;supports. It enables the installation of&nbsp;Rust&nbsp;from stable, beta, and nightly channels, as well as provide support to cross-compile programs to other targets.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>If you have an existing&nbsp;<code>rustup</code>&nbsp;installation, run&nbsp;<code>rustup update</code>&nbsp;to update your installation.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Once the installation has completed, you will find the&nbsp;Rust&nbsp;toolchain installed in&nbsp;<code>~/.cargo/bin</code>&nbsp;directory. The&nbsp;Rust&nbsp;toolchain includes:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><code>rustc</code>&nbsp;-&nbsp;Rust&nbsp;compiler.</li><li><a href="https://github.com/rust-lang/cargo" target="_blank" rel="noreferrer noopener"><code>cargo</code></a>&nbsp;-&nbsp;Rust&nbsp;package manager.</li><li><a href="https://github.com/rust-lang/rust-clippy" target="_blank" rel="noreferrer noopener"><code>cargo-clippy</code></a>&nbsp;- Linter to catch common mistakes and improve your&nbsp;Rust&nbsp;code.</li><li><code>rustdoc</code>&nbsp;- Project documentation builder.</li><li><a href="https://github.com/rust-lang/rustfmt" target="_blank" rel="noreferrer noopener"><code>rustfmt</code></a>&nbsp;- Formats&nbsp;Rust&nbsp;code, making it easier to read, write, and maintain.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Check your cargo version by running:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>cargo --version
#cargo 1.43.0 (3532cf738 2020-03-17)</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>During installation,&nbsp;<code>rustup</code>&nbsp;will attempt to include the directory in the system PATH environment variable. If the above command fails after successful installation, manually add the directory to system PATH by executing:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Additional toolchains from other distribution channel will be stored in&nbsp;<code>~/.rustup/toolchains</code>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="creating-the-rust-program">Creating the&nbsp;Rust&nbsp;Program</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>We will be using&nbsp;<code>cargo</code>&nbsp;to create a new project. The command&nbsp;<code>cargo new</code>&nbsp;by default starts a new package which we will use to make a binary program.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>cargo new rust_lambda</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The above command will create a project directory (relative to the current directory) called&nbsp;<code>rust_lambda</code>&nbsp;and generate some necessary files.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Our project directory structure should look like:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>rust_lambda/
├── Cargo.toml
└── src
└── main.rs
1 directory, 2 files</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now let's change into our project directory and view the files. Run&nbsp;<code>cd rust_lambda</code>&nbsp;to enter the directory.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3><code>Cargo.toml</code></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>This file contains all the metadata that&nbsp;<code>cargo</code>&nbsp;needs to install and compile our package. This file is also called a&nbsp;<strong>manifest</strong>. By default,&nbsp;<code>cargo new</code>&nbsp;adds two sections to the manifest –&nbsp;<code>[package]</code>&nbsp;and&nbsp;<code>[dependencies]</code>. The package section defines the details about the package (our project).</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The dependencies section defines our package dependencies. You can learn more about&nbsp;<a href="https://doc.rust-lang.org/cargo/reference/manifest.html" target="_blank" rel="noreferrer noopener">the manifest file format here</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&#91;package]
name = "rust_lambda"
version = "0.1.0"
authors = &#91;"Chuma Umenze &lt;hello@chumaumenze.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
&#91;dependencies]</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>We will need to include a few crates in the dependencies section of our manifest file. A crate is a compilation unit in&nbsp;Rust&nbsp;which can be compiled into a binary or library package. We will be using the following crates:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li><code>lambda_runtime</code> – A Rust runtime for AWS Lambda.</li><li><code>serde</code> – Serialization and Deserialization framework for Rust.</li></ul>
<!-- /wp:list -->
<!-- wp:paragraph -->
<p>Add them to your dependencies section. The section should look like this:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&#91;dependencies]
lambda_runtime = "0.2.1"
serde = { version = "^1.0", features = &#91;"derive"] }</code></pre>
<!-- /wp:code -->
<!-- wp:heading {"level":3} -->
<h3><code>main.rs</code></h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>The other file in our project is the&nbsp;<code>main.rs</code>&nbsp;located within&nbsp;<code>src</code>&nbsp;folder. This is where we define our function code. Overwrite the&nbsp;<code>main.rs</code>&nbsp;with the following content. You can also modify the code to your use case.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>use lambda_runtime::{error::HandlerError, lambda, Context};
use serde::{Deserialize, Serialize};
use std::error::Error;
#&#91;derive(Deserialize, Serialize, Clone)]
#&#91;serde(rename_all = "camelCase")]
struct LambdaRequest {
full_name: String,
message: Option&lt;String>,
}
#&#91;derive(Deserialize, Serialize, Clone)]
#&#91;serde(rename_all = "camelCase")]
struct LambdaResponse {
lambda_request: LambdaRequest,
}
fn main() -> Result&lt;(), Box&lt;dyn Error>> {
lambda!(lambda_handler);
Ok(())
}
fn lambda_handler(e: LambdaRequest, _c: Context) -> Result&lt;LambdaResponse, HandlerError> {
let mut e = e.clone();
e.full_name = format!("Hello {name}!", name = e.full_name);
let msg = match e.message {
Some(msg) => format!("Your message is '{msg}'.", msg = msg),
None => format!("You have no message."),
};
e.message = Some(msg);
Ok(LambdaResponse { lambda_request: e })
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The above code is a simple&nbsp;Rust&nbsp;function that greets a user with messages. There are two main function –&nbsp;<code>main()</code>&nbsp;and&nbsp;<code>lambda_handler()</code>. In the lines before the&nbsp;functions, we defined two structs –&nbsp;<code>LambdaRequest</code>&nbsp;and&nbsp;<code>LambdaResponse</code>&nbsp;– they respectively define the structure of request payload the function expects and the type of response our function is returning.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Now we have our function defined, if you try to run the code by executing&nbsp;<code>cargo run</code>, the main function will panic with following error.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>thread 'main' panicked at 'Could not find runtime API env var: environment variable not found'
, &lt;::std::macros::panic macros>:5:6
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>This error occurred because our code expects certain environment variables that exist on&nbsp;AWS&nbsp;Lambda&nbsp;to run. We will resolve it later in this guide.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="testing-the-rust-function">Testing the&nbsp;Rust&nbsp;Function</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Let's write a simple test for our&nbsp;<code>lambda_handler()</code>&nbsp;function. At the bottom of our&nbsp;<code>src/main.rs</code>&nbsp;file, include the following lines:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>#&#91;cfg(test)]
mod tests {
use lambda_runtime::Context;
use super::{LambdaRequest, LambdaResponse};
#&#91;test]
fn test_lambda_handler() {
let expected_response = LambdaResponse {
data: LambdaRequest {
full_name: "Hello Chuma Umenze!".to_string(),
message: Some("Your message is 'It is a simple test'.".to_string())
}
};
let lambda_context = Context {
aws_request_id: "0123456789".to_string(),
function_name: "test_function_name".to_string(),
memory_limit_in_mb: 128,
function_version: "$LATEST".to_string(),
invoked_function_arn: "arn:aws:lambda".to_string(),
xray_trace_id: Some("0987654321".to_string()),
client_context: Option::default(),
identity: Option::default(),
log_stream_name: "logStreamName".to_string(),
log_group_name: "logGroupName".to_string(),
deadline: 0,
};
let lambda_request = LambdaRequest {
full_name: "Chuma Umenze".to_string(),
message: Some("It is a simple test".to_string())
};
// Check the result is ok
let result = super::lambda_handler(lambda_request, lambda_context);
assert_eq!(result.is_err(), false, "Error: {}", result.err().unwrap());
// Confirm the expected values in result
let value = result.ok().unwrap();
assert_eq!(value.data.full_name, expected_response.data.full_name);
assert_eq!(value.data.message, expected_response.data.message);
}
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The above code defines a single test case for&nbsp;<code>lambda_handler()</code>&nbsp;function. Execute&nbsp;<code>cargo test</code>&nbsp;to run the test. We should get an output as follows:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>Compiling rust_lambda v0.1.0 (/Users/chumaumenze/Desktop/rust_lambda)
Finished test &#91;unoptimized + debuginfo] target(s) in 1.41s
Running target/debug/deps/rust_lambda-d2b9fa9d3cb89902
running 1 test
test tests::test_lambda_handler ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2 id="compiling-the-rust-project">Compiling the&nbsp;Rust&nbsp;Project</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>When configuring a custom runtime,&nbsp;AWS&nbsp;Lambda&nbsp;expects an executable file name&nbsp;<code>bootstrap</code>. The executable should be bundled in your deployment package or&nbsp;lambda&nbsp;layers package. We can configure&nbsp;<code>cargo</code>&nbsp;to build our binary as&nbsp;<code>bootstrap</code>&nbsp;instead of using our package name.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In our Cargo.toml, add the&nbsp;<code>autobins = false</code>&nbsp;to the&nbsp;<code>[package]</code>&nbsp;section, then create a new section called&nbsp;<code>[[bin]]</code>&nbsp;with the key-values&nbsp;<code>name = "bootstrap"</code>&nbsp;and&nbsp;<code>path = "src/main.rs"</code>. Your&nbsp;<code>Cargo.toml</code>&nbsp;should have the following structure:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>&#91;package]
....
autobins = false
&#91;&#91;bin]]
name = "bootstrap"
path = "src/main.rs"</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>To facilitates easy cross-compilation of packages, we will use&nbsp;<a href="https://github.com/rust-embedded/cross" target="_blank" rel="noreferrer noopener">rust-embedded/cross</a>. Cross relies on docker to compile our packages to any supported target with minimal setup time.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>cargo install cross</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Specify docker images cross should use to compile our package.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>echo '
&#91;target.x86_64-unknown-linux-gnu]
image = "lambci/lambda:build-provided"
&#91;target.x86_64-unknown-linux-musl]
image = "lambci/lambda:build-provided"
' >> Cross.toml</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Now that we have the right setup, let's compile for&nbsp;the AWS&nbsp;Lambda&nbsp;environment. We can achieve this in two ways:</p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul><li>Making a static build by targeting&nbsp;<code>x86_64-unknown-linux-musl</code></li><li>Dynamically linking shared libraries by targeting&nbsp;<code>x86_64-unknown-linux-gnu</code></li></ul>
<!-- /wp:list -->
<!-- wp:heading {"level":3} -->
<h3>Statically Linked Compilation</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>In static compilation, no dynamic linking occurs. All bindings are done at compile time; the linker takes one or more objects, such as a set of routines, external&nbsp;functions&nbsp;and variables from external libraries generated by compilers, and assembles them into a single standalone executable program. During execution, the application is not dependent on any auxiliary module such as dynamically linked libraries (<code>.dll</code>) or shared objects (<code>.so</code>).</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Static linking to the libraries that rely heavily on C/C++ code will require some extra hack. See&nbsp;<a href="https://github.com/rust-lang/rust/issues/36710#issuecomment-249634183" target="_blank" rel="noreferrer noopener">rust-lang/rust#36710</a>&nbsp;for further explanation.</p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":3672,"sizeSlug":"large","className":"is-style-rounded"} -->
<div class="wp-block-image is-style-rounded"><figure class="aligncenter size-large"><img src="https://content.adevait.com/wp-content/uploads/2020/09/GF8oVn4-1024x418.png" alt="Statically Linked Compilation" class="wp-image-3672"/></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>At the time of writing, the target triple&nbsp;<code>x86_64-unknown-linux-musl</code>&nbsp;has a tier 2&nbsp;Rust&nbsp;platform support. Targets in this tier are guaranteed to build but are not guaranteed to produce a working build. If your package fails to build using this method, consider&nbsp;dynamic compilation. See the&nbsp;<a href="https://doc.rust-lang.org/nightly/rustc/platform-support.html" target="_blank" rel="noreferrer noopener">list of&nbsp;Rust&nbsp;platform support here</a>.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code># Make a build targeting x86_64-unknown-linux-musl
cross build --target x86_64-unknown-linux-musl --release
# Determine the file type
file target/x86_64-unknown-linux-musl/release/bootstrap
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The last output should look like this:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>target/x86_64-unknown-linux-musl/release/bootstrap: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID&#91;sha1]=48b9519ccfae9bd613c825165f0dde46567e83e3, with debug_info, not stripped
</code></pre>
<!-- /wp:code -->
<!-- wp:heading {"level":3} -->
<h3>Dynamically Linked Compilation</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>GNU/Linux and BSD systems excluding Musl targets uses dynamic linking by default. The&nbsp;Rust&nbsp;compiler also adheres to this when compiling for their targets. Unlike static compilation, a dynamically linked executable depends on external libraries and shared objects that are dynamically loaded at runtime. Since objects are store separately, there may be a compatibility problems if your package or required library was compiled by a newer version of compiler. When that happens,&nbsp;Lambda&nbsp;would raise a&nbsp;<code>RuntimeError</code>&nbsp;with a message similar to the following:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>/var/task/bootstrap: /lib64/libc.so.6: version `GLIBC_2.18' not found (required by /var/task/bootstrap)</code></pre>
<!-- /wp:code -->
<!-- wp:image {"id":3673,"sizeSlug":"large","className":"is-style-rounded"} -->
<figure class="wp-block-image size-large is-style-rounded"><img src="https://content.adevait.com/wp-content/uploads/2020/09/ZI7oJit-1024x527.png" alt="Dynamically Linked Compilation" class="wp-image-3673"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>Let's make a dynamic build:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code># Make a build targeting x86_64-unknown-linux-gnu
cross build --target x86_64-unknown-linux-gnu --release
# Determine the file type
file target/x86_64-unknown-linux-gnu/release/bootstrap</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The last output should look like this:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>target/x86_64-unknown-linux-gnu/release/bootstrap: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID&#91;sha1]=9e61a11646f347bf3be0259362d9077b2d4b4925, with debug_info, not stripped</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>For the remainder of this guide, we will be working with&nbsp;<code>x86_64-unknown-linux-gnu</code>&nbsp;target. Be sure to change the target triple to match your use case.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="deployment">Deployment</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Before&nbsp;deploying&nbsp;our bootstrap, we will first, manually test our build in a sandbox environment using Docker and docker-lambda&nbsp;images to replicate&nbsp;AWS&nbsp;Lambda. This gives us an additional benefit to test offline, avoid incurring request charges, and also the assurance that our function will run on&nbsp;Lambda&nbsp;with no issues.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>docker run --rm \
-e DOCKER_LAMBDA_STAY_OPEN=1 -p 9001:9001 \
-v "$PWD"/target/x86_64-unknown-linux-gnu/release/bootstrap:/var/task/bootstrap:ro,delegated \
lambci/lambda:provided main</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>On a separate terminal window, invoke the:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>aws lambda invoke \
--endpoint http://localhost:9001 \
--no-sign-request --function-name=rust_lambda \
--invocation-type=RequestResponse \
--payload $(echo '{"fullName": "Martin Luther", "message": null}' | base64 ) \
output.json</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>The response from the function will be written to the file&nbsp;<code>output.json</code>.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 id="uploading-the-function">Uploading the Function</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Now that we are certain our function works as expected, let's zip it up and upload it. The next command adds our&nbsp;<code>bootstrap</code>&nbsp;to a zip file&nbsp;<code>bootstrap.zip</code>.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>zip -r9 -j bootstrap.zip ./target/x86_64-unknown-linux-gnu/release/bootstrap</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Before creating a&nbsp;lambda&nbsp;function, we need to create an execution role for the function. The execution role is a set of permissions that defines what our function should be able to do.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code># Create an IAM Role lambda-basic-execution.
aws iam create-role \
--role-name lambda-basic-execution \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": &#91;
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
# Attach AWSLambdaBasicExecutionRole to the role.
aws iam attach-role-policy \
--role-name lambda-basic-execution \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>In this case, we created a role called&nbsp;<code>lambda-basic-execution</code>&nbsp;and attached the policy&nbsp;<code>AWSLambdaBasicExecutionRole</code>&nbsp;to it. The AWSLambdaBasicExecutionRole is a policy created by&nbsp;AWS&nbsp;which defines the most basic permissions for a&nbsp;Lambda&nbsp;function – writing logs to&nbsp;AWS&nbsp;CloudWatch.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Next, we create a&nbsp;lambda&nbsp;function called&nbsp;<code>rust_lambda</code>&nbsp;with a custom runtime which has the execution role of&nbsp;<code>lambda-basic-execution</code>&nbsp;and uses our zipped bootstrap.</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code># Create a Lambda function with our custom bootstrap.
AWS_ACCOUNT_ID=`aws sts get-caller-identity --query Account --output text` &amp;&amp; \
aws lambda create-function \
--function-name rust_lambda \
--runtime provided \
--role arn:aws:iam::$AWS_ACCOUNT_ID:role/lambda-basic-execution \
--zip-file fileb://bootstrap.zip \
--description "Simple Rust function" \
--timeout 5 \
--handler main</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>Once our function is deployed successfully, we can run the function by executing:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code># Test the deployed function
aws lambda invoke \
--function-name=rust_lambda \
--invocation-type=RequestResponse \
--payload $(echo '{"fullName": "Martin Luther", "message": null}' | base64 ) \
output.json</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>You should get the following response:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>And a new file called&nbsp;<code>output.json</code>&nbsp;with the following content:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>{"data":{"fullName":"Hello Martin Luther!","message":"You have no message."}}</code></pre>
<!-- /wp:code -->
<!-- wp:heading -->
<h2 id="and-thats-it">And That's It!</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>I hope this guide has helped you learn&nbsp;Rust&nbsp;and how you can deploy&nbsp;Rust&nbsp;functions&nbsp;to&nbsp;AWS&nbsp;Lambda. You can have a lot of fun building awesome things with this.</p>
<!-- /wp:paragraph --> ]]></description>
<category>Rust</category>
<author>Chuma Umenze</author>
<pubDate>Thu, 10 Sep 2020 09:26:05 +0000</pubDate>
</item>
<item>
<title><![CDATA[ Building a Culture of Experimentation Into Your Software Delivery Process ]]></title>
<link><![CDATA[ https://adevait.com/software/building-culture-of-experimentation ]]></link>
<description><![CDATA[ <!-- wp:paragraph -->
<p><em>If you want to get a competitive edge, building a culture of experimentation is critical. It can result in cost savings, higher revenue, and improved user experience.&nbsp;</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>People have been building scientific and technological innovations through testing and experimentation for centuries.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Eratosthenes measured the circumference of Earth 2,000 years ago.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Newton's prism experiment proved color is an inherent property of light itself.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Marie Curie, using an instrument called electrometer, found that radioactivity is an inherent property of individual atoms that emanates from their internal structure.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>These experiments have paved the way for modern medicine, geography, energy, communication, physics, etc.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>In today's technological world, experimentation holds the same power when it comes to innovation.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Some of the biggest companies, like Amazon, Netflix, and Google, use this scientific method to challenge the status quo. In return, they innovate, grow, and improve.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Amazon CEO, Jeff Bezos, has said: “Our success at Amazon is a function of how many experiments we do per year, per month, per week, per day.”</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Mark Zuckerberg has reported that the company conducts thousands of experiments at any given time.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>As far back as 2008, Google was already leveraging its search engine users to simultaneously conduct 50–200 experiments.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>The end goal of this "test everything" mentality? To roll out new products, get past the competition, improve customer experience, and try new business models.&nbsp;</p>
<!-- /wp:paragraph -->
<!-- wp:uagb/table-of-contents {"block_id":"86445deb","classMigrate":true,"mappingHeaders":[true,true,true,true,true,true],"headerLinks":"[{\u0022tag\u0022:2,\u0022text\u0022:\u0022Why an Experimentation Culture is Valuable\u0022,\u0022link\u0022:\u0022why-an-experimentation-culture-is-valuable\u0022,\u0022content\u0022:\u0022Why an Experimentation Culture is Valuable\u0022,\u0022level\u0022:0},{\u0022tag\u0022:2,\u0022text\u0022:\u0022How to Build an Experimentation Culture\u0022,\u0022link\u0022:\u0022how-to-build-an-experimentation-culture\u0022,\u0022content\u0022:\u0022How to Build an Experimentation Culture\u0022,\u0022level\u0022:0},{\u0022tag\u0022:3,\u0022text\u0022:\u0022A Culture of Experimentation Starts With Accepting Failure\u0022,\u0022link\u0022:\u0022a-culture-of-experimentation-starts-with-accepting-failure\u0022,\u0022content\u0022:\u0022A Culture of Experimentation Starts With Accepting Failure\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Small Changes Can Generate Huge Benefits\u0022,\u0022link\u0022:\u0022small-changes-can-generate-huge-benefits\u0022,\u0022content\u0022:\u0022Small Changes Can Generate Huge Benefits\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022More Experiments Are Better Than Few\u0022,\u0022link\u0022:\u0022more-experiments-are-better-than-few\u0022,\u0022content\u0022:\u0022More Experiments Are Better Than Few\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Rely on Data, Not on Strong Opinions\u0022,\u0022link\u0022:\u0022rely-on-data-not-on-strong-opinions\u0022,\u0022content\u0022:\u0022Rely on Data, Not on Strong Opinions\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Keep the Feedback Coming\u0022,\u0022link\u0022:\u0022keep-the-feedback-coming\u0022,\u0022content\u0022:\u0022Keep the Feedback Coming\u0022,\u0022level\u0022:1},{\u0022tag\u0022:3,\u0022text\u0022:\u0022Finally, Celebrate Your Wins and Learn From Your Failures\u0022,\u0022link\u0022:\u0022finally-celebrate-your-wins-and-learn-from-your-failures\u0022,\u0022content\u0022:\u0022Finally, Celebrate Your Wins and Learn From Your Failures\u0022,\u0022level\u0022:1}]"} -->
<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-undefined uagb-block-86445deb" data-scroll="true" data-offset="30" data-delay="800"><div class="uagb-toc__wrap"><div class="uagb-toc__title-wrap"><div class="uagb-toc__title">Table Of Contents</div></div><div class="uagb-toc__list-wrap"><ul class="uagb-toc__list"><li><a href="#why-an-experimentation-culture-is-valuable">Why an Experimentation Culture is Valuable</a></li><li><a href="#how-to-build-an-experimentation-culture">How to Build an Experimentation Culture</a></li><ul class="uagb-toc__list"><li><a href="#a-culture-of-experimentation-starts-with-accepting-failure">A Culture of Experimentation Starts With Accepting Failure</a></li><li><a href="#small-changes-can-generate-huge-benefits">Small Changes Can Generate Huge Benefits</a></li><li><a href="#more-experiments-are-better-than-few">More Experiments Are Better Than Few</a></li><li><a href="#rely-on-data-not-on-strong-opinions">Rely on Data, Not on Strong Opinions</a></li><li><a href="#keep-the-feedback-coming">Keep the Feedback Coming</a></li><li><a href="#finally-celebrate-your-wins-and-learn-from-your-failures">Finally, Celebrate Your Wins and Learn From Your Failures</a></li></ul></ul></div></div></div>
<!-- /wp:uagb/table-of-contents -->
<!-- wp:heading -->
<h2 id="why-an-experimentation-culture-is-valuable">Why an Experimentation Culture is Valuable</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Only a decade ago, Yahoo was on a par with Google. The two tech giants were competing fiercely to conquer the territory of the World Wide Web. But Google's ferocious experimentation led the company on a path of con
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment