<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Ry Vee - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Ry Vee - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:30:01 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/ryvee/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use Object Storage for Data Parallelization and Experimentation ]]>
                </title>
                <description>
                    <![CDATA[ By using big data, companies can learn a lot about how their businesses are performing. Analytics on sales, churn rates, and other basic metrics are available in almost real time as data comes in.  Then there are more complex analyses that you'll nee... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-object-storage-for-parallelization-and-experimentation/</link>
                <guid isPermaLink="false">66bb5252b0a396d22e4116fa</guid>
                
                    <category>
                        <![CDATA[ big data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ storage ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Mon, 27 Sep 2021 14:09:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/article-cover-pic.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By using big data, companies can learn a lot about how their businesses are performing. Analytics on sales, churn rates, and other basic metrics are available in almost real time as data comes in. </p>
<p>Then there are more complex analyses that you'll need to do. At times relationships between two seemingly unrelated data sets can provide surprising insights and unveil important opportunities for the organization.</p>
<p>Data scientists and engineers are continuing to improve how they break down and work on data. Experimentation entails discovering the right correlations among data points. </p>
<p>This means they also need to do some sort of parallelization of such data and resulting models. Parallelization simply means that the same data set is being operated upon in many different ways without damaging the integrity of the original data.</p>
<p>In this article we are going to talk about how you can make sure you're doing such experimentation and parallel processing efficiently and that it provides the maximum insights. We will be tackling different concepts related to data storage and data versioning.</p>
<h1 id="heading-block-storage-vs-object-storage">Block Storage vs Object Storage</h1>
<p>For the uninitiated, we first must understand the difference between block and object storage and why the latter is the better option when dealing with data experimentation.</p>
<p><img src="https://lh4.googleusercontent.com/p8F4n7jqjmQtqquQasDGPEj1eRdxhNIsdMFxX9gIM03w6r6u-VRzU6rn2gMqdF1U3lrGOrjWEPwlBFzR-0cYVHWBWF7tigFiS4m_EtYjw0bU4tPATeWsZNYTFwpZTbyLBAzxqmbX=s0" alt="Image" width="1000" height="500" loading="lazy">
_<a target="_blank" href="https://res.cloudinary.com/practicaldev/image/fetch/s--PYImgKrK--/c_imagga_scale,f_auto,fl_progressive,h_500,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4519hl0nf6aze73pyvsr.png">Image source</a>_</p>
<h2 id="heading-what-is-block-storage">What is Block Storage?</h2>
<p>It is called “block storage” (also known as <a target="_blank" href="https://www.snia.org/education/storage_networking_primer/san/what_san">SAN</a>) because each dataset (in the form of files) is grouped into blocks stored in disks. </p>
<p>A classic example of block storage is the file system on your personal computer. For enterprise-level use-cases, it is scaled through a network of hard drives connected through fiber optic cables. </p>
<p>There are a few disadvantages to using block storage. First, if a sector (or a block) becomes corrupted, it can damage the files. Another problem is the lack of scalability (expanding the network of fiber optic cables is costly).</p>
<h2 id="heading-what-is-object-storage">What is Object Storage?</h2>
<p>In object storage, data is stored as objects. Each object contains the actual data, called the blob, a unique identifier (UUID), and metadata, which contains information about the object (such as timestamp, version, and author).</p>
<p>Object storage makes it cost-effective to scale your data store—you don’t need complex hardware for this. It also makes data retrieval faster as each object can be retrieved through its UUID. </p>
<p>This is in contrast to block storage, where each data location needs to be identified before the actual information can be retrieved.</p>
<p>One disadvantage of using object storage is that data can only be written once and cannot be updated. But this isn’t really a disadvantage as we will see further on in this article.</p>
<h2 id="heading-what-problems-does-object-storage-solve">What Problems Does Object Storage Solve?</h2>
<p>As we have already seen, data retrieval can be incredibly fast with object storage (no matter the size of the data store). But when it comes to data experimentation and data parallelization, object storage shines the brightest.</p>
<p>As mentioned before, you can't overwrite any data already stored as an object. This ensures object storage is protected from unwanted (or unauthorized) data destruction or updating. That’s great to know if you do a lot of data processing where accidental corruption of information could happen.</p>
<p>One other problem that object storage can solve is that it doesn’t require data to be structured. As companies produce and consume tremendous amounts of information every moment, often non-structured data (such as PDFs, videos, images) are not so easily processed into useful forms (such as for analytics or dashboards). </p>
<p>With object storage, this is now possible. You can now use non-structured data to develop machine learning models.</p>
<p>With data storage, it’s possible to have different versions of the same blob (with different metadata). As there is Git for code version control, we can have similar ways of managing different versions of the same data.</p>
<p>This brings us to the concept of data lakes.</p>
<h2 id="heading-what-are-data-lakes">What are Data Lakes?</h2>
<p>Data lakes are central repositories of data that don’t care which format such data is in. </p>
<p>Companies produce and consume tremendous amounts of data. Such data traditionally sits in silos because they belong to different departments or are in different forms (for example, videos aren’t stored in the same directory as the data in the MySQL database). </p>
<p>With data lakes, any department in the enterprise can store information without the need to pre-process it. Likewise, any data can be retrieved and analyzed by anybody from any department.</p>
<p>Data lakes are important because they make data analytics extremely fast and convenient.</p>
<h2 id="heading-how-data-experimentation-and-parallelization-work-with-object-storage">How Data Experimentation and Parallelization Work with Object Storage</h2>
<p>As with developing software, working with data requires us to utilize tools that can aid us in our workflow. A powerful open source tool for experimenting with data and performing parallelization (that is working on the same data to create different sets of machine learning models) is LakeFS.</p>
<p>LakeFS is an open source platform that provides Git-like capabilities when working with data. This means you can create branches (allowing you to experiment with data) and commit versions of data (and data models).</p>
<h3 id="heading-why-is-this-git-like-feature-important">Why is this Git-like feature important?</h3>
<p>First, you need to make sure that your data lake is <a target="_blank" href="https://mariadb.com/resources/blog/acid-compliance-what-it-means-and-why-you-should-care/">ACID</a> compliant. This means that your data changes can happen in isolation (in branches). Thus, the integrity of the data is maintained in the master branch (until such changes are ready to be merged).</p>
<p>Another important feature of LakeFS is continuous integration of data (again, much like in software development). Enterprises need to incorporate new data quickly and without being disrupted. Therefore, this ability to have a <a target="_blank" href="https://www.infoworld.com/article/3271126/what-is-cicd-continuous-integration-and-continuous-delivery-explained.html">CI/CD</a> workflow is invaluable. </p>
<p>So, let’s see how we can get started with using LakeFS with our object storage experimentation and parallelization.</p>
<h3 id="heading-how-to-install-lakefs">How to Install LakeFS</h3>
<p>Locally you can install LakeFS by running the following command in your terminal:*  </p>
<p><img src="https://lh4.googleusercontent.com/pTYRbQlB2_Mp8j_XGxUOvBI0PLf5kuuT1tYV5AxcPmrnq8K5sjLCUBwQqp4klk4rnraQnK9OD5hrudEFUwBLNcvmyNGQqDPkLQ_DkVBoVgCUfITIFdS6d1RxtkTFG_T40ZV0ia0L=s0" alt="Image" width="501" height="111" loading="lazy">
<em><a target="_blank" href="https://carbon.now.sh/?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=seti&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=curl%2520https%253A%252F%252Fcompose.lakefs.io%2520%257C%2520docker-compose%2520-f%2520-%2520up%250A">Code source</a></em></p>
<p>_*This is assuming you have Docker and Docker-Compose installed in your system. If you don’t have Docker and Docker-Compose, you may try other installation methods <a target="_blank" href="https://docs.lakefs.io/quickstart/more_quickstart_options.html">here</a>._</p>
<p>Now visit <a target="_blank" href="http://127.0.0.1:8000/setup">http://127.0.0.1:8000/setup</a> in your browser to verify you have installed it correctly.</p>
<h3 id="heading-how-to-create-a-repository-in-lakefs">How to Create a Repository in LakeFS</h3>
<p>Once you’ve verified that LakeFS is installed correctly, go ahead and create an admin user.</p>
<p><img src="https://lh5.googleusercontent.com/kRpsNjJe60f7fiIEFC0O5ZbY88F9g-F4X-GRtl8L8WiVJ_sDiKcnz-0jmprZc-bVkfq029fYhq4K-jdBXyBQttc012Nv4v6j2vbJvk4jnbs71BF9Wulo_5JwsvmSjRE1nkQ-ltRe=s0" alt="Image" width="1627" height="923" loading="lazy">
<em><a target="_blank" href="https://docs.lakefs.io/assets/img/setup.png">Image source</a></em></p>
<p><img src="https://lh3.googleusercontent.com/oez-1Q1JH6Q_cqUh0tKE1bW-IbEXg92UP4NVkTy_o-vVETELASw8R8CoPS5ogWDZNl4hH8W3cb68_PvEECO1os9U1sgfJFA2PMnc1J57wEjomp9SrN0ZZK-OXoOjJpZcF-LPZlhu=s0" alt="Image" width="1627" height="921" loading="lazy">
_<a target="_blank" href="https://docs.lakefs.io/assets/img/setup_done.png">Image source</a>_</p>
<p>Click on the login link and log in as an administrator. </p>
<p>On the page to which you get redirected, click on Create Repository. A popup will appear:</p>
<p><img src="https://lh6.googleusercontent.com/2abxJeRjLk7IRzhohW7jlG3cKQKH4kRCjIyVbQkHe_Fa9qdcGPdrbcTsFRhW7lv3S5LQtfa4xBmnNu0wRqhFSvwi1hp5_ARB_fRJlcLgz1TmDa_a9DQ-apmcIiclMLwsgfuyoD9P=s0" alt="Image" width="1622" height="907" loading="lazy">
_<a target="_blank" href="https://docs.lakefs.io/assets/img/create_repo_local.png">Image source</a>_</p>
<p>Congratulations! You now have your first repository. This is the main “bucket” in which you are going to store your data. </p>
<p>Next, we’ll start adding some data.</p>
<h3 id="heading-how-to-add-data-to-your-lakefs-repository">How to Add Data to your LakeFS Repository</h3>
<p>Visit <a target="_blank" href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html">here</a> to install AWS CLI.</p>
<p>With the credentials created during the admin-user creation phase, configure a new connection profile:</p>
<p><img src="https://lh5.googleusercontent.com/D9FDuc11VgqsUr5LfN2UE_zTQYSKinNHB_saQxvr0MJj2yurnDCTqEC0cWA-dvOj3TYGMxJq52Una4zpaG6hrImrAaOWA43V1nMsUg0NpI9XIj8lKF6THD3ZoC0BNMqd-uRUsS6p=s0" alt="Image" width="645" height="204" loading="lazy">
<em><a target="_blank" href="https://carbon.now.sh/?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=seti&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=aws%2520configure%2520--profile%2520local%250A%2523%2520output%253A%250A%2523%2520AWS%2520Access%2520Key%2520ID%2520%255BNone%255D%253A%2520AKIAJVHTOKZWGCD2QQYQ%250A%2523%2520AWS%2520Secret%2520Access%2520Key%2520%255BNone%255D%253A%2520****************************************%250A%2523%2520Default%2520region%2520name%2520%255BNone%255D%253A%250A%2523%2520Default%2520output%2520format%2520%255BNone%255D%253A%250A">Code source</a></em></p>
<p>To test if the connection is working, run the following:</p>
<p><img src="https://lh5.googleusercontent.com/oP-iisEz7w9qQM-zQaAUcdhXj_YMRGamhV-AwwNfFsDVm_p4HcKlGsw0sVD0aJS-Q-3rCy3VlhtcvtBxJgFCrHQLXrPB7ZyHVril1iGeWKP_mqPPrxizpw8NNAGWdNc2ZF36mfX4=s0" alt="Image" width="560" height="148" loading="lazy">
<em><a target="_blank" href="https://carbon.now.sh/?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=seti&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=aws%2520--endpoint-url%253Dhttp%253A%252F%252Flocalhost%253A8000%2520--profile%2520local%2520s3%2520ls%250A%2523%2520output%253A%250A%2523%25202021-06-15%252013%253A43%253A03%2520example-repo%250A">Code source</a></em></p>
<p>Now, to copy files into the main branch:</p>
<p><img src="https://lh5.googleusercontent.com/Z_3sbfX6IMJzPkYeejJ1O9ftjkO3c4kPk_rlCJ1iOP2FgTnJTZ03cB8C8Ml2u4bet4cvBS60rHt7Ns-xgLWix422-w3ZvpGQCyeGKgBDd0Oog-sV-E4XSpV4ARpoYeQhR2INZV_H=s0" alt="Image" width="847" height="148" loading="lazy">
<em><a target="_blank" href="https://carbon.now.sh/?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=seti&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=aws%2520--endpoint-url%253Dhttp%253A%252F%252Flocalhost%253A8000%2520--profile%2520local%2520s3%2520cp%2520.%252Ffoo.txt%2520s3%253A%252F%252Fexample-repo%252Fmain%252F%250A%2523%2520output%253A%250A%2523%2520upload%253A%2520.%252Ffoo.txt%2520to%2520s3%253A%252F%252Fexample-repo%252Fmain%252Ffoo.txt%250A">Code source</a></em></p>
<p>Just note that we need to prefix the path with the name of the branch we want to use.</p>
<p>Now, we will see the file we’ve added in the UI:</p>
<p><img src="https://lh6.googleusercontent.com/F8UCd8s43wM0y4WgRhHWy04p2rzBQ1ccvUZhppCzl30fE0FJEpMQb7Y1X06x-WDx3J9I5LELQv4FtFKOYWJqU2E9dENB5MMqjsv-MYfLI-oCEXLekhWH9xTcazm1-_Fmo4NxgDb_=s0" alt="Image" width="1627" height="934" loading="lazy">
_<a target="_blank" href="https://docs.lakefs.io/assets/img/object_added.png">Image source</a>_</p>
<p>Next, we will need to know how to commit and create branches. To do that, we will need to install the LakeFS CLI.</p>
<h3 id="heading-how-to-install-the-lakefs-cli">How to Install the LakeFS CLI</h3>
<p>You need to first download the binary file <a target="_blank" href="https://docs.lakefs.io/#downloads">here</a>. </p>
<p>Again, we need to use the earlier created admin credentials:</p>
<p><img src="https://lh4.googleusercontent.com/KQntIwi6YaOyp2kKvKLxeYs4Il4czCGCv8fj2_PFhg2Bqy2RRGNNQtLsCxS8YT57DEH-Q63obz7emujS5tST4aoPx0qb4XLjJV3AeKEwRwQGATfJd6us3BA5Svo7Lz_i3k_Smy7N=s0" alt="Image" width="552" height="204" loading="lazy">
<em><a target="_blank" href="https://carbon.now.sh/?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=seti&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=lakectl%2520config%250A%2523%2520output%253A%250A%2523%2520Config%2520file%2520%252Fhome%252Fjanedoe%252F.lakectl.yaml%2520will%2520be%2520used%250A%2523%2520Access%2520key%2520ID%253A%2520AKIAJVHTOKZWGCD2QQYQ%250A%2523%2520Secret%2520access%2520key%253A%2520****************************************%250A%2523%2520Server%2520endpoint%2520URL%253A%2520http%253A%252F%252Flocalhost%253A8000%252Fapi%252Fv1%250A">Code source</a></em></p>
<p>Here are some of the commands we can run to try it out:</p>
<p><img src="https://lh4.googleusercontent.com/4HuuBJwfpif6TzMS5spkzhkLQf_TC-rZ6WMjAiOOrsv3z8iF2vaTtKTjzicnm5qDjXmLq_aSGqXvAF7RE43BWd9hGB7gUSb76w1bt6ntyLJgAVFBMLwP7uYRPLFUd-1G27kVER7O=s0" alt="Image" width="721" height="521" loading="lazy">
<em><a target="_blank" href="https://carbon.now.sh/?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=seti&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=lakectl%2520branch%2520list%2520lakefs%253A%252F%252Fexample-repo%250A%2523%2520output%253A%250A%2523%2520%252B----------%252B------------------------------------------------------------------%252B%250A%2523%2520%257C%2520REF%2520NAME%2520%257C%2520COMMIT%2520ID%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257C%250A%2523%2520%252B----------%252B------------------------------------------------------------------%252B%250A%2523%2520%257C%2520main%2520%2520%2520%2520%2520%257C%2520a91f56a7e11be1348fc405053e5234e4af7d6da01ed02f3d9a8ba7b1f71499c8%2520%257C%250A%2523%2520%252B----------%252B------------------------------------------------------------------%252B%250A%2520%2520%2520%2520%2520%250Alakectl%2520commit%2520lakefs%253A%252F%252Fexample-repo%252Fmain%2520-m%2520%27added%2520our%2520first%2520file%21%27%250A%2523%2520output%253A%250A%2523%2520Commit%2520for%2520branch%2520%2522main%2522%2520done.%250A%2523%2520%250A%2523%2520ID%253A%2520901f7b21e1508e761642b142aea0ccf28451675199655381f65101ea230ebb87%250A%2523%2520Timestamp%253A%25202021-06-15%252013%253A48%253A37%2520%252B0300%2520IDT%250A%2523%2520Parents%253A%2520a91f56a7e11be1348fc405053e5234e4af7d6da01ed02f3d9a8ba7b1f71499c8%250A%2520%2520%250Alakectl%2520log%2520lakefs%253A%252F%252Fexample-repo%252Fmain%250A%2523%2520output%253A%2520%2520%250A%2523%2520commit%2520901f7b21e1508e761642b142aea0ccf28451675199655381f65101ea230ebb87%250A%2523%2520Author%253A%2520Example%2520User%2520%253Cuser%2540example.com%253E%250A%2523%2520Date%253A%25202021-06-15%252013%253A48%253A37%2520%252B0300%2520IDT%250A%2520%2520%2520%2520%2520%2520%2520%250A%2520%2520%2520%2520%2520%2520added%2520our%2520first%2520file%21%250A%2520%2520%2520%2520%2520%2520%2520">Code source</a></em></p>
<p>You can find all the other commands, such as branch creation, and so on, <a target="_blank" href="https://docs.lakefs.io/reference/commands.html">online</a>.</p>
<p>There you have it! Now, you can work with your data any way you like. Experiment without guilt and create multiple versions of your data models.</p>
<h2 id="heading-in-closing">In Closing</h2>
<p>In this article, we covered a bit of ground. We learned the different kinds of data storage mechanisms and why object storage has a lot of edge when dealing with data experimentations and parallelism. </p>
<p>Next, we looked into data lakes and LakeFS, which is a powerful tool for working with data.</p>
<p>At first, it might seem a daunting task. But, as we’ve shown here, with the right set of tools and knowledge, there’s a lot you can accomplish.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Must-Have Network Certifications for IT Managers ]]>
                </title>
                <description>
                    <![CDATA[ In this increasingly digital world, Information Technology careers have expanded and blossomed to suit nearly everyone’s skill sets. One such lucrative career is IT Management. IT Managers earn an average of $91,000 a year. This salary bracket can ac... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/must-have-network-certifications-for-it-managers/</link>
                <guid isPermaLink="false">66bb5254074d8d7b12eae37e</guid>
                
                    <category>
                        <![CDATA[ Certification ]]>
                    </category>
                
                    <category>
                        <![CDATA[ computer networking ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Network Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ System administration ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Thu, 07 Jan 2021 17:09:49 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5ff3d53d7af2371468bb77eb.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this increasingly digital world, Information Technology careers have expanded and blossomed to suit nearly everyone’s skill sets. One such lucrative career is IT Management.</p>
<p>IT Managers earn an average of $91,000 a year. This salary bracket <a target="_blank" href="https://www.indeed.com/career-advice/careers/what-does-an-it-manager-do">can actually range</a> from $21,000 to $180,000 annually, depending on the industry of the IT Manager. In each case, though, the job entails problem-solving and project management.</p>
<p>Specifically, an IT Manager position has the following job description:</p>
<ul>
<li>Analyze, plan, and design the company’s information system needs and execute such plans and designs.</li>
<li>Monitor and improve such a system (which may also include the company’s full telecommunications infrastructure) and recommend any upgrades required to its top management.</li>
<li>Manage the company’s IT policies, including information policy, data/information access, and regulatory compliance.</li>
<li>Hire and lead system administrators and other personnel who will be part of their team.</li>
<li>Identify the training needs of the team and be able to arrange for such training and measure the benefits.</li>
</ul>
<p>The first three above, as you will see, require the IT Manager to be astute in the technical aspects of the job. In particular, they must be competent in network-related areas. They should master these skills if they want to reach the higher tier of the salary scale.</p>
<p>Luckily, there are many training programs designed for IT Management professionals. These aren’t just regular training programs but fully-fledged certification courses. What follows are some of the top programs.</p>
<h2 id="heading-cisco-certified-network-associate-ccnahttpswwwciscocomcenustraining-eventstraining-certificationscertificationsassociateccnahtml"><a target="_blank" href="https://www.cisco.com/c/en/us/training-events/training-certifications/certifications/associate/ccna.html">Cisco Certified Network Associate (CCNA)</a></h2>
<p><img src="https://lh5.googleusercontent.com/f4S28XjFyAb80RUONagOn7wzEbSnvAnrI_jgM_ykBpHnh6EnDMdKiLuHR0giQWGL2zffx0aoOhDZ9Yp6kwcgVlibSCi41DsUKKn1izXd9StcBhgRxmCWl5bveDVAP-dRPg" alt="Image" width="1600" height="882" loading="lazy"></p>
<p>The Cisco Certified Network Associate (CCNA) course is probably the most widely respected certification out there for IT professionals. It is an intermediate-level certification course. A CCNA holder has high competence in configuring, operating, and troubleshooting routed networks.</p>
<p>To get this certification, you must take and pass the CCNA 200-301 examination, which deals with fundamentals on network security, internet protocols, automation, and other security-related skills. </p>
<p>The exam is composed of 120 questions where each question has an associated score. To pass the exam, you must have a score of at least 800 (the highest attainable is 1,000). The cost for this exam is $300.</p>
<h2 id="heading-cisco-certified-network-professional-ccnphttpswwwciscocomcenustraining-eventstraining-certificationscertificationsprofessionalhtml"><a target="_blank" href="https://www.cisco.com/c/en/us/training-events/training-certifications/certifications/professional.html">Cisco Certified Network Professional (CCNP)</a></h2>
<p><img src="https://lh6.googleusercontent.com/u7bKANhre4cxUye5Lnx150ni7d0Dx0rsZuYQmD0wqMpVYSGi19MRmHGAykzCmEGJqNiYpN8FlrrZniaupJkUZxXiX133HGEk13FuAw9SBV2mb16ArYm9g0C-7vmecok_0A" alt="Image" width="1600" height="905" loading="lazy"></p>
<p>Whereas CCNA covers the basic to intermediate skill level, the Cisco Certified Network Professional certification is for those who want to achieve a higher level of certification.</p>
<p>Unlike the CCNA, which requires the candidate to pass one exam, CCNP certification requires two exams: a core exam, covering fundamental networking concepts, and a concentration exam in any one area of intended focus (network design, automation, and so on).</p>
<p>It’s best to get a CCNP certificate after at least three years of experience in this industry. You don't need to take the CCNA before the CCNP examination. The costs for CCNP examinations range anywhere from $900 to $1,200. </p>
<h2 id="heading-secure-access-service-edge-sasehttpswwwcatonetworkscomsasesase-expert-level-1"><a target="_blank" href="https://www.catonetworks.com/sase/sase-expert-level-1/">Secure Access Service Edge (SASE)</a></h2>
<p><img src="https://lh6.googleusercontent.com/3ozE3MSwh2rMMMvJJkzoJfHRGXH3JFgv-gM-04tDn7Ku8vo4Ry7PlPQZoN5JpbeO-K4tWAQB375wabpPhfmvDJlHnlCvOsd719E4rz67F9sHxAhH63QYc8O0sSonpPs54w" alt="Image" width="1600" height="903" loading="lazy"></p>
<p>SASE is a new technology (as described in Gartner’s “<a target="_blank" href="https://thehackernews.com/2019/11/network-security-sase.html">The Future of Network Security is in the Cloud</a>”). This architecture integrates Wide Area Network (WAN) and some native security protocols of the cloud. </p>
<p>Cato Networks is a company that offers a cloud-based SASE platform, and they also offer a certification course for SASE so you can get familiarized with this new technology.</p>
<p>For this particular architecture, the center of a company’s network access is its physical data centers. For SASE, that center transfers over to the cloud. </p>
<p>In a nutshell, SASE makes it more efficient for IT Managers to administer the network as it removes some of the complexities associated with traditional physical data center setup.</p>
<p>To get a SASE certification, you need to take the SASE Expert Level 1 course and pass the associated examination (minimum score must be 85%).</p>
<h2 id="heading-comptia-cloudhttpswwwcomptiaorgcertifications"><a target="_blank" href="https://www.comptia.org/certifications">CompTIA cloud+</a></h2>
<p><img src="https://lh4.googleusercontent.com/UCtX_yh_g-kbwR-weKXWdTBu6gJ78j90l35tcInCuICzy2tJKEmO6nrSvdNTP4P4S1nkFQRkQXpGi2jFmU2SMTkHxdIKE-vMrDcb4iY3BMFlWoj5aPpj1G6oQ-SEK3Jj6A" alt="Image" width="1600" height="903" loading="lazy"></p>
<p>CompTIA’s cloud+ certifications are for those who want to validate their system administration, cloud services maintenance, and other network-related knowledge and skills.</p>
<p>Currently, there are two such exams you can take to get a certification.</p>
<p>The CV0-002 (launched in February of 2018) is designed for candidates whose tasks include integrating various solutions into a business-specific system. It has 90 questions max and can be taken in 90 minutes. The passing score (from 100 to 900) is 750. The cost to take this exam is $329.</p>
<p>The CV0-003 (still in beta mode) is designed to get the candidate vendor-agnostic in creating solutions for their organizations. It has 110 questions that can be answered in 165 minutes. At the moment, there isn’t any finalized passing mark, and since it’s in beta, the cost to take this particular certification is just $50.</p>
<p>In both cases, it is recommended that the candidate has at least two years of experience.</p>
<h2 id="heading-aws-certified-solutions-architecthttpsawsamazoncomcertificationcertified-solutions-architect-professional"><a target="_blank" href="https://aws.amazon.com/certification/certified-solutions-architect-professional/">AWS Certified Solutions Architect</a></h2>
<p><img src="https://lh4.googleusercontent.com/pqePNLAG7Qr0uEJ2hMA78bE39byopwvRHvsnhQNNLdWM4GXj8tSqLCD6FWjvbdKJPVX4O8qx87kFhbw1AErxvg2k5IkGOZJWn-zfEn2epyT5c0UPAUBKkBmpSF-pFqhsvw" alt="Image" width="1600" height="903" loading="lazy"></p>
<p>The AWS Certified Solutions Architect certification is geared for professionals who design network architecture involving AWS. It requires that the candidate has at least two years of experience in operating and administering AWS applications.</p>
<p>It is one of the more sought-after certifications, as Amazon is the top vendor for cloud computing services. Hence, more and more organizations hire professionals that can navigate through this infrastructure.</p>
<p>With a price tag of $300 to take the exam, you should prepare for it thoroughly. The great thing is Amazon provides some <a target="_blank" href="https://aws.amazon.com/certification/certification-prep/">preparatory materials</a> for those interested in acquiring this prized certification. And <a target="_blank" href="https://www.freecodecamp.org/news/pass-the-aws-certified-solutions-architect-exam-with-this-free-10-hour-course/">so does freeCodeCamp</a>.</p>
<h2 id="heading-salesforce-certified-development-lifecycle-and-deploymenthttpstrailheadsalesforcecomcredentialsdevelopmentlifecycledeploymentdesigner"><a target="_blank" href="https://trailhead.salesforce.com/credentials/developmentlifecycledeploymentdesigner">Salesforce Certified Development Lifecycle and Deployment</a></h2>
<p><img src="https://lh5.googleusercontent.com/-3Tgw4LsvcllNhxCS7pnqLOlKpQOaSbXQ7p_oYODhoKnqUKDyTceT9auLA_PibGt3u4o925nBN4ragylZ6A43khtInmWoZ6vZPQ-HJ5XGhpm7pEmVz7WXFGO1BMizNc_iQ" alt="Image" width="1600" height="904" loading="lazy"></p>
<p>As Salesforce is a key enterprise CRM solution, organizations often count on this SaaS platform to manage their relationship with customers as well as provide centralized access for related departments.</p>
<p>This exam also has a hefty price tag - $400. The exam itself has 60 multiple choice questions and requires the candidate to answer at least 60% of them correctly. Those failing the exam are allowed to retake it for a $200 fee.</p>
<h2 id="heading-in-conclusion">In conclusion</h2>
<p>These certifications are by no means the only ones that can enhance an IT Manager’s skills (and hence, career prospects). There are also others related to project management. </p>
<p>What is important to note here is that in the ever-changing technology landscape, it’s always essential to put yourself into continuous learning mode.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Yahoo Weather API Alternatives ]]>
                </title>
                <description>
                    <![CDATA[ For beginner developers, the Yahoo Weather API might be enough to build simple weather applications.  Yahoo, however, has a lot of limitations as it only provides location-specific current data and ten-day historical data.  If your application requir... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/yahoo-weather-api-alternatives/</link>
                <guid isPermaLink="false">66bb525a74045df86842bf5f</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ weather ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Mon, 04 Jan 2021 22:02:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/01/lloyd-dirks-kz8pEH4IsUo-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For beginner developers, the <a target="_blank" href="https://developer.yahoo.com/weather/">Yahoo Weather API</a> might be enough to build simple weather applications. </p>
<p>Yahoo, however, has a lot of limitations as it only provides location-specific current data and ten-day historical data. </p>
<p>If your application requires more features and information, using this free API may not be the best option.</p>
<p>What follows is a list of the best alternatives to the Yahoo weather API along with their key benefits and features, most common use cases, and pricing.</p>
<h2 id="heading-climacell-microweather-apihttpswwwclimacellcoweather-api"><a target="_blank" href="https://www.climacell.co/weather-api/">ClimaCell Microweather API</a></h2>
<p><img src="https://lh3.googleusercontent.com/A5lc9386L7Qoo24R1O6hVzwgdduieT1QksavGabQM4LioAIj2fcBnHq3Ggj2ahcZukYUmUa1UaKDmBvFn7KKqQgrmxFvHbFCwBV6YGg_nDBeTmRR6rHPYsSR9ysCQM6Amw" alt="Image" width="991" height="449" loading="lazy"></p>
<p>ClimaCell’s Microweather API provides a wide range of information offered both as numerical data and map layers. It can provide up to four weeks of historical data from partner stations and up to six hours of historical data from its own observations.</p>
<h3 id="heading-key-featuresbenefits-of-the-climacell-microweather-api">Key features/benefits of the ClimaCell Microweather API:</h3>
<ul>
<li>Artificial intelligence-driven data model that processes data from a wide range of sources such as drones and IoT devices</li>
<li>Map layers for more than 20 parameters</li>
<li>Hyper-local and global historical and real-time data</li>
<li>Out of the box templates for easier crafting of request calls</li>
</ul>
<p><strong>Best used for:</strong></p>
<ul>
<li>Most corporate applications. The API is used by companies such as Ford and Uber.</li>
</ul>
<p><strong>Pricing</strong>: Free plan allows for up to 1,000 calls per day. Paid plans start at $87 per month.</p>
<h2 id="heading-openweathermap-apihttpsopenweathermaporgapi"><a target="_blank" href="https://openweathermap.org/api">OpenWeatherMap API</a></h2>
<p><img src="https://lh4.googleusercontent.com/X3V2dcRC9eTfn8v0WeIvghTNu96xKaffyxSQ4Z8U2Gp2I72RPQZ8TLOI-BKBCVUK4KTAslPvyuIOZSGOHCWQ_0mpKSEBNA0z0W_sxEIpmsA8kSFN_w8EHK2chgJLRALhZQ" alt="Image" width="800" height="488" loading="lazy"></p>
<p>OpenWeatherMap is an API inspired by Wikipedia’s crowdsourcing model. It is probably the most popular weather API because of its simplicity.</p>
<h3 id="heading-key-featuresbenefits-of-the-openweathermap-api">Key features/benefits of the OpenWeatherMap API:</h3>
<ul>
<li>Very simple to use</li>
<li>40-year historical weather data for any location</li>
<li>Useful data visualization such as a “this-day-in-history” chart</li>
<li>16-day forecast for several locations</li>
<li>Three-hour and five-day forecasts</li>
<li>Very accurate data as it collects from over 40,000 stations globally</li>
<li>Creative Commons Share-Alike licenses on weather maps which allow developers to easily build map-based applications</li>
</ul>
<p><strong>Best used for</strong>:</p>
<ul>
<li>Personal weather stations and simple projects for developers</li>
<li>Applications geared toward the agricultural sector</li>
</ul>
<p><strong>Pricing</strong>: Its free tier allows for up to 100 calls per day. Paid plans start at $40 per month.</p>
<h2 id="heading-accuweather-apihttpsdeveloperaccuweathercom"><a target="_blank" href="https://developer.accuweather.com/">Accuweather API</a></h2>
<p><img src="https://lh3.googleusercontent.com/wOnvI2RujT_Gul96Ib_zG8nUtCnsrUbTubOMXUabZWjlJDJOEprRGRB_kBaDGn6A1YyIj9DuOkAbp7b2gOCFP3cwZT4hYFxi_so19PhdyFlrzxTVhUjQUBExuaK0Yfy1hg" alt="Image" width="1600" height="900" loading="lazy"></p>
<p>Accuweather is another very popular weather API. It processes over 30 billion requests daily and provides imagery endpoints.</p>
<h3 id="heading-key-featuresbenefits-of-the-accuweather-api">Key features/benefits of the Accuweather API:</h3>
<ul>
<li>Developers can quickly get started with its <a target="_blank" href="https://apigee.com/api-management/">Apigee</a> portal (Accuweather’s project with Google).</li>
<li>Its “Indices API” provides other useful information such as flight delays, mosquito activity, data for stargazers, and a host of daily indices for specific locations.</li>
<li>It provides engaging video presentations along with the minute by minute forecasts.</li>
<li>As its name suggests, it provides super accurate weather data for almost any point on earth.</li>
<li>Weather information can be customized.</li>
</ul>
<p><strong>Best used for</strong>:</p>
<ul>
<li>It’s the best option if the application needs to have video presentations.</li>
<li>Applications geared toward managing disaster risks.</li>
</ul>
<p><strong>Pricing:</strong> It has a limited trial that allows for 50 calls daily. Paid plans start at $25 per month.</p>
<h2 id="heading-stormglass-apihttpsstormglassio"><a target="_blank" href="https://stormglass.io/">Stormglass API</a></h2>
<p><img src="https://lh6.googleusercontent.com/nfcnumdm7ugonJcRH2Z0S0ONzK1KIFzJIKl1XN2GYKOq-5Zw_TwaAoiC6LqHL06uI72_bG9cAvmdOed70kNHjYRWHO4KPgJRGv4yUOc1sTDVbyo1CDqczUKoz9VCROYpfw" alt="Image" width="1024" height="452" loading="lazy"></p>
<p>The Stormglass weather API provides high-resolution forecasts globally from renowned meteorological institutions. It allows developers to fetch data from any coordinate through simple HTTP requests.</p>
<h3 id="heading-key-featuresbenefits-of-the-stormglass-api">Key features/benefits of the Stormglass API:</h3>
<ul>
<li>It provides up to 10-day forecasts with high-resolution.</li>
<li>Provides marine information such as tides, water chemical analysis.</li>
<li>Provides data for renewable energy (wind and solar indices) as well as agricultural information (soil moisture, surface temperature).</li>
</ul>
<p><strong>Best Used For</strong>:</p>
<ul>
<li>Marine-related applications.</li>
<li>Renewable energy monitoring.</li>
<li>Agricultural organizations.</li>
</ul>
<p><strong>Pricing</strong>: It has a free tier that allows up to 50 daily API calls. Paid plans start at 16 euros a month.</p>
<h2 id="heading-weather-company-api-ibmhttpswwwibmcomproductsweather-company-data-packages"><a target="_blank" href="https://www.ibm.com/products/weather-company-data-packages">Weather Company API (IBM)</a></h2>
<p><img src="https://lh6.googleusercontent.com/CgRmpyRclHzJP49XhkwKR1zObkg5X_L8RtWpvlwoFNFqwXqrVOYUtICYMYX7W5g6lOM9DbgCKIrska-Y9E8YYghqqBVfVEutGQm_1x1kfu4Y8slwgF1ZWVlpyBWPNesgbg" alt="Image" width="700" height="394" loading="lazy"></p>
<p>The Weather Company API is owned by IBM and is part of a much more comprehensive data package. Its main value proposition is the provision of highly actionable insights that allows business to optimize their operations and reduce costs while increasing the bottomline.</p>
<h3 id="heading-key-featuresbenefits-of-the-weather-company-api">Key features/benefits of the Weather Company API:</h3>
<ul>
<li>It provides very accurate forecasts of about 500-meter resolution.</li>
<li>It has an extensive number of information sources including high-resolution observations from 250,000 weather stations.</li>
<li>It provides historical data encompassing a 35 kilometer worldwide grid allowing businesses to understand patterns to make better decisions relating to weather.</li>
<li>It provides real-time severe weather forecasting.</li>
<li>It also provides non-weather information such as air-quality, pollen and flu indices.</li>
</ul>
<p><strong>Best Used For</strong>:</p>
<ul>
<li>Business relying heavily on quick forecasts as well as long historical weather data.</li>
</ul>
<p><strong>Pricing</strong>: Free trial that allows for up to 10 calls per minute. The trial then expires once the limit of 10,000 free calls is consumed. Paid plans start at $24.95 per month.</p>
<h2 id="heading-weather-2020-apihttpswwwweather2020comapi"><a target="_blank" href="https://www.weather2020.com/api/">Weather 2020 API</a></h2>
<p><img src="https://lh4.googleusercontent.com/xvEDCc8qVjv1kqEuZemB6ZmELiI_HL0ruNvoeiwI3171A2DQUgfy6pJPZ2Ju53_XWJgfpTmdRrl6xsImE9sEP74KcHy4vrz0qVWoYD1z3MyQXhQAljZs7vQoWm6eg7QsNA" alt="Image" width="360" height="480" loading="lazy"></p>
<p>Weather 2020 prides itself on being a predictive weather modeling platform. Its main proposition is that it can provide for up to nine months forecast just based on the preceding three-month observation. Its statistical model is based on the work of famed meteorologist Gary Lezak.</p>
<h3 id="heading-key-featuresbenefits-of-the-weather-2020-api">Key features/benefits of the Weather 2020 API:</h3>
<ul>
<li>It provides long-term forecasts allowing businesses and organizations to have longer planning horizons.</li>
<li>It offers over 10-million forecasts per day and is best used for mobile applications.</li>
<li>It has a very interactive dashboard that displays key information, analytics and graphs.</li>
</ul>
<p><strong>Best Used For</strong>:</p>
<ul>
<li>Mobile weather applications.</li>
<li>Creating video forecasts (available for paid plans).</li>
</ul>
<p><strong>Pricing</strong>: The free plan allows for up to 1,000 API calls per day. Paid plans start at $ 9.99 per month.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As we’ve seen from the list above, each option has certain use-cases for which it is best suited. This is, by no means, an indication that these are the only uses these APIs have. </p>
<p>What you select will depend on several factors including cost, amount and accuracy of data required, as well your own preferences.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Top 5 Object Storage Tools for Developers ]]>
                </title>
                <description>
                    <![CDATA[ Choosing a storage solution is one of the most significant decisions a developer (or development team) needs to make when building a web or mobile application. As you can imagine, there are many different storage options.  In this article, we’ll brie... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/top-5-object-storage-tools-for-developers/</link>
                <guid isPermaLink="false">66bb5258e326dc37a9d68ed5</guid>
                
                    <category>
                        <![CDATA[ Cloud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ storage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tools ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Fri, 27 Nov 2020 14:40:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/11/jakob-owens-uX7UOpU-884-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Choosing a storage solution is one of the most significant decisions a developer (or development team) needs to make when building a web or mobile application.</p>
<p>As you can imagine, there are many different storage options. </p>
<p>In this article, we’ll briefly discuss two of the most used cloud solutions: <a target="_blank" href="https://www.ionos.com/digitalguide/server/know-how/what-is-block-storage/">block storage</a> (also known as SAN or storage area network) and <a target="_blank" href="https://lakefs.io/object-storage/">object storage</a>. After this, we will go through my top 5 suggested object storage solutions.</p>
<p>There is a third type of storage that’s commonly used: file system storage. However, this mechanism can also concur with SANs and object storage, so we won't go too deep into it.</p>
<h2 id="heading-what-is-block-storage">What is Block Storage?</h2>
<p>Block storage is a network of hard drives connected via fiber-optic network. This gives it an edge over copper cables due to the increased speed.</p>
<p>The reason it's called block storage is that each file in this system is divided into “blocks” of data stored in a disk. Sectors in the disk hold onto individual blocks of data, and these blocks, when combined, form the whole file.</p>
<p>So while there are advantages of using SAN, like high scalability, it is costly and can get incredibly complex as the network grows.</p>
<h2 id="heading-what-is-object-storage">What is Object Storage?</h2>
<p>The defining feature of object storage is that, instead of storing files as blocks, data is stored as <a target="_blank" href="https://techterms.com/definition/object">objects</a>. </p>
<p>Typically these objects will have more data attached to them than the blocks used for block storage. The objects often include: </p>
<ul>
<li>A blob which contains all the payload (i.e., image, video, text content)</li>
<li>Metadata, which tells us more about the file (timestamps, permissions, author, revision, and so on)</li>
<li>A universally unique ID (UUID)</li>
</ul>
<p>One major advantage of this type of storage is that objects are easily obtained and found because of their UUID. With block storage, there’s a specific hierarchy of files that a user goes through before getting the data they need, which can considerably slow down data retrieval.</p>
<p>Now that we have that out of the way, here’s a list of my top 5 object storage tools for developers:</p>
<h3 id="heading-amazon-aws-s3httpsawsamazoncoms3"><a target="_blank" href="https://aws.amazon.com/s3/">Amazon AWS S3</a></h3>
<p><img src="https://lh3.googleusercontent.com/EaFmG10ltwYNmeyrtQrW0Td1DMX189sUjdWs5KUssGlLBr--KFKUnlYcawhqmAQyJeyv2WBKIehdeyp_jEpLjdiv1GJo8mFP-EzLCMbNhx8wMQ6A6n_PHJL8is7i21qXrg" alt="Image" width="1354" height="669" loading="lazy"></p>
<p>S3 is one of the pioneers of object storage. It manages gigantic loads of data from all over the world across hundreds of industries.</p>
<p><strong>Features</strong>:</p>
<ul>
<li>High reliability and durability as it stores S3 objects in copies across multiple systems.</li>
<li>Allows you to manage costs through its S3 Storage Classes, which provides different rates depending on access patterns.</li>
<li>Provides the highest security and protection for your data.</li>
</ul>
<h3 id="heading-google-cloud-storage-gcshttpscloudgooglecomstorage"><a target="_blank" href="https://cloud.google.com/storage/">Google Cloud Storage (GCS)</a></h3>
<p><img src="https://lh5.googleusercontent.com/EjlExkD_Wo8Jg4-hLNzzS_rQM_1-0kpD5RiQQA7fYV1CQxlpczDyNzFraXJvpft1ujMwlQ0HJGpCoa50NSMYxS-gfp6IB9M0ULxf20-sHPEAVX3rExv60A0saQ1j5WJ0mA" alt="Image" width="1354" height="669" loading="lazy"></p>
<p>Google offers four different storage types for business levels of all sizes. When you’re moving data across each of those storage types, it will provide you with the data lifecycle. With this, you can manage how long data should be stored until it has to be deleted.</p>
<p><strong>Features</strong>:</p>
<ul>
<li>You don’t have a minimum object size.</li>
<li>You have access to storage locations all around the world.</li>
<li>Very high durability and low latency.</li>
<li>Data has redundancy across several geographic locations.</li>
</ul>
<h3 id="heading-lakefshttpslakefsio"><a target="_blank" href="https://lakefs.io/">LakeFS</a></h3>
<p><img src="https://lh5.googleusercontent.com/bcXj_Y_kRrMpi2AzKVSuNcXLXB1nM9q3DvYSFzLRUgq_kCoiR3XIwp4RCF8oCyZj0NsEdwYEhozemu6VlYKSZuEkN_Lboe5xLmVXLzGMBTZJOaZp5grKe_NKRgm6aUJ9GA" alt="Image" width="1354" height="669" loading="lazy"></p>
<p>LakeFS is an open-source tool that works with object storage <a target="_blank" href="https://aws.amazon.com/big-data/datalakes-and-analytics/what-is-a-data-lake/">data lakes</a>. Data lakes usually store files or blobs in raw format centrally through a repository.</p>
<p>Data lakes, on their own, are limited by the lack of frequent communication between entities. LakeFS solves this by using data versioning.</p>
<p><strong>Features:</strong></p>
<ul>
<li>Through S3 or GCS, it allows scaling up to Petabytes in size by using a system that mimics Git.</li>
<li>You can experiment as it provides you with a development environment with your data.</li>
<li>Since it uses a Git-like scheme, you can safely use new data in another branch without affecting the main branch. You can then, later on, merge it safely once each aspect of new data checks out (schema, etc.).</li>
</ul>
<h3 id="heading-miniiohttpsminio"><a target="_blank" href="https://min.io/">MiniIO</a></h3>
<p><img src="https://lh6.googleusercontent.com/dUASXaVGj9APcrVmK0EYEU4-tbs7eSjSasDfyDXLF6_lk2MgIG2aFLPA70y2sGa5WaTWgQRQHbzkCeT4cvCDg30_dgVJyBx0qzhnNvzNboJHTMb7htYdlS09FbVEiQvmrA" alt="Image" width="1354" height="669" loading="lazy"></p>
<p>MiniIO is another open-source solution. It utilizes the Amazon S3 API, which makes it perfect for high scale projects that require super strict security.</p>
<p><strong>Features:</strong></p>
<ul>
<li>It calls itself the world’s fastest object storage as it has a read/write speed of up to 183 GB.</li>
<li>It applies web scaling principles – a cluster can join forces with other clusters until it forms multiple data centers.</li>
<li>It’s Kubernetes friendly.</li>
<li>Because it's open source, users can improve and freely redistribute it.</li>
</ul>
<h3 id="heading-stackpathhttpswwwstackpathcomproductsobject-storagesourceaffiliateampirgwc1ampclickidxtbytz2dxxylthdwux0mo3qwukew1b2pyt54ua0"><a target="_blank" href="https://www.stackpath.com/products/object-storage/?source=affiliate&amp;irgwc=1&amp;clickid=Xtbytz2dXxyLTHDwUx0Mo3QWUkEw1B2PYT54UA0">Stackpath</a></h3>
<p><img src="https://lh3.googleusercontent.com/Jb-xzBULDvCI5nZyffRY4xIT8c1Qez_Ik86zlAa2N3hPjk_hBQC3fDGdPbg57bcf38UmEvEulXynAZpjcBn06Zwicqgtbzl6MzgTHs5wl4GwoGyPrtxaAkw1YG4GsZwauw" alt="Image" width="1354" height="669" loading="lazy"></p>
<p>StackPath offers both a Content-Delivery Network service, <a target="_blank" href="https://www.networkworld.com/article/3224893/what-is-edge-computing-and-how-it-s-changing-the-network.html">Edge Computing</a>, and an S3 compatible Object Storage. It touts itself as a cheaper option to Amazon S3 and other cloud providers.</p>
<p><strong>Features</strong>:</p>
<ul>
<li>It is six times faster than competing services, especially when combined with the CDN or the Edge Computing platform.</li>
<li>It is serverless, which means it needs no warmup.</li>
<li>It has 45 edge locations, which means your application is available worldwide with the same performance anywhere.</li>
</ul>
<h3 id="heading-in-closing">In Closing</h3>
<p>There you have it – a short list of the top object storage tools that you can use for your next web or mobile project. Object storage has indeed proven a great way to store data when scalability is the most significant consideration.</p>
<p>Thanks for reading this article! I hope you learned a thing or two about storage models, especially about object storage. Please feel free to connect with me on <a target="_blank" href="https://linkedin.com/in/rvvergara">LinkedIn</a> and <a target="_blank" href="https://twitter.com/coachryanv">Twitter</a>.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Best Automation Testing Tools For Developers ]]>
                </title>
                <description>
                    <![CDATA[ Test-driven development is something that every software developer should implement in their projects.  The success of using TDD, however, depends highly on how productive the developer can be while implementing code and application testing. This is ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/best-automation-testing-tools-for-developers/</link>
                <guid isPermaLink="false">66bb5246074d8d7b12eae37a</guid>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ automation testing  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Mon, 05 Oct 2020 16:47:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/arif-riyanto-G1N9kDHqBrQ-unsplash-1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Test-driven development is something that every software developer should implement in their projects. </p>
<p>The success of using <a target="_blank" href="https://www.guru99.com/test-driven-development.html">TDD</a>, however, depends highly on how productive the developer can be while implementing code and application testing.</p>
<p>This is where automation tools come in.</p>
<p>Below is a list of 10 recommended testing automation frameworks/platforms and a short summary of their features.</p>
<h2 id="heading-seleniumhttpswwwseleniumdev"><a target="_blank" href="https://www.selenium.dev/">Selenium</a></h2>
<p><img src="https://lh3.googleusercontent.com/fOEtWbGlSP_hzAkDaSowqKEUiz9l6e8l9nGNuVuZhXhCJRVGSEuA59oWIWyP387ndCrEsuB1K2Z3_c2quLaM1OB5iaLreOLydfaTiPlmhlAvj_OnS-jIJUhUBAg0bSZh1A" alt="Image" width="421" height="298" loading="lazy"></p>
<p>Selenium is, arguably, the most popular automated testing framework. It is a browser-based framework that works on different operating systems and browsers.</p>
<p>It features the Selenium IDE, which is Chrome and Firefox extension that allows the recording and playback of user interactions. For scaling tests (i.e, running on several machines) then Selenium Grid is the tool of choice.</p>
<p>The most popular tool in the framework is Selenium Webdriver, which is a collection of language specific bindings and allows for the creation of browser-based regression tests.</p>
<h2 id="heading-perfectoiohttpswwwperfectoio"><a target="_blank" href="https://www.perfecto.io/">Perfecto.io</a></h2>
<p><img src="https://lh4.googleusercontent.com/DplVGhU1kNQJVWhayvQ4h738H_M97iYitDoxAaDFCRDTwlZffOg9KlyhuJM2QW1HvpJrAOvX8yhlyuufjiNc_GnoqUw7nZE2IEZIvjTFSKhVwZz57KENe4XXlRoGNAY9ww" alt="Image" width="1200" height="750" loading="lazy"></p>
<p>Perfecto is both a web and mobile app testing framework. It’s delivered as a SaaS tool and allows testing engineers to run their tests from anywhere.</p>
<p>The web testing tool provides for parallel testing of apps on different operating systems and browsers. It allows for a huge volume of daily tests to be run, and the tests are 50% faster than any other framework.</p>
<p>The mobile test tool allows engineers to test on both emulators and actual devices. Just like the web test tool, it allows for a high volume of test runs daily (10,000 executions).</p>
<h2 id="heading-serenityhttpwwwthucydidesinfo"><a target="_blank" href="http://www.thucydides.info/#/">Serenity</a></h2>
<p><img src="https://lh4.googleusercontent.com/TQ1Vqg7502EEaW8P8S9cYHz_1ebaXSqA95ilO6KzMe13vR_CK29WH_jZESyU2EutJD6XOV63R0PbnR7_NtqKgS59Rh7nk6iuA8YlcIlCFq3heOeN3b4K06Zs8_eLPSFeww" alt="Image" width="1008" height="609" loading="lazy"></p>
<p>Serenity BDD’s slogan is “Automated Acceptance Testing with Style”. This is because Serenity’s unique angle is helping testers write world-class test reports and documentation.</p>
<p>Testing starts with the creation of user stories and acceptance criteria. Serenity then automates the acceptance criteria. Tests are automatically broken down into steps that make them more readable. Developers can easily run these tests against actual application executions.</p>
<p>Once tests are finished, Serenity creates detailed reports that include screenshots of the tests and all relevant information such as error messages and execution times.</p>
<h2 id="heading-cypresshttpswwwcypressio"><a target="_blank" href="https://www.cypress.io/">Cypress</a></h2>
<p><img src="https://lh4.googleusercontent.com/q6KHdpPaoPhHi5JKT5HA4oH_00gVtIuCW8JdPITzA7VxGZhL1GbFp3g5dxH9roP6WRU4wys8jQLWyH0_Depy1o4FblwzNweaEiCeS6AmlifxVFWE07IZlJX5VNM1M_Zvpg" alt="Image" width="1102" height="599" loading="lazy"></p>
<p>Cypress is a great tool to use for frontend or end-to-end <a target="_blank" href="https://www.perfecto.io/blog/what-is-test-automation">automated testing</a>.</p>
<p>Installing Cypress in a project is as easy as running a simple <code>npm install cypress</code> or <code>yarn add cypress</code> command. JavaScript developers who are used to unit testing tools such as <a target="_blank" href="http://jestjs.io/">Jest</a> or <a target="_blank" href="https://mochajs.org/">Mocha</a> will find writing Cypress test scripts a breeze.</p>
<p>Its dashboard makes testing more powerful and faster by allowing tests to be grouped by browser type, environment, package type, and so on. The parallelization feature allows developers to run more tests and test more features easily.</p>
<h2 id="heading-lambda-testhttpswwwlambdatestcom"><a target="_blank" href="https://www.lambdatest.com/">Lambda Test</a></h2>
<p><img src="https://lh5.googleusercontent.com/7w_SznSrnJ3RbUpAjsWmHuuHZmJYCRIJpncsvXuedQrBix8lp80YKqBDADgSjNKYdoY6a2q6gmeyPeQ3vDwG8y9BxP8iABYLJvpWq8d9_ATFXmdLhvCpW7Lz6XFmDrEWCg" alt="Image" width="758" height="560" loading="lazy"></p>
<p>LambdaTest is a leading test automation software for both desktop and web apps.</p>
<p>It allows for live and interactive testing of both publicly hosted and local machine hosted web applications and websites.</p>
<p>LambdaTest also allows developers to run Selenium test scripts with its Browser Testing Grid. It is a very powerful and versatile suite that also integrates with CI/CD tools such as Jenkins, Circle CI, and Travis CI.</p>
<p>Now the coolest part is that it allows for geo-testing, meaning web applications can be tested for how they perform depending on which location in the world they are being accessed from.</p>
<h2 id="heading-testprojectiohttpstestprojectio"><a target="_blank" href="https://testproject.io/">TestProject.io</a></h2>
<p><img src="https://lh3.googleusercontent.com/AFtWUpNPNMMP382wf89DoDKiWgtJn8FFNY6NEYKT2DQ-w4PAJlw72WaByvEWHatg0hA6JZxYVSnnN0VovjB7swkEu_XstmWNnSiWaNzn-eCN2THVed57P0j4ZcLxcm6kEw" alt="Image" width="1335" height="587" loading="lazy"></p>
<p>TestProject’s community is probably one of the biggest among those in the testing community. It is an end-to-end and API cloud hosted test framework.</p>
<p>As an open-source project, users get easy access to updates and can even participate in its improvements. It is ready for use with Selenium with all of its pre-packaged dependencies.</p>
<p>With its myriad of integration tools, it allows for testing on different browsers, and even in Docker.</p>
<p>One of the best things about TestProject is it allows non-coders to perform testing through its Scriptless Test recorder.</p>
<h2 id="heading-katalon-studiohttpswwwkataloncomhomepagepkabeabtestinghomepage082020amppkabvlayout2"><a target="_blank" href="https://www.katalon.com/homepage/?pk_abe=AB_testing_Homepage_08_2020&amp;pk_abv=layout2">Katalon Studio</a></h2>
<p><img src="https://lh4.googleusercontent.com/Etrs1mFEa-U-0wofZ-Vw-Cmn0G9dlZbA1DcMjs1M2hDXVK3qBe2VJ4X-o1KKH-6dUoxLHdm-LknJPbinYRpWBlBIQTtYM9Qf8nf0hNTYDQrbNYzud_0ZQg-4wLNoTiBWEg" alt="Image" width="873" height="466" loading="lazy"></p>
<p>Another open-source API, web, and mobile testing suite is Katalon Studio. It is one of the most complete testing suites in the entire list, with features like recording, auto-generating test scripts, and powerful integrations.</p>
<p>It is a testing framework that is easy to start (yes, even for non-coders) but is powerful enough for scaling.</p>
<p>Katalon Studio works well with existing CI/CD setups. For instance, it's easy to integrate it with Github or Gitlab’s continuous testing tools. This makes it great for Agile teams.</p>
<h2 id="heading-opentesthttpsgetopentestorg"><a target="_blank" href="https://getopentest.org/">OpenTest</a></h2>
<p><img src="https://lh6.googleusercontent.com/ht1yDKuYIf2V3aQakjQqZSKeIPIfUrOr5b_sowtlr7f2l-h7Hr3_bHcX41fZoLDBNGJXWhaY8Gd7RUAiCAZMYGoGA7Ra63WwSWrO9iwxeu7mjisKyZ5dANIoq97eq_jIiw" alt="Image" width="1600" height="1000" loading="lazy"></p>
<p>OpenTest is another open source tool that automates testing for API’s, web, mobile and desktop applications. It is mostly used for functional testing.</p>
<p>It still has lots of limitations as there are some test scenarios that are not yet supported. However, it is very good for beginners and non-coders alike since it uses plain English keywords for writing test actions.</p>
<p>Some of its most notable features include web testing with Selenium, mobile testing with Appium, keyword-driven testing, parallel testing, and data-driven testing.</p>
<h2 id="heading-accelqhttpswwwaccelqcom"><a target="_blank" href="https://www.accelq.com/">AccelQ</a></h2>
<p><img src="https://lh3.googleusercontent.com/HLpAj_Qg-Prqnp6Zq5i9WtahnDrBQjclRAknTaCiS_20fc40jEUDWgnu1gt5M6mpt4sfYtQkMGwnazK95RRTU8LRyk9jajQ4OkeSKptTgaP8sq14cDttfsb7MqtHY30CMw" alt="Image" width="1600" height="862" loading="lazy"></p>
<p>AccelQ is a codeless test automation platform that is artificial-intelligence based. As such, it is best used for Agile development as it allows for rapid building and easy introduction of changes in the project.</p>
<p>The platform allows for API and end-to-end testing. The AI backbone provides predictive analytics that help in accelerating the test script generation. It has an intuitive and easy to use UI that allows even beginners to get started quickly.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The choice boils down to, not surprisingly, your particular use-case. </p>
<p>However, given the extensive capabilities of each of these tools, it is understandably difficult to select one. The beautiful thing about a lot of them being open source is that development teams can use one for a particular project, and another for a different one.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make Your Dev Team More Productive ]]>
                </title>
                <description>
                    <![CDATA[ Whether you’re a startup founder or a long-term dev team manager, you want your developer team to be as productive as possible. Here are a few tips you can use to help your team improve, become more efficient, and deliver on projects faster. The Engi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-your-team-more-productive/</link>
                <guid isPermaLink="false">66bb524f24c949cee2fb6bd1</guid>
                
                    <category>
                        <![CDATA[ motivation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ startup ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Mon, 21 Sep 2020 17:24:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/mimi-thian-vdXMSiX-n6M-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Whether you’re a startup founder or a long-term dev team manager, you want your developer team to be as productive as possible.</p>
<p>Here are a few tips you can use to help your team improve, become more efficient, and deliver on projects faster.</p>
<h2 id="heading-the-engineers-way-of-improving-team-productivity">The Engineer’s Way of Improving Team Productivity</h2>
<p>The importance of providing your team with the right tools cannot be overstated. It's not the only important factor, as we’ll see later, but it can definitely make certain processes go more smoothly.</p>
<p>For instance, since code debugging is one of the most tedious tasks a developer needs to perform, you can equip your team with tools that will help them debug faster and more conveniently.</p>
<p>Let’s say you observe that your developers, who are working remotely in different parts of the world, are getting stuck with debugging code. </p>
<p>Debugging your own code is challenging enough. But if you have to debug someone else's – and they live in a different time zone – it can cause massive delays.</p>
<p>Using a debugger can help manage issues like these and make the entire team faster and more efficient.</p>
<h3 id="heading-go-beyond-the-system-to-the-people">Go beyond the system – to the people</h3>
<p>However, increasing productivity isn’t just about finding the right tools to get the job done. A dev team is a group of human beings, not just code. And humans are complex organisms. </p>
<p>Additionally, software developers are highly intelligent individuals. Thus, they tend to not perform as well if what they’re doing isn’t challenging.</p>
<p>The point is not to look at productivity just at the system level. You need to also see the people who are inside that system.</p>
<p>This is a big problem I see with most startup founders or dev team managers. Most neglect developing leadership skills.</p>
<p>A team of developers isn’t so different from any other kind of a team. It’s a group of individuals put together to accomplish a goal. No matter how “horizontal” you think your team should be, at the end of the day it will fall apart without leadership.</p>
<p>Having been an avid learner in the subject of leadership, I will be borrowing some wisdom from John C. Maxwell’s <a target="_blank" href="https://www.amazon.com/17-Indisputable-Laws-Teamwork-Embrace/dp/1400204739">The 17 Indisputable Laws Of Teamwork</a>.</p>
<h2 id="heading-make-sure-your-team-has-a-vision">Make Sure Your Team Has a Vision</h2>
<p><img src="https://lh4.googleusercontent.com/Csd9qY2eCyAC7ukDOeeTY6a7WKLc8StyTlRZEt3Tk1nFfJhPSCFn9P5EuuH-aCwxT_eLLa0XgLuOuPTsLZebxid5HjrZWZ_ZITMjueDMe7l_Jmn67Fid9qALAvtTLfycxg" alt="Image" width="1600" height="1067" loading="lazy"></p>
<p>A vision gives direction to the team. It provides a battlecry that will make each member emotionally invested in the team’s goals.</p>
<p>A vision also ensures that individual achievements aren’t meaningless trophies. Each member can now align their individual goals to what the whole team ultimately wants to achieve.</p>
<p>For instance, take a look at Apple's vision statement:</p>
<blockquote>
<p>"We are on the face of the earth to make great products, and that’s not changing. We don't settle for anything less than excellence."</p>
</blockquote>
<p>With this kind of vision, each team member will believe that each line of code they write contributes to creating great products and not settling for anything less than excellence.</p>
<p>Productivity naturally occurs, as each member will have a higher view of their contributions to the team.</p>
<h2 id="heading-focus-on-your-teams-strengths">Focus on Your Team’s Strengths</h2>
<p>Having talented developers in the team doesn’t necessarily translate to excellence in performance. Each member of the team has a particular expertise that needs to be utilized in the right tasks for that expertise.</p>
<p>A team’s dynamic changes depending on how members are placed. For instance, place one person in the wrong task and you'll get a confused team. Or worse, it will generate frustration (and resentment).</p>
<p>But pairing the right people with the right tasks will create progress and a high level of motivation (and thus productivity) in the team.</p>
<p>So how do you ensure that you’re focusing on your team’s strengths? Here are a few tips:</p>
<ol>
<li>You must personally be familiar with every aspect of the team’s vision and shared values.</li>
<li>Not only should you be intimate with the vision and core values of the team, but you have to know how to adapt the team depending on each situation. Rigidity and an unwillingness to adapt kills productivity.</li>
<li>It’s important that you, as a leader, know each member personally so you’ll easily understand which tasks they’re more suited for.</li>
</ol>
<h2 id="heading-constantly-work-on-better-communication">Constantly Work on Better Communication</h2>
<p><img src="https://lh4.googleusercontent.com/iKrNIRR30VBOzUJL_9W3ygGlC27luei4qO0CNgfkdjK5tjESzXQeEMioRk71wl0uqnGWGSWp5dwQRsLgHkgwHbYFlomyQEFocrF5Ynw4A0bLL-h2PFna1VqOSSgl7UiqkA" alt="Image" width="1600" height="1200" loading="lazy"></p>
<p>This may sound cliché, but I cannot overemphasize the importance of communication.</p>
<p>Software developers, especially when they’re “in the zone”, wearing headphones, shut themselves off from the outside world. They do this so they can focus.</p>
<p>It’s great. Coding is an art. The coder is the artist. Any distraction ruins the masterpiece.</p>
<p>But this doesn’t mean we cannot introduce systems and tools that encourage everybody to speak their minds and share ideas.</p>
<p><a target="_blank" href="https://blog.bird-office.com/en/2017/08/23/advantages-stand-meeting/">Stand-up meetings</a> provide for a short but very effective way for everybody to get updated on the team’s progress.</p>
<p>Communication tools such as Slack or Telegram ensure that information is shared in <a target="_blank" href="https://smallbusiness.chron.com/pros-using-im-workplace-10534.html">real time</a>.</p>
<p>Github and Gitlab also have tools that allow teams to discuss issues and be able to resolve them.</p>
<p>For example, team members can review each other's code and ensure proper collaboration on improving shipped code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/image-111.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image courtesy of: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The bottom line is that increasing your dev team’s productivity is a mixture of systemization of tasks (such as equipping them with the right tools) and enhancing their potential as human beings. </p>
<p>This not only will ensure you have a highly productive team, but also a group of happy individuals avoiding burnout and enjoying doing what they do best.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Best Application Security Tools in 2020 ]]>
                </title>
                <description>
                    <![CDATA[ Software has become more and more ubiquitous. Open source libraries are widely used as they make it easy for developers to focus on the core features of the applications they’re building. Using these open source libraries provides tremendous producti... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/best-application-security-tools-in-2020ed/</link>
                <guid isPermaLink="false">66bb524324c949cee2fb6bcf</guid>
                
                    <category>
                        <![CDATA[ Web App Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Application Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Tue, 08 Sep 2020 16:56:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/corinne-kutz-tMI2_-r5Nfo-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Software has become more and more ubiquitous. Open source libraries are widely used as they make it easy for developers to focus on the core features of the applications they’re building.</p>
<p>Using these open source libraries provides tremendous productivity benefits. However, it also comes with disadvantages – namely in relation to security.</p>
<p>Cyber-criminals and hackers have been increasingly exploiting vulnerabilities in applications and IT systems. It has, therefore, become more and more important to ensure that code bases minimize or totally eliminate vulnerabilities.</p>
<p>However, keeping tabs on all the vulnerabilities, let alone updated ones, in projects can be very daunting. That’s why in this article we’ll take a look at eight tools that automate the detection and fixing of vulnerable spots in a project.</p>
<h2 id="heading-deepscan">DeepScan</h2>
<p><img src="https://lh5.googleusercontent.com/vuWbsmQMINLuAr1tebYQarvIebIladiOhTOGjsTUl1RD9uSXvB8Q970XMd_6IEcQTy6ubG61E79EZGC9fVa-EzOryvnhhfUP652kJBGXYxpAE29S1Ax1gllq8CM1VaUwKA" alt="Image" width="1287" height="552" loading="lazy"></p>
<p>DeepScan is a tool that analyzes JavaScript and TypeScript code. At its core, it not only inspects for code quality à la ESLint, but it also employs data-flow analysis and looks into the execution flow. Errors and quality issues are detected even without running the code.</p>
<p>DeepScan works with most JavaScript libraries such as React and Vue.js.</p>
<p>Teams can simply integrate their projects’ GitHub repository with DeepScan. Every time a push is made into a repository, DeepScan provides a real time report on test results. </p>
<p>One of the best things about this is that code quality standards are more enforceable. DeepScan motivates teams to write quality code by grading the project as Poor, Normal, or Good.</p>
<h2 id="heading-sonarqube">SonarQube</h2>
<p><img src="https://lh3.googleusercontent.com/SURJlYBtjoi0RD-3HI9GyI0JhQqgcNO9JZQJJyRTyYmyI0IorGp3IwYTQQL51mEkfLMhYHchedXdNtI4bzkViT2cDVGwzLXa4s-jplyxMyup7e3GWpzuy0T_nCVKYbu2mg" alt="Image" width="1210" height="647" loading="lazy"></p>
<p>SonarQube is an open-source platform that continuously inspects a project for code quality, bugs, code-smells and even security vulnerabilities.</p>
<p>It's a tool written in Java but has the ability to analyze other languages through the use of plugins. </p>
<p>Unlike most of the others in this list, SonarQube isn’t integrated into a project as a simple GitHub extension. It needs to be installed in the local machine for you to be able to use it.</p>
<p>It works by receiving the project’s files as input and then making the necessary analysis. It then generates data based on the analysis, stores that data in a database, and displays it in a dashboard.</p>
<h2 id="heading-dependabot">Dependabot</h2>
<p><img src="https://lh6.googleusercontent.com/qXWWBNa5LZVuRQl442r-KrFOWbQNNWsJbjqDAt4tv-UjAVTgVmiQ6mdNR0-WbiYRfZhPVXStmA7OV8WHVDzd6tbzSu_4O4PE-tBMEKpHg7D5FEX_YpD_t-kWVjZhWdBX0A" alt="Image" width="1052" height="581" loading="lazy"></p>
<p>Dependabot is a tool you use inside of GitHub that automatically creates pull requests upon detection of vulnerabilities.</p>
<p>This tool performs scans on all of a repository’s dependency files and searches for outdated or insecure dependencies. It then generates a single pull request for each outdated or insecure dependency. The developer can then check those pull requests and merge as necessary.</p>
<p>The great thing about Dependabot is that it’s owned by GitHub so that it can be seamlessly integrated into any repository. It performs constant monitoring and quickly updates users when there's a new vulnerability.</p>
<p>It can be very chaotic to receive daily notifications, so users can configure the frequency that the tool performs scans and creates pull requests.</p>
<h2 id="heading-sourceclear">SourceClear</h2>
<p><img src="https://lh6.googleusercontent.com/j7uvCW3rdbFP5gwvZKZ8fq9vUCSmLnsPtKKixXa3ShyZMd5Nvzr3OfNwmPrfvliO70EN5sdCYd6L9rL4KN1F9KND3DHdfo2vkTOeQMtkKyUNoB0_wE1zQIjhhXPEXV6Yhg" alt="Image" width="1192" height="469" loading="lazy"></p>
<p>SourceClear is a tool that helps developers understand more about the open source libraries they are using. SourceClear provides information on those libraries such as who created them, what they do, and which dependencies of such libraries have vulnerabilities.</p>
<p>SourceClear meshes well with a developer’s workflow and provides real-time reports on open-source code risks. It has machine-learning tools that makes it possible to provide such detailed information for each library used.</p>
<p>One of its main features is the prioritization of vulnerabilities that are directly in the code’s execution path. This can reduce remediation time for big projects by up to 90%.</p>
<h2 id="heading-spotbugs">SpotBugs</h2>
<p><img src="https://lh5.googleusercontent.com/udDfNTSn2DTsmNOESuK_KFK7J1SVE1upA-2IfQxJ4dBTTf6VSzyca1rGjD_PVsfQov2SW3f5c4Yq-ai7ZpAeA8ZafzbeATaBGnSYAWMLb-_A1RHZFe5q_o06ZrBtPFXxVw" alt="Image" width="1034" height="408" loading="lazy"></p>
<p>SpotBugs, a successor to FindBugs, is a static code analyzer for Java code bases. It can either be used as a stand-alone tool or integrated to other platforms/tools.</p>
<p>Most Java programs compile cleanly but are still buggy. Compilation captures mostly only syntax and references errors, among others. Usage of static analysis tools such as SpotBugs provides a more comprehensive solution in catching bugs and even vulnerabilities.</p>
<p>SpotBugs inspects Java bytecode (not the source code) and checks for bug patterns. It then classifies errors or potential errors based on how severe they are: Of Concern, Troubling, Scary, Scariest.</p>
<p>This tool is very good at identifying bug patterns (over 400).</p>
<h2 id="heading-arxan-application-protection">Arxan Application Protection</h2>
<p><img src="https://lh4.googleusercontent.com/T0tufco3sAC5q_EG_CfcKKXMS0XGyY-RQXrr52YSD_F51vtGuuAQDNnq4bxoIsOGFDowj0SmbE_5nagoFH86k8j_BAz5-kYBKu_48JEezinD6PbhAD7NjV1L-t-SGY7iLQ" alt="Image" width="1169" height="422" loading="lazy"></p>
<p>Arxan Application Protection is a total solution to “protect apps inside and out”. This tool’s main selling point - Protecting applications against reverse engineering.</p>
<p>A lot of today’s attacks such as <a target="_blank" href="https://en.wikipedia.org/wiki/Clickjacking">clickjacking</a> are engineered by cyber-criminals through hacking the app’s binary code and then creating a replica app. Users are then lured into trusting this fake app and giving away their data such as banking passwords.</p>
<p>Arxan protects an application from such attacks by “hardening” the application’s code by inserting “code guards” into them. These code guards are tiny security units which protect the application and each other against compromise and they detect attacks at runtime.</p>
<h2 id="heading-gitlab">GitLab</h2>
<p><img src="https://lh3.googleusercontent.com/eXpuwOc4PRGblwLr6qMK42LKuUv59By2wzb6ldd9h5PSUi_1_NSLK3M1L5qWiUh8OnNQSDgPVrPmqunzovYwa09Uu1fFPqiddGZEng6XYZ3YyLm0uHJy0McSwk8x4-YQtQ" alt="Image" width="1238" height="665" loading="lazy"></p>
<p>One of GitLab’s core value propositions to developers is that it is one of the most exquisite devops tools out there. Added to this is GitLab’s focus on secure deployment.</p>
<p>The platform has incorporated security in its already loaded devops arsenal. Developers can focus on coding while being confident that any security vulnerability will quickly be detected. This makes it very pleasant to use, as no additional tool or integration is necessary.</p>
<p>It employs what it calls the Secure Stage where all the security parts of devops are performed. This “stage” has a goal of identifying proactively any vulnerabilities before they can be exploited in production code.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Each tool has its own pros and cons and the choice to use one over the other depends on the particular taste of the developer. Often, some tools can even be used together. </p>
<p>The bottom line is that nowadays we are more equipped to handle security issues before they become big problems in our application projects.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to calculate Binary Tree height with the recursive method ]]>
                </title>
                <description>
                    <![CDATA[ Previously I wrote about an algorithm for finding out the height of a binary tree using iteration. Though that method gets the job done (in 7 steps no less), the same can be accomplished in a much simpler way. In my opinion, one of the most powerful ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-calculate-binary-tree-height-with-the-recursive-method-aafc461f2201/</link>
                <guid isPermaLink="false">66bb524c074d8d7b12eae37c</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Recursion ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Mon, 07 Jan 2019 23:49:21 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*ci3-dY6FOCFu2UeqtzJ73A.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Previously I wrote about an algorithm for finding out the height of a binary tree <a target="_blank" href="https://medium.freecodecamp.org/how-to-calculate-a-binary-trees-height-using-array-iteration-in-ruby-63551c6c65fe">using iteration</a>. Though that method gets the job done (in 7 steps no less), the same can be accomplished in a much simpler way.</p>
<p>In my opinion, one of the most powerful programming techniques is recursion. For readers new to programming — it is simply a function or method calling itself. To make the introduction simpler we have a method below that calls another method:</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_method</span><span class="hljs-params">(name)</span></span>       (R1)
  inner_method + name
<span class="hljs-keyword">end</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_method</span>             <span class="hljs-params">(R2)</span></span>
  <span class="hljs-string">"Hello "</span>
<span class="hljs-keyword">end</span>
print outer_method(<span class="hljs-string">"Steve"</span>) -&gt; <span class="hljs-comment">#"Hello Steve"</span>
</code></pre>
<p>In the above method <code>outer_method</code>, which takes in a string as argument, calls <code>inner_method</code>, which simply returns the string <code>“Hello “</code> inside it. Recursion is similar in that, say in this case, <code>outer_method</code> simply calls itself:</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_method</span><span class="hljs-params">(name)</span></span>              (R3)
  outer_method(<span class="hljs-string">"hello "</span>) + name
<span class="hljs-keyword">end</span> (R3)
</code></pre>
<p>One caveat, though, with code <code>R3</code> above — it will run until the computer complains that resources are not enough to keep processing the method. It’s like running an infinite loop except that infinite loops don’t necessarily raise exceptions. The reason for this is that code <code>R3</code> doesn’t have a ‘terminal state’ or a point where it doesn’t ‘recurse’ anymore.</p>
<p>We can solve this by including a terminal state:</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_method</span><span class="hljs-params">(name)</span></span>                 (R4)
  <span class="hljs-keyword">return</span> name <span class="hljs-keyword">if</span> name == <span class="hljs-string">"hello "</span>
  outer_method(<span class="hljs-string">"hello "</span>) + name
<span class="hljs-keyword">end</span>
</code></pre>
<p>The first line inside the method definition simply states that if the argument <code>name</code> is equal to <code>‘hello’</code> then simply return <code>name</code>. That will then ignore any line after it. Therefore in the second line, the code <code>outer_method(“hello “)</code> will simply give the string “hello “ to be added to whatever name is in the main argument. So the same <code>print outer_method(“Steve”)</code> will result in the output <code>“hello Steve”</code> as well.</p>
<p>OK then, that may not be the best example for describing recursion (as the recursive version in this case doesn’t have that much advantage over the non-recursive one). But working on the binary tree height problem, we will see that recursion is so much simpler to understand and faster to run.</p>
<p>For this discussion let me put again the same example as I showed in the previous article:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*tsVyCA_zXrAh3LqTF4LHxw.png" alt="Image" width="727" height="337" loading="lazy">
<em>Figure 1: Simple binary tree</em></p>
<p>which we can represent as the following array:</p>
<pre><code class="lang-ruby">tree = [<span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">6</span>, <span class="hljs-number">0</span>, <span class="hljs-number">9</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">11</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">4</span>, <span class="hljs-number">0</span>] (T<span class="hljs-number">0</span>)
</code></pre>
<p>The indices of the left and right children of any sub tree can be determined as follows:</p>
<pre><code class="lang-ruby">left child of tree[i] is at index <span class="hljs-number">2</span>*i + <span class="hljs-number">1</span> (T1)
right child of tree[i] is at index <span class="hljs-number">2</span>*i + <span class="hljs-number">2</span> (T2)
</code></pre>
<p>If you’re puzzled about how the figure above became the array following it, I’ll direct you to read the <a target="_blank" href="https://medium.freecodecamp.org/how-to-calculate-a-binary-trees-height-using-array-iteration-in-ruby-63551c6c65fe">previous article</a> on the iterative method for clarification.</p>
<p>And again the formula for calculating the height of a binary tree, as well as the heights of any of its sub trees, is:</p>
<pre><code class="lang-ruby">height = <span class="hljs-number">1</span> + max of(left_child_height, right_child_height) (T3)
</code></pre>
<p>Now with these we can outline the steps to develop a recursive program.</p>
<p><strong>Step 0:</strong> Set default values — To make the initial method call simple, I always like setting default values for the arguments that will change during each recursive call. Since we will repetitively compute heights, our indices will always change.</p>
<p>For instance, to find the height of the root’s (<code>tree[0]</code>) left child we will need to call the method on that left child (whose index is at <code>2*(0) + 1</code>). Therefore, our method definition will be:</p>
<pre><code class="lang-rb"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tree_height_recursive</span><span class="hljs-params">(tree_array,i=<span class="hljs-number">0</span>)</span></span> (S<span class="hljs-number">0</span>.<span class="hljs-number">1</span>)
</code></pre>
<p>to indicate that for the initial call we are calling it on the root element. This will simply allow us to call <code>tree_height_recursive</code> by inputting only the tree_array. However, this also means, as we will see in the simulation afterwards, we can find the height of any sub tree by simply including its index as the second argument in the method call.</p>
<p><strong>Step 1:</strong> Find terminal state — At which point do we simply return a value and not do any further recursive calls? In our binary tree problem, the terminal state is at:</p>
<pre><code class="lang-rb"><span class="hljs-keyword">return</span> <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> tree[i].<span class="hljs-literal">nil</span> <span class="hljs-keyword">or</span> tree[i] == <span class="hljs-number">0</span> (S1.<span class="hljs-number">1</span>)
</code></pre>
<p>It simply says that if the element at index <code>i</code> does not exist or if its value is 0 then simply return 0. Logically, a non-existing sub tree will not have any height.</p>
<p><strong>Step 2:</strong> Find the height of the left child — this is where the magic of recursion starts to benefit us. We don’t need any fancy code. No more declaring another array to hold the height of each element. No more multiple variable definitions for height indices and the heights themselves, just:</p>
<pre><code class="lang-rb">right_child_height = tree_height_recursive(tree_array, <span class="hljs-number">2</span>*i + <span class="hljs-number">2</span>)
</code></pre>
<p>We simply pass the index of the left child as second argument. Can you see why?</p>
<p>We do the same for finding the right child’s height next.</p>
<p><strong>Step 3:</strong> Find the height of right child — Likewise, we simply do a recursive call to our method but passing the index of the right child as second argument:</p>
<pre><code class="lang-rb">right_child_height = tree_height_recursive(tree_array, <span class="hljs-number">2</span>*i + <span class="hljs-number">2</span>)
</code></pre>
<p>Now that we have the heights of the left and right children, we can now compute the total height.</p>
<p><strong>Step 4:</strong> Calculate and return total height — As code <code>T3</code> states, we just add 1 and the height of whichever is taller between the left and right children.</p>
<pre><code class="lang-rb">total_height = <span class="hljs-number">1</span> + [left_child_height, right_child_height].max (S4.<span class="hljs-number">1</span>)
</code></pre>
<p>Since <code>S.4</code> will be the last statement in our method, then the evaluated <code>total_height</code> will be returned. Remember that if the conditions in <code>S1.1</code> hold true (our terminal state) then none of Steps 2–4 will run and the method will simply return 0.</p>
<p>The full method below:</p>
<p>Comparing this to the <a target="_blank" href="https://medium.freecodecamp.org/how-to-calculate-a-binary-trees-height-using-array-iteration-in-ruby-63551c6c65fe">iterative method</a>, the recursive version took 3 fewer steps and 4 fewer variable definitions. The code also (excluding empty spaces and comments) is 7 lines fewer. On top of it, the recursive code will run 2x faster (using the <code>benchmark</code> built-in Ruby module). This is a big advantage if we’re running the method on binary trees hundreds of levels tall.</p>
<p>Now let’s do the same simulation as we did before. For the tree at <code>T0</code> we run the recursive method:</p>
<pre><code>tree = [<span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">6</span>, <span class="hljs-number">0</span>, <span class="hljs-number">9</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">11</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">4</span>, <span class="hljs-number">0</span>]
</code></pre><pre><code class="lang-rb">puts tree_height_recursive(tree_array)-&gt; <span class="hljs-comment">#should give us 4</span>
</code></pre>
<p>Note that since we have a default <code>i=0</code> in our method definition we don’t need to specify the index here because we are finding the height of the whole tree. To make this simulation more intuitive we shall create an imaginary array called <code>call_stack</code> where push every call to <code>tree_height_recursive</code>.</p>
<p>So then when we call the method the first time (the main call), we store it in a temporary variable <code>ht_0</code> and push it to <code>call_stack</code>:</p>
<pre><code>ht_0 = height <span class="hljs-keyword">of</span> tree[<span class="hljs-number">0</span>] = tree_height_recursive(tree_array,i=<span class="hljs-number">0</span>)
</code></pre><pre><code class="lang-rb">call_stack = [ht_<span class="hljs-number">0</span>]
</code></pre>
<p>We then run Step 1:</p>
<pre><code class="lang-rb">tree[<span class="hljs-number">0</span>].<span class="hljs-literal">nil</span>? -&gt; <span class="hljs-comment">#falsetree[0] == 0 -&gt; #false, it is 2</span>
</code></pre>
<p>Since this results in <code>false</code>, we go ahead to Step 2:</p>
<pre><code>since i= <span class="hljs-number">0</span>, then <span class="hljs-number">2</span>*i + <span class="hljs-number">1</span> = <span class="hljs-number">2</span>*<span class="hljs-number">0</span> + <span class="hljs-number">1</span> = <span class="hljs-number">1</span>:
</code></pre><pre><code class="lang-rb">left_child_height = tree_height_recursive(tree_array,<span class="hljs-number">1</span>)
</code></pre>
<p>Since we cannot readily determine this height so then we push it again to <code>call_stack</code>:</p>
<pre><code>ht_1 = left_child_height = tree_height_recursive(tree_array,<span class="hljs-number">1</span>)
</code></pre><pre><code>call_stack = [ht_0,ht_1]
</code></pre><p>Then upon doing Step 3:</p>
<pre><code class="lang-rb">ht_2 = right_child_height = left_child_height = tree_height_recursive(tree_array,)
</code></pre>
<pre><code class="lang-rb">call_stack = [ht<span class="hljs-number">0</span>,ht1,ht2]
</code></pre>
<p>We cannot proceed to Step 4 until all the items in <code>call_stack</code> have been evaluated by our program and popped off from <code>call_stack</code> (which should happen for every time each height has been evaluated).</p>
<p>So we will also do the same for each of the succeeding heights. For instance, to compute <code>ht1</code> we know that we have to compute for its own left and right children’s heights too. So that means the method will be called for them too. So as not to prolong this article, the reader is invited to try this on paper.</p>
<p>Ultimately, the method will be called recursively with <code>i = 14</code> as second argument. Thus, at this point, <code>call_stack</code> will be:</p>
<pre><code class="lang-rb">call_stack = [ht<span class="hljs-number">0</span>,ht1,ht2,ht3,ht4,ht5,ht6,ht7,ht8,ht9,ht1<span class="hljs-number">0</span>,ht11,ht12,ht13,ht14]
</code></pre>
<p>Now we will evaluate each. Note that from <code>tree[7]</code> up to <code>tree[14]</code> the elements don’t have any children. So we can simply evaluate their heights as 1 or 0 (depending on whether <code>tree[i]</code> is 0 or not (where <code>i ≥ 7</code>):</p>
<pre><code>ht14 = <span class="hljs-number">0</span>
</code></pre><pre><code>ht13 = <span class="hljs-number">1</span>
</code></pre><pre><code>ht12 = <span class="hljs-number">0</span>
</code></pre><pre><code>ht11 = <span class="hljs-number">0</span>
</code></pre><pre><code>ht10 = <span class="hljs-number">1</span>
</code></pre><pre><code>ht9 = <span class="hljs-number">1</span>
</code></pre><pre><code>ht8 = <span class="hljs-number">1</span>
</code></pre><pre><code>ht7 = <span class="hljs-number">1</span>
</code></pre><p>Again, when these heights are evaluated we simply pop them off successively from <code>call_stack.</code> After which, <code>call_stack</code> will appear as follows:</p>
<pre><code class="lang-rb">call_stack = [ht<span class="hljs-number">0</span>, ht1, ht2, ht3, ht4, ht5, ht6]
</code></pre>
<p>Now, to evaluate <code>ht6</code> we must remember that it is the call to <code>tree_height_recursive(tree_array, 6)</code>. Inside this call we also call on the method to compute for the heights of the left and right children of <code>tree[6]</code>. These we previously already evaluated as <code>ht13</code> and <code>ht14</code>. So then:</p>
<pre><code class="lang-rb">ht6 = <span class="hljs-number">1</span> + [ht13, ht14].max = <span class="hljs-number">1</span> + [<span class="hljs-number">1</span>,<span class="hljs-number">0</span>] = <span class="hljs-number">1</span> + <span class="hljs-number">1</span> = <span class="hljs-number">2</span>
</code></pre>
<p>So we now evaluate <code>ht5</code>, which is the height of <code>tree[5]</code>. We know the heights of its children are <code>ht11</code> and <code>ht12</code></p>
<pre><code class="lang-rb">ht5 = <span class="hljs-number">1</span> + [ht11,ht12].max = <span class="hljs-number">1</span> + [<span class="hljs-number">0</span>,<span class="hljs-number">0</span>].max = <span class="hljs-number">1</span> + <span class="hljs-number">0</span> = <span class="hljs-number">1</span>
</code></pre>
<p>Doing the same for <code>ht4</code> to <code>h1</code> (again the reader is invited to do the confirmation on paper):</p>
<pre><code>ht4 = <span class="hljs-number">1</span> + [ht9,ht10].max = <span class="hljs-number">1</span> + [<span class="hljs-number">1</span>,<span class="hljs-number">1</span>].max = <span class="hljs-number">1</span> + <span class="hljs-number">1</span> = <span class="hljs-number">2</span>
</code></pre><pre><code>ht3 = <span class="hljs-number">1</span> + [ht7, ht8].max = <span class="hljs-number">1</span> + [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>].max = <span class="hljs-number">1</span> + <span class="hljs-number">1</span> = <span class="hljs-number">2</span>
</code></pre><pre><code>ht2 = <span class="hljs-number">1</span> + [ht5, ht6].max = <span class="hljs-number">1</span> + [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>].max = <span class="hljs-number">1</span> + <span class="hljs-number">2</span> = <span class="hljs-number">3</span>
</code></pre><pre><code class="lang-rb">ht1 = <span class="hljs-number">1</span> + [ht3, ht4].max = <span class="hljs-number">1</span> + [<span class="hljs-number">2</span>,<span class="hljs-number">2</span>].max = <span class="hljs-number">1</span> + <span class="hljs-number">3</span> = <span class="hljs-number">3</span>
</code></pre>
<p>Again, we pop out each height from <code>call_stack</code> as we evaluate it so after evaluating <code>ht1</code> the <code>call_stack</code> appears as follows:</p>
<pre><code class="lang-rb">call_stack = [ht<span class="hljs-number">0</span>]
</code></pre>
<p>Now evaluating <code>ht0</code> is returning to the main call to <code>tree_height_recursive</code>, so this is the remaining Step 4:</p>
<pre><code class="lang-rb">ht<span class="hljs-number">0</span> = <span class="hljs-number">1</span> + [ht1, ht2].max = <span class="hljs-number">1</span> + [<span class="hljs-number">3</span>, <span class="hljs-number">3</span>].max = <span class="hljs-number">1</span> + <span class="hljs-number">3</span> = <span class="hljs-number">4</span>ortotal_height = <span class="hljs-number">1</span> + [left_child_height, right_child_height].max
</code></pre>
<p>Which will return <code>4</code> as the result of the main method call.</p>
<p>As I keep mentioning, doing this on paper whether during the algorithm formulation or during simulation will help a lot in understanding it. This same method can also be used to determine the height of any of the sub trees inside the <code>tree_array</code>, for instance to determine only the height of the tree’s left child:</p>
<pre><code class="lang-rb">puts tree_height_recursive(tree_array, <span class="hljs-number">1</span>) -&gt; <span class="hljs-comment">#will print out 3</span>
</code></pre>
<p>Or any of the lower sub trees:</p>
<pre><code class="lang-rb">puts tree_height_recursive(tree_array, <span class="hljs-number">3</span>) -&gt; <span class="hljs-comment">#will print out 2</span>
</code></pre>
<h4 id="heading-wrapping-up">Wrapping up</h4>
<p>The key takeaway in creating a recursive algorithm, in my perspective, is setting the terminal state. Again, this is the scenario wherein the main method will not have to do any recursive call to itself. Without this, the method will just keep calling itself until the computer blows up (hyperbolically speaking…). When we have the terminal state we can easily set the arguments for the recursive calls and know that our method will safely return the value we expect.</p>
<p>Finally, working on algorithms challenge our minds to think. As software engineers, or even engineers in general, our main task is to solve problems. We, therefore, need to develop our critical thinking skills.</p>
<p>If for a problem, our first option is always ‘google it’ and copy/paste other people’s code without fully understanding the problem and the copied solution, then we are defeating ourselves.</p>
<p>So my suggestion is always have pen and paper ready and not immediately type code when faced with an algorithm challenge. Simulate the problem for simple inputs then come up with the code after you determine the steps (like I outlined them above).</p>
<p><strong>Follow me</strong> on <a target="_blank" href="https://twitter.com/coachryanv"><strong>Twitter</strong></a> | <a target="_blank" href="https://github.com/rvvergara"><strong>Github</strong></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to calculate a Binary Tree’s height using array iteration in Ruby ]]>
                </title>
                <description>
                    <![CDATA[ Data structures and algorithms are the heart and soul of computer science and software. One cannot learn programming without understanding how data is organized in code and how to manipulate it. One such data structure is a binary tree: _Photo by [U... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-calculate-a-binary-trees-height-using-array-iteration-in-ruby-63551c6c65fe/</link>
                <guid isPermaLink="false">66bb524974045df86842bf5d</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ry Vee ]]>
                </dc:creator>
                <pubDate>Wed, 19 Dec 2018 16:58:45 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca73c740569d1a4ca75d1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Data structures and algorithms are the heart and soul of computer science and software. One cannot learn programming without understanding how data is organized in code and how to manipulate it.</p>
<p>One such data structure is a binary tree:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*HItcyUcWWnuqDzKgNCoprw.jpeg" alt="Image" width="800" height="1200" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/photos/EwKXn5CapA4?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="_blank" title=""&gt;Jeremy Bishop on &lt;a href="https://unsplash.com/search/photos/tree?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="<em>blank" title=")</em></p>
<p>Oh no not that kind of tree, I mean this one:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*tsVyCA_zXrAh3LqTF4LHxw.png" alt="Image" width="727" height="337" loading="lazy">
<em>.Figure 1: Simple binary tree</em></p>
<p>In simple terms, a tree is network of ‘nodes’. A node is an object whose properties include the data itself and pointers to its ‘children’. For a binary tree, the maximum number of children each node can have is 2. A binary tree will have a root node and at most two children. Each child is just a pointer to another tree object or it can be nil. Using a hash, this can be visualized as:</p>
<pre><code class="lang-rb">tree = {
 <span class="hljs-symbol">:data</span>        =&gt; <span class="hljs-number">1</span>,
 <span class="hljs-symbol">:left_child</span>  =&gt; [another_tree] <span class="hljs-params">||</span> <span class="hljs-literal">nil</span>,
 <span class="hljs-symbol">:right_child</span> =&gt; [another_tree_again] <span class="hljs-params">||</span> <span class="hljs-literal">nil</span>
}
</code></pre>
<p>Before we go into height computations let us first find some uses for binary trees.</p>
<p>If you observe the directories or file structure in your computer, it follows a (albeit the more general) tree structure. Each folder can contain files (the data) and a number of other directories (which are not necessarily data in themselves but rather just addresses of such data contained within those sub directories). There are other use cases for binary trees that discussed better by other articles:</p>
<p><a target="_blank" href="https://www.quora.com/What-are-some-practical-applications-of-binary-search-trees"><strong>In Quora</strong></a></p>
<p><a target="_blank" href="https://stackoverflow.com/questions/2130416/what-are-the-applications-of-binary-trees"><strong>Stack Overflow</strong></a></p>
<p>Binary trees are a vast subject and there are so many things that I can write about them (such as the different ways to search through them — a future article perhaps?). However, here I will be very specific — computing the height of a binary tree.</p>
<p>The first thing to understand in relation to this, is that we can represent a binary tree using an array. But even though that’s possible, there are a number of ways to lay down each node and associate them (as an element in an array) to their respective left and right children.</p>
<p>For simplicity we’ll use the “breadth-first” method of flattening the tree. In ‘breadth-first’ we place the data contained in each node starting from the root. Then we go to the next lower level, laying down each node’s data from left to right. We go through all the levels until the lowest one.</p>
<p>If a sub tree has no left or right child then such child can be represented as 0, as long as the sub tree isn’t in the lowest level in the binary tree.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*G7zWkk-nosVTUQxqJLwYCw.jpeg" alt="Image" width="771" height="411" loading="lazy">
<em>Figure 2: Modified binary tree from Figure 1.</em></p>
<pre><code class="lang-rb">tree = [<span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">6</span>, <span class="hljs-number">0</span>, <span class="hljs-number">9</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">11</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">4</span>, <span class="hljs-number">0</span>] (T<span class="hljs-number">0</span>)* array representation of Figure2
</code></pre>
<p>Numerically, we can compute the positions of the left and right children of each node:</p>
<pre><code class="lang-rb">left child of tree[i] is at index <span class="hljs-number">2</span>*i + <span class="hljs-number">1</span> (T1)right child of tree[i] is at index <span class="hljs-number">2</span>*i + <span class="hljs-number">2</span> (T2)
</code></pre>
<p>As we can see from figure 2 we can tell how tall a tree is — that is we just need to count how many nodes there are from the root down to the lowest element (including the root and the lowest element) along the longest branch. But when it’s already in array form, how do we know how tall it is?</p>
<p>First we must have a general formula for the height of any tree:</p>
<pre><code class="lang-rb">height = <span class="hljs-number">1</span> + max of(left_child_height, right_child_height) (T3)
</code></pre>
<p>For multilevel trees then we can conclude that in order to compute the height of any sub-tree (and the tree itself) we first must compute the heights of the left and right children and then find the higher between the two. In computing the heights of these two children we need to compute the heights of their respective children and so on.</p>
<p>Having this we can now begin to outline an algorithm for computing the height of multilevel binary trees. There are two methods we can take, one is using iterations or loops, and the other, because of the repetitive nature of the steps (previous paragraph), is using recursion. I will follow up this article with a discussion on how to use recursion to do this. However, that would be too easy. So let’s learn the hard way first: we’ll do this using iteration.</p>
<h4 id="heading-iterative-method">Iterative Method</h4>
<p>We will use the tree array <code>T0</code> above to illustrate this process</p>
<p><strong>Step 0:</strong> Declare a heights array which will store the heights of each sub tree.</p>
<pre><code class="lang-rb">heights = [] (S<span class="hljs-number">0</span>.<span class="hljs-number">1</span>)
</code></pre>
<p><strong>Step 1:</strong> Iterate through the array — since we need to compute the heights of the descendants first, we iterate from the last element. And instead of using <code>each</code> method directly in the tree array we will use it for the indices of each element.</p>
<pre><code class="lang-rb">(tree.length - <span class="hljs-number">1</span>).downto(<span class="hljs-number">0</span>) <span class="hljs-keyword">do</span> <span class="hljs-params">|i|</span> (S1.<span class="hljs-number">1</span>)
</code></pre>
<p><strong>Step 2:</strong> For each element, find initial height — if the element is zero (meaning it’s actually a nil node) then initial height is 0, else it is 1.</p>
<pre><code class="lang-rb">initial_height = tree[i] == <span class="hljs-number">0</span> ? <span class="hljs-number">0</span> : <span class="hljs-number">1</span> (S2.<span class="hljs-number">1</span>)
</code></pre>
<p><strong>Step 3:</strong> Find height of left child — inside <code>heights</code> array, if the element has a left child then the height of this child is equal to:</p>
<pre><code class="lang-rb">left_child_height = heights[left_child_index] (S3.<span class="hljs-number">1</span>)
</code></pre>
<p>In the above, the <code>left_child_index</code> can be computed as follows:</p>
<pre><code class="lang-rb">left_child_index = heights.length - i - <span class="hljs-number">1</span> (S3.<span class="hljs-number">2</span>)
</code></pre>
<p>I came up with <code>S3.2</code> through a little trial and error. In the simulation that will follow these series of steps I will make mention of it.</p>
<p>To summarize though, I initially intended to <code>unshift</code> each descendant’s heights into <code>heights</code> so that the heights of each element would have the same indices as the element itself has on <code>trees</code>. But as I’ll later note, using unshift for this will be taxing resource wise for large array inputs.</p>
<p>So then I decided to use <code>push</code>. Each height will then be ordered in reverse compared to their corresponding elements’ order in <code>tree</code>. So that the height, let’s say of <code>tree[0]</code> will ultimately be located in <code>heights[-1]</code>.</p>
<p>If the element in question has no left child then <code>left_child_index</code> should be <code>nil</code>. To ensure that we catch this scenario:</p>
<pre><code class="lang-rb">left_child_index = <span class="hljs-literal">nil</span> <span class="hljs-keyword">if</span> tree[<span class="hljs-number">2</span>*i + <span class="hljs-number">1</span>].<span class="hljs-literal">nil</span>? (S3.<span class="hljs-number">3</span>)
</code></pre>
<p>Putting <code>S3.2</code> and <code>S3.3</code> together using a ternary:</p>
<pre><code class="lang-rb">left_child_index = tree[<span class="hljs-number">2</span>*i + <span class="hljs-number">1</span>].<span class="hljs-literal">nil</span>? ? <span class="hljs-literal">nil</span> : heights.length - i -<span class="hljs-number">1</span> (S3.<span class="hljs-number">4</span>)
</code></pre>
<p>Therefore, the height of the left child will have to be 0 if left child is <code>nil</code>. The full formula for <code>left_child_height</code> then is:</p>
<pre><code class="lang-rb">left_child_height = left_child_index.<span class="hljs-literal">nil</span>? ? <span class="hljs-number">0</span> : heights[left_child_index] (S3.<span class="hljs-number">5</span>)
</code></pre>
<p><strong>Step 4:</strong> Find height of right child — finding the height of the right child of a sub tree follows the same logic as Step 3. Since we are filling up <code>heights</code> array from left to right (using <code>push</code>) and we are iterating <code>tree</code> from right to left, the height of the right child of any sub tree will always be pushed first to <code>heights</code>. Therefore, the left child of any element will be at position <code>left_child_index -1</code> inside <code>heights</code> (if right child is not <code>nil</code> in <code>tree</code>). Taking these into consideration and following the logic of Step 3:</p>
<pre><code>right_child_index = tree[<span class="hljs-number">2</span>*i + <span class="hljs-number">2</span>].nil? nil : left_child_index - <span class="hljs-number">1</span> (S4<span class="hljs-number">.1</span>)
</code></pre><pre><code class="lang-rb">right_child_height = right_child_index.<span class="hljs-literal">nil</span>? ? <span class="hljs-number">0</span> : heights[right_child_index] (S4.<span class="hljs-number">2</span>)
</code></pre>
<p><strong>Step 5:</strong> Find element’s total height — After finding the heights of the left and right children of the element in question (at <code>i</code> index in L<code>tree</code>), we can now find that element’s total height:</p>
<pre><code class="lang-rb">total_height = initial_height + [left_child_height, right_child_height].max (S5.<span class="hljs-number">1</span>)
</code></pre>
<p>Numerically speaking, if the element is 0 and it happens to have any child(ren) inside tree then such child(ren) will also be 0. Hence, its <code>total_height</code> will also be 0. Such is the case with element at <code>i = 5</code> in <code>T0</code> above:</p>
<pre><code class="lang-rb">                                         left  right
                                         child child
tree = [<span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">6</span>, <span class="hljs-number">0</span>,  <span class="hljs-number">9</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">11</span>, <span class="hljs-number">0</span>,   <span class="hljs-number">0</span>,   <span class="hljs-number">4</span>, <span class="hljs-number">0</span>] 
                      i=<span class="hljs-number">5</span>                i=<span class="hljs-number">11</span> i=<span class="hljs-number">12</span>
                  element <span class="hljs-keyword">in</span> question
(T<span class="hljs-number">0</span> here repeated)
total_height = <span class="hljs-number">0</span> + [<span class="hljs-number">0</span>,<span class="hljs-number">0</span>].max = <span class="hljs-number">0</span> (S5.<span class="hljs-number">2</span>)
</code></pre>
<p>But for the element at <code>i = 4</code>, the height is:</p>
<pre><code class="lang-rb">                                    left   right
                                    child  child
tree = [<span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">6</span>, <span class="hljs-number">0</span>,  <span class="hljs-number">9</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>,   <span class="hljs-number">5</span>,    <span class="hljs-number">11</span>,     <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">4</span>, <span class="hljs-number">0</span>] 
                   i=<span class="hljs-number">4</span>               i=<span class="hljs-number">9</span>  i=<span class="hljs-number">10</span>
                  element 
                 <span class="hljs-keyword">in</span> question
total_height = <span class="hljs-number">1</span> + [<span class="hljs-number">1</span>,<span class="hljs-number">1</span>].max = <span class="hljs-number">2</span> (S5.<span class="hljs-number">3</span>)
</code></pre>
<p>In <code>S5.3</code> and <code>S5.4</code> above we just used visual inspection to compute the heights of the right and left children of the element in question. But this illustrates how our algorithm works. Now after computing for the <code>total_height</code> we simply:</p>
<p><strong>Step 6:</strong> Push <code>total_height</code> into <code>heights</code> — As I noted before, using the push method is more efficient, especially for large arrays.</p>
<pre><code class="lang-rb">heights.push(total_height) (S6.<span class="hljs-number">1</span>)
</code></pre>
<p>Once we have iterated through all elements in the <code>tree</code> array, we will have an array <code>heights</code> composed of the heights of each sub tree in the binary tree. It should look like this:</p>
<pre><code class="lang-rb">heights(after full iteration) = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>] (S6.<span class="hljs-number">2</span>)
</code></pre>
<p><strong>Step 7:</strong> Return height of the binary tree — If our goal is just find out the height of the mother tree (meaning from the root down to the lowest-rightmost node) then we simply:</p>
<pre><code class="lang-rb"><span class="hljs-keyword">return</span> heights[-<span class="hljs-number">1</span>] (S7.<span class="hljs-number">1</span>)
*Note <span class="hljs-keyword">if</span> this is the last line <span class="hljs-keyword">in</span> the method <span class="hljs-keyword">then</span> the <span class="hljs-string">'return'</span> keyword is redundant (<span class="hljs-keyword">in</span> Ruby at least)
</code></pre>
<p>However, a lot of times we may be interested to compute for the heights of any of the sub trees. In that case we simply return the <code>heights</code> array itself and then anyone using the program can simply include any index to find the height of a specific branch in the tree.</p>
<p>The full method below:</p>
<pre><code class="lang-rb"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_tree_height</span><span class="hljs-params">(tree_array)</span></span>
  <span class="hljs-comment">#0 Declare a heights array which will store the heights of each sub tree</span>
  heights = []
  <span class="hljs-comment">#1 Iterate through the tree_array starting from last element down to first</span>
  (tree_array.length - <span class="hljs-number">1</span>).downto(<span class="hljs-number">0</span>) <span class="hljs-keyword">do</span> <span class="hljs-params">|i|</span>

  <span class="hljs-comment">#2 For each element, find initial height</span>
  initial_height = tree_array[i] == <span class="hljs-number">0</span> ? <span class="hljs-number">0</span> : <span class="hljs-number">1</span>

  <span class="hljs-comment"># 3 Find height of left child</span>
  left_child_index = tree_array[<span class="hljs-number">2</span>*i + <span class="hljs-number">1</span>].<span class="hljs-literal">nil</span>? ? <span class="hljs-literal">nil</span> : heights.length - i - <span class="hljs-number">1</span> <span class="hljs-comment">#index of left child's height in heights</span>
  left_child_height = left_child_index.<span class="hljs-literal">nil</span>? ? <span class="hljs-number">0</span> : heights[left_child_index] 

  <span class="hljs-comment"># 4 Find height of right child</span>
  right_child_index = tree_array[<span class="hljs-number">2</span>*i + <span class="hljs-number">2</span>].<span class="hljs-literal">nil</span>? ? <span class="hljs-literal">nil</span> : left_child_index - <span class="hljs-number">1</span> <span class="hljs-comment">#index of right child's height in heights</span>
  right_child_height = right_child_index.<span class="hljs-literal">nil</span>? ? <span class="hljs-number">0</span> : heights[right_child_index]

  <span class="hljs-comment"># 5 Find element's total height</span>
  total_height = initial_height + [left_child_height,right_child_height].max

  <span class="hljs-comment"># 6 Push total height to heights array</span>
  heights.push(total_height)

 <span class="hljs-keyword">end</span>
 puts heights[-<span class="hljs-number">1</span>]
<span class="hljs-keyword">end</span>
</code></pre>
<p>Let’s test this algorithm out.</p>
<p>Let us suppose we run <code>binary_tree_height(tree).</code> Computing for the heights of <code>tree[14]</code> down to <code>tree[7]</code> is pretty straightforward (they will either be 0 or 1 since they are all at the lowest level of <code>tree</code>) so we won’t simulate them anymore here. We will assume we are already in that part of the iteration when <code>i</code> will be equal to 6. Therefore, at this juncture:</p>
<pre><code class="lang-rb">i = <span class="hljs-number">6</span> (F1)
tree[<span class="hljs-number">6</span>] = <span class="hljs-number">9</span> (F2)
heights = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>] (heights.length at this point is <span class="hljs-number">8</span>) (F3)
</code></pre>
<p>Now, we can see that <code>tree[6]</code> is equal to 9 (and not 0). Therefore:</p>
<pre><code>initial_height = <span class="hljs-number">1</span> (F4)
</code></pre><p>As promised, here is how I came up with the formula for the indices of the left and right children.</p>
<p>So I began with a <code>heights</code> array already filled with the heights of the lowest elements as shown in <code>F3</code>. Since I’m now working with <code>tree[6]</code> (which is 9) then its left and right children are <code>tree[13]</code> and <code>tree[14]</code>; whose corresponding heights are in <code>heights[1]</code> and <code>heights[0]</code>, respectively. If that’s not clear enough, we know we push starting from <code>tree[14]</code> — this will become <code>heights[0]</code>. We then compute for and push the height of <code>tree[13]</code> — this will be <code>heights[1]</code>. Relating the indices:</p>
<pre><code class="lang-rb">index of left child <span class="hljs-keyword">in</span> trees = <span class="hljs-number">13</span>
index of left child<span class="hljs-string">'s height in heights = LEFT_INDEX =1
index of right child in trees = 14
index of right child'</span>s height <span class="hljs-keyword">in</span> heights = RIGHT_INDEX = <span class="hljs-number">0</span>
current index of element <span class="hljs-keyword">in</span> question = MOTHER_INDEX = <span class="hljs-number">6</span>
current length of heights array = LENGTH = <span class="hljs-number">8</span>
LEFT_INDEX = <span class="hljs-number">1</span> = <span class="hljs-number">8</span> - <span class="hljs-number">6</span> - <span class="hljs-number">1</span> = LENGTH - MOTHER_INDEX - <span class="hljs-number">1</span>
RIGHT_INDEX = <span class="hljs-number">0</span> = <span class="hljs-number">8</span> - <span class="hljs-number">6</span> - <span class="hljs-number">2</span> = LENGTH - MOTHER_INDEX - <span class="hljs-number">2</span> 
(<span class="hljs-keyword">or</span> simply LEFT_INDEX -<span class="hljs-number">1</span> ) (F5)
</code></pre>
<p>We can now apply this logic to all elements, so then in code we compute for the height of <code>tree[6]</code> as follows:</p>
<pre><code class="lang-rb">Computing <span class="hljs-keyword">for</span> tree[<span class="hljs-number">6</span>]<span class="hljs-string">'s left child'</span>s <span class="hljs-symbol">height:</span>
from code at S3.<span class="hljs-number">4</span>:
left_child_index = tree[<span class="hljs-number">2</span>*i + <span class="hljs-number">1</span>].<span class="hljs-literal">nil</span>? ? <span class="hljs-literal">nil</span> : heights.length - i - <span class="hljs-number">1</span>
Since tree[<span class="hljs-number">2</span>*<span class="hljs-number">6</span> + <span class="hljs-number">1</span>] = tree[<span class="hljs-number">13</span>] = <span class="hljs-number">4</span> is <span class="hljs-keyword">not</span> <span class="hljs-literal">nil</span> <span class="hljs-symbol">then:</span>
left_child_index = <span class="hljs-number">8</span> - <span class="hljs-number">6</span> - <span class="hljs-number">1</span> = <span class="hljs-number">1</span>
from code at S3.<span class="hljs-number">5</span>:
left_child_height = left_child_index.<span class="hljs-literal">nil</span>? ? <span class="hljs-number">0</span> : heights[left_child_index]
So <span class="hljs-symbol">then:</span>
left_child_height = heights[<span class="hljs-number">1</span>] = <span class="hljs-number">1</span>
</code></pre>
<p>Following the same for <code>tree[6]</code>’s right child’s height:</p>
<pre><code class="lang-rb">from code at S4.<span class="hljs-number">1</span>:
right_child_index = tree[<span class="hljs-number">2</span>*i + <span class="hljs-number">2</span>].<span class="hljs-literal">nil</span>? <span class="hljs-literal">nil</span> : left_child_index - <span class="hljs-number">1</span> 
Since tree[<span class="hljs-number">2</span>*<span class="hljs-number">6</span> + <span class="hljs-number">2</span>] = tree[<span class="hljs-number">14</span>] = <span class="hljs-number">4</span> <span class="hljs-keyword">and</span> is <span class="hljs-keyword">not</span> <span class="hljs-symbol">nil:</span>
right_child_index = left_child_index -<span class="hljs-number">1</span> = <span class="hljs-number">1</span> -<span class="hljs-number">1</span> = <span class="hljs-number">0</span> -&gt; !<span class="hljs-literal">nil</span>?
<span class="hljs-keyword">and</span> from code at S4.<span class="hljs-number">2</span>:
right_child_height = right_child_index.<span class="hljs-literal">nil</span>? ? <span class="hljs-number">0</span> : heights[right_child_index]
<span class="hljs-symbol">Therefore:</span> right_child_height = heights[<span class="hljs-number">0</span>] = <span class="hljs-number">0</span>
</code></pre>
<p>Now we can find the total height of <code>tree[6]</code>:</p>
<pre><code class="lang-rb">total_height (tree[<span class="hljs-number">6</span>]) = <span class="hljs-number">1</span> + [<span class="hljs-number">1</span>,<span class="hljs-number">0</span>].max = <span class="hljs-number">1</span> + <span class="hljs-number">1</span> = <span class="hljs-number">2</span>
</code></pre>
<p>We can then push this <code>total_height</code> into <code>heights</code>:</p>
<pre><code class="lang-rb">heights.push(<span class="hljs-number">2</span>), such <span class="hljs-symbol">that:</span>
</code></pre>
<pre><code class="lang-rb">heights = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
</code></pre>
<p>And the same thing goes on until we work on <code>tree[0]</code> and the final <code>heights</code> array should be:</p>
<pre><code class="lang-rb">heights = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
</code></pre>
<p>And returning <code>heights[-1]</code> (or <code>heights[heights.length -1]</code>, whichever we prefer), we determine that the height of <code>tree</code> is <strong>4</strong>. We can verify this visually in both figures 1 and 2 above.</p>
<p>It took us 7 steps to come up with the answer. With this size of <code>tree</code> array the operation took around 0.024 milliseconds to finish. It takes half the time (only 0.012 milliseconds) for the same thing to be accomplished using recursion.</p>
<p>As a preview on how to do this recursively, we can simply do something like:</p>
<pre><code class="lang-rb"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tree_height_recursive</span><span class="hljs-params">(tree_array, index = <span class="hljs-number">0</span>)</span></span>
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> tree_array[index].<span class="hljs-literal">nil</span>? <span class="hljs-keyword">or</span> tree_array[index] == <span class="hljs-number">0</span>
  left_child_height = recursive_tree_height(tree_array, <span class="hljs-number">2</span>*index + <span class="hljs-number">1</span>)
  right_child_height = recursive_tree_height(tree_array, <span class="hljs-number">2</span>*index +<span class="hljs-number">2</span>)
  total_height = <span class="hljs-number">1</span> + [left_child_height, right_child_height].max
<span class="hljs-keyword">end</span>
</code></pre>
<p>We see that recursion probably will only take us at most 4 steps to do the same task. And it saves us half of the time and less resources used.</p>
<p>One secret for learning algorithms is hard work and practice. It also helps if you work collaboratively with others. I actually did the above not alone but with my coding partner. I <a target="_blank" href="https://hackernoon.com/how-five-weeks-of-remote-pair-programming-helped-me-build-strong-habits-e0493c9ba780">previously wrote</a> about how learning this way is so much more productive and effective.</p>
<p>Here is my <a target="_blank" href="https://github.com/rvvergara/data-structures">repository</a> on the different data structures and algorithms that I’ve worked on.</p>
<p><strong>Follow me</strong> on <a target="_blank" href="https://twitter.com/coachryanv"><strong>Twitter</strong></a> | <a target="_blank" href="https://github.com/rvvergara"><strong>Github</strong></a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
