<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[dev.henryjperez.com]]></title><description><![CDATA[dev.henryjperez.com]]></description><link>https://dev.henryjperez.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 20 May 2026 06:50:29 GMT</lastBuildDate><atom:link href="https://dev.henryjperez.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[About Software Testing: Why even bother]]></title><description><![CDATA[Why Testing?
Testing is necessary to ensure that everything works as expected.
And, to be honest, we all kinda do it when we are developing. Or am I the only one who uses a bunch of console.log, print, fmt.Println or anything like that everywhere?
Fo...]]></description><link>https://dev.henryjperez.com/software-testing</link><guid isPermaLink="true">https://dev.henryjperez.com/software-testing</guid><category><![CDATA[Testing]]></category><category><![CDATA[React Native]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Software Testing]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Fri, 19 May 2023 00:36:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684455452359/b029fdcb-a9b8-45d8-a8f9-718746477f43.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-why-testing">Why Testing?</h2>
<p>Testing is necessary to ensure that everything works as expected.</p>
<p>And, to be honest, <strong>we all kinda do it when we are developing</strong>. Or am I the only one who uses a bunch of <code>console.log</code>, <code>print</code>, <code>fmt.Println</code> or anything like that everywhere?</p>
<p>For example, when we are developing an algorithm we create variables containing the inputs of the use cases that we want to make sure they work. It’s very <strong>instinctive</strong>. What <strong>testing</strong> <strong>propose</strong> is to <strong>systematize</strong> that.</p>
<p>In the process, you will write a little more code, yes, once. But then, what you’ll get in return is the <strong>reliability</strong> of your code; it will <strong>force</strong> <strong>you</strong> to <strong>write</strong> more <strong>modular</strong> <strong>code</strong> and <strong>clean</strong> <strong>architecture</strong>; you can refactor knowing that you need to make sure to pass the tests that you already created; and really put your code to the limit trying all kinds of different edge cases, all while ensuring that their processes do <strong>not</strong> disrupt development.</p>
<h2 id="heading-wait-if-it-is-that-good-then-why-everyone-is-not-doing-it">Wait… if it is that good. Then, why everyone is not doing it?</h2>
<p>True, it sounds too good to be true, right? Well, because it is. You see, although I said that we instinctively already do testing, it’s not like <strong>learning</strong> and using the <strong>tools</strong> are trivial things. As with any skill it requires time and <strong>practice</strong> to master it. Writing good tests is a skill all by itself.</p>
<p>And even when you manage to get the hang of testing, making tests takes time and effort and, most important of all, <strong>writing tests don’t assure that no bug will be introduced into the code base</strong>. I’m afraid that we don’t write tests for our tests so we can’t be 100% sure that every use case was tested.</p>
<hr />
<h2 id="heading-alright-i-get-it-now-then-why-even-bother">Alright, I get it now… then, why even bother?</h2>
<p>Sure, there’s the usual: “<em>caching bugs early</em>” and all things I already mentioned. But, from a developer's point of view, it leads to more reliable and modular code and clean architecture, which can make it more maintainable, scalable, and reusable. By systematically testing your code, you can ensure that it works as intended in a variety of use cases.</p>
<p>Also, I would say that while testing you get to know a little bit more about your components. You can <strong>experiment</strong> with different scenarios and see how far can they go; and refactor when you see that it’s not working as intended (whether the code or the tests themselves).</p>
<p>Finally, It’s not only to debug an application but also a <strong>culture</strong>, a way of approaching the development process. <strong>Testing sets the standard of the application</strong>.</p>
<h2 id="heading-alright-you-convinced-me-where-do-i-start">Alright, you convinced me. Where do I start?</h2>
<p>Well, it will depend on what <em>languages</em> and <em>frameworks</em>/<em>libraries</em> you use. But, here are some principles that I use to write tests:</p>
<h3 id="heading-logic-and-ui-separation">Logic and UI separation</h3>
<p>Sometimes it's easier to test your components in their different functionalities and then test them together <strong>than</strong> testing all at once and trying to figure out where a possible bug could be.</p>
<h3 id="heading-start-with-the-basics-and-move-to-the-complex-ones">Start with the basics and move to the complex ones</h3>
<p>Sometimes time we forget to check if the code we want to test sends a response to begin with, or even if it is even defined. So, <strong>test even the most fundamental things</strong>.</p>
<h3 id="heading-keep-it-short-and-sweet">Keep it short and sweet</h3>
<p>Try to test one thing at a time.</p>
<h3 id="heading-dont-forget-to-test-edge-cases-and-error-handling">Don't forget to test edge cases and error handling</h3>
<p><strong>It's important to test not only the expected results but also the unexpected ones</strong>. By testing edge cases and error handling, you can ensure that your code is robust and can handle unexpected scenarios.</p>
<h3 id="heading-use-mocks-and-stubs">Use mocks and stubs</h3>
<p>Mocks and stubs are tools that can help you <strong>isolate and test specific parts of your code</strong>. For example, if your code relies on an external API, you can use a mock API to simulate different responses and test how your code handles them.</p>
<h3 id="heading-every-failing-test-is-an-opportunity-to-improve">Every failing test is an opportunity to improve</h3>
<p>Yes, that’s right, the idea is to improve code quality, so, <strong>use every failed test</strong> to solve it and hence <strong>improve the code</strong> and reliability of it.</p>
<h3 id="heading-dont-test-everything">Don't test everything</h3>
<p>Testing is important, but it's not realistic to test every single line of code. Instead, <strong>focus on testing the critical parts of your code</strong> and the parts that are most likely to break.</p>
<p>By following these principles and incorporating testing into your development process, you can <strong>build</strong> more <strong>reliable</strong> and <strong>maintainable</strong> <strong>software</strong>.</p>
<h3 id="heading-find-your-own-thing">Find your own thing</h3>
<p>Even when you learn from courses, coworkers and tutorials, it’s also important to <strong>listen to your own experience</strong> and find your way to do it.</p>
<hr />
<h2 id="heading-now">Now</h2>
<p>I’ll be releasing an article on testing in <strong>react native</strong> with this example that I made only for that article. Here’s the <a target="_blank" href="https://github.com/henryjperez/rn-testing--tutorial">repository</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://snack.expo.io/@henryjperez/github.com-henryjperez-rn-testing--tutorial">https://snack.expo.io/@henryjperez/github.com-henryjperez-rn-testing--tutorial</a></div>
<p> </p>
<p>I don’t know if I’ll gonna release it after this article because I’ve been organizing my study notes and stuff. But I’ll let you know 😆 (And, yes, I did the thumbnail of this article. Pretty cool, right? 😎).</p>
<p>That’s it for me, but you can follow me on <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://www.facebook.com/henryjperezr">Facebook</a>,  <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://www.reddit.com/user/henryjperez">Reddit</a> and here in <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a>. Also, you can subscribe to my newsletter down below 👇. Well, see ya!</p>
]]></content:encoded></item><item><title><![CDATA[Object Oriented Programming using Typescript: A Complete Guide]]></title><description><![CDATA[Classes
They are the blueprint for its instances (objects that the class produce).
JavaScript has had classes since the ES5 language implementations. In there it was introduced to us the native implementations of “classes” was. Typescript extends the...]]></description><link>https://dev.henryjperez.com/oop-ts</link><guid isPermaLink="true">https://dev.henryjperez.com/oop-ts</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Computer Science]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Mon, 27 Mar 2023 21:14:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679951507172/4ac07e18-61bf-453d-82c4-a8d530c03687.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-classes">Classes</h1>
<p>They are the blueprint for its instances (objects that the class produce).</p>
<p>JavaScript has had classes since the ES5 language implementations. In there it was introduced to us the native implementations of “classes” was. Typescript extends the functionalities of that feature to make it look more like more common programming languages like Java for example.</p>
<p>Before we continue, if you're in a hurry, here's the GitHub <a target="_blank" href="https://github.com/henryjperez/ts_oop--tutorial">repository</a> with all the code of this guide, just in case.</p>
<p>Now, let’s see what functionalities are and how to use them.</p>
<h1 id="heading-basic-declaration">Basic declaration</h1>
<p>There is no mystery here. You use the keyword <code>class</code>, next to the name of the class (starting it with Uppercase by convention) and open brackets.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* ------------- Basic declaration ------------ */</span>
<span class="hljs-keyword">class</span> A {
    a1: <span class="hljs-built_in">string</span>;
    a2: <span class="hljs-built_in">number</span>;
    a3: <span class="hljs-built_in">boolean</span>;

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">a1: <span class="hljs-built_in">string</span>, a2: <span class="hljs-built_in">number</span>, a3: <span class="hljs-built_in">boolean</span></span>) {
        <span class="hljs-built_in">this</span>.a1 = a1;
        <span class="hljs-built_in">this</span>.a2 = a2;
        <span class="hljs-built_in">this</span>.a3 = a3;
    }
}
</code></pre>
<p>In that snippet of code, you have <code>a1</code> , <code>a2</code> and <code>a3</code> declared at the top of the class, that’s because Typescript will use that to tell <code>this</code> that those are part of its constructor and will not throw an error nor syntax warnings on the editor.</p>
<p>I know that’s a little too much boilerplate for just a simple class, but don’t worry, keep reading and I’ll show you a shorter way of doing that.</p>
<p>Then you can instantiate it like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> aa = <span class="hljs-keyword">new</span> A(<span class="hljs-string">"New Class"</span>, <span class="hljs-number">1</span>, <span class="hljs-literal">true</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Basic declaration:"</span>, aa);
</code></pre>
<h2 id="heading-with-methods">With methods</h2>
<p>Went you wanna add methods, you don’t need to declare it at the top of the class nor do you have to use the keyword <code>function</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* --------------- With methods --------------- */</span>
<span class="hljs-keyword">class</span> B {
    b1: <span class="hljs-built_in">string</span>;
    b2: <span class="hljs-built_in">number</span>;
    b3: <span class="hljs-built_in">boolean</span>;

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">b1: <span class="hljs-built_in">string</span>, b2: <span class="hljs-built_in">number</span>, b3: <span class="hljs-built_in">boolean</span></span>) {
        <span class="hljs-built_in">this</span>.b1 = b1;
        <span class="hljs-built_in">this</span>.b2 = b2;
        <span class="hljs-built_in">this</span>.b3 = b3;
    }

    run(time: <span class="hljs-string">"all day"</span> | <span class="hljs-string">"just the mornings"</span> | <span class="hljs-string">"anytime"</span>): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`I'm running <span class="hljs-subst">${time}</span>, so you have this: <span class="hljs-subst">${<span class="hljs-built_in">this</span>.b1}</span> times <span class="hljs-subst">${<span class="hljs-built_in">this</span>.b2}</span> and it's <span class="hljs-subst">${<span class="hljs-built_in">this</span>.b3}</span>`</span>);
    }
}
<span class="hljs-keyword">const</span> bb = <span class="hljs-keyword">new</span> B(<span class="hljs-string">"Power"</span>, <span class="hljs-number">59</span>, <span class="hljs-literal">true</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"B class:"</span>, bb);
bb.run(<span class="hljs-string">"all day"</span>);
</code></pre>
<h1 id="heading-encapsulation">Encapsulation</h1>
<p>Sometimes you’ll want to limit the kind of information that the <strong>instances</strong> share with the rest of the code, in those cases, you’ll use <strong>encapsulation</strong>.</p>
<p>The default way that classes instantiate their properties is <code>public</code>. Anyone can see them, anyone can change them, and anyone can manipulate that data.</p>
<p>Then, you have <code>private</code> properties which can only be manipulated by the class itself. By convention, you start the name of a <strong>private</strong> with an underscore <code>_</code> and they are strongly related to <strong>getters</strong> and <strong>setters</strong>, which I’ll explain in a moment</p>
<p>Some properties can only be read and cannot be modified, not even by the class itself, those are <code>readonly</code> .</p>
<p>And finally, we have <code>protected</code> which is very similar to <strong>private</strong> but with the difference that <strong>protected</strong> properties can also be modified by <strong>inherited</strong> classes (I’ll talk a little bit about that later).</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* --------------- Encapsulation -------------- */</span>
<span class="hljs-keyword">class</span> C {
    c0: <span class="hljs-built_in">any</span> <span class="hljs-comment">// public by default</span>
    <span class="hljs-keyword">public</span> c1: <span class="hljs-literal">null</span> | <span class="hljs-built_in">number</span>;
    <span class="hljs-keyword">private</span> _c2: <span class="hljs-built_in">boolean</span> | <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">readonly</span> c3: <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">protected</span> _c4: <span class="hljs-built_in">string</span>;

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">{ c1, c2, c3, c4 }: { c1: <span class="hljs-literal">null</span> | <span class="hljs-built_in">number</span>, c2: <span class="hljs-built_in">boolean</span>, c3: <span class="hljs-built_in">string</span>, c4: <span class="hljs-built_in">string</span>, }</span>) {
        <span class="hljs-built_in">this</span>.c0 = <span class="hljs-string">"Whatever"</span>;
        <span class="hljs-built_in">this</span>.c1 = c1;
        <span class="hljs-built_in">this</span>._c2 = c2;
        <span class="hljs-built_in">this</span>.c3 = c3;
        <span class="hljs-built_in">this</span>._c4 = c4;
    }

    get c2() {
        <span class="hljs-keyword">return</span> <span class="hljs-string">`Mr. C2 says that  it's value is: <span class="hljs-subst">${<span class="hljs-built_in">this</span>._c2}</span>. Now you can go, please`</span>;
    }
    set c2(newValue: <span class="hljs-built_in">boolean</span> | <span class="hljs-built_in">string</span>) {
        <span class="hljs-comment">// this.c3 = "Nope, still not changing"; // it will change the value, but the idea is to listen to typescript</span>
        <span class="hljs-built_in">this</span>._c2 = newValue;
    }

    set c4(newValue: <span class="hljs-built_in">string</span>) {
        <span class="hljs-built_in">this</span>._c4 = newValue;
    }

}
<span class="hljs-keyword">const</span> cc = <span class="hljs-keyword">new</span> C({ c1: <span class="hljs-literal">null</span>, c2: <span class="hljs-literal">false</span>, c3: <span class="hljs-string">"You can only see me, not modify me"</span>, c4: <span class="hljs-string">"Only the class can make me change and it's children"</span> });
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Encapsulation with class:"</span>, cc);

cc.c0 = <span class="hljs-string">"I'm public, whatever"</span>;
cc.c1 = <span class="hljs-number">975</span>;
<span class="hljs-comment">// cc._c2 = true; // it will change the value, but the idea is to listen to typescript</span>
cc.c2 = <span class="hljs-string">"VIP"</span>;
<span class="hljs-comment">// cc.c3 = "Time to change... hahaha, not really"; // it will change the value, but the idea is to listen to typescript</span>
<span class="hljs-comment">// cc._c4 = "I told you, only the class can change me, not you"; // it will change the value, but the idea is to listen to typescript</span>
cc.c4 = <span class="hljs-string">"Oh, well, if you say it please.... okey, let's go"</span>;

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After changes:"</span>, cc)
<span class="hljs-built_in">console</span>.log(cc.c2)
<span class="hljs-built_in">console</span>.log(cc.c3)
<span class="hljs-comment">// console.log(cc._c4) // it will display the value, but the idea is to listen to typescript</span>
</code></pre>
<p>In the code above you’ll see a lot of comments, that’s because since this is an implementation of Typescript, many of these keywords don’t exist natively on Javascript, so the changes that you make in those scenarios are, even if they are invalid to Typescript, it will still run went it transpile to Javascript.</p>
<h2 id="heading-getters-and-setters">Getters and Setters</h2>
<p>Although this is not specific to Typescript but also Javascript. <strong>Getters</strong> and <strong>Setters</strong> are used to <code>set</code> or <code>get</code> a value of a property.</p>
<p>They are useful when you are using <code>private</code> or <code>protected</code> properties but you still want a way for the class to expose those values without directly referencing them.</p>
<p>Using the example above, they would like something like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> C {
    <span class="hljs-keyword">private</span> _c2: <span class="hljs-built_in">boolean</span> | <span class="hljs-built_in">string</span>;

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">{ c2, }: { c2: <span class="hljs-built_in">boolean</span> }</span>) {
        <span class="hljs-built_in">this</span>._c2 = c2;
    }

    get c2() {
        <span class="hljs-keyword">return</span> <span class="hljs-string">`Mr. C2 says that  it's value is: <span class="hljs-subst">${<span class="hljs-built_in">this</span>._c2}</span>. Now you can go, please`</span>;
    }
    set c2(newValue: <span class="hljs-built_in">boolean</span> | <span class="hljs-built_in">string</span>) {
        <span class="hljs-comment">// this.c3 = "Nope, still not changing"; // it will change the value, but the idea is to listen to typescript</span>
        <span class="hljs-built_in">this</span>._c2 = newValue;
    }

}
</code></pre>
<h3 id="heading-get">Get</h3>
<p><code>get</code> will <strong>return</strong> the value of the <strong>property.</strong></p>
<pre><code class="lang-typescript"><span class="hljs-built_in">console</span>.log(cc.c2)
</code></pre>
<h3 id="heading-set">Set</h3>
<p><code>set</code> can overwrite the value of the <code>private</code> <strong>property.</strong></p>
<pre><code class="lang-typescript">cc.c2 = <span class="hljs-string">"VIP"</span>;
</code></pre>
<h1 id="heading-short-constructor">Short constructor</h1>
<p>To avoid all the boilerplate to declare the variables with their types at the beginning of the class, you can use <strong>attributes</strong> of the constructor to short that off. The only condition is to <strong>add</strong> the <strong>access type</strong> of <strong>each</strong> variable.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* ------------- Short constructor ------------ */</span>
<span class="hljs-keyword">class</span> D {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-comment">// d0: any // you need to add the type of access: public, private, etc</span>
        <span class="hljs-keyword">public</span> d1: <span class="hljs-built_in">number</span>,
        <span class="hljs-keyword">private</span> d2: <span class="hljs-built_in">boolean</span>,
        <span class="hljs-keyword">readonly</span> d3: <span class="hljs-built_in">string</span>,
        <span class="hljs-keyword">protected</span> d4: <span class="hljs-built_in">number</span> = 888,
    </span>) { }

    d5(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Just logging"</span>);
    }
}
<span class="hljs-keyword">const</span> dd = <span class="hljs-keyword">new</span> D(<span class="hljs-number">13</span>, <span class="hljs-literal">true</span>, <span class="hljs-string">"Reading..."</span>, <span class="hljs-comment">/* 99 */</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Short constructor"</span>, dd);
</code></pre>
<h1 id="heading-inheritance">Inheritance</h1>
<p>A class can have all the methods and properties that another class has. To do so, one class <code>extends</code> the functionalities of another, this process is called <strong>inheritance</strong> because, in some sense, the class <strong>extended</strong> will become a “parent” and the other a “child” that will inherit everything that its “parents” has.</p>
<p>As a side note, a class can only inherit one class at a time.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* ---------------- Inheritance --------------- */</span>
<span class="hljs-keyword">class</span> E {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> e1: <span class="hljs-built_in">number</span>,
        <span class="hljs-keyword">private</span> e2: <span class="hljs-built_in">string</span> = "Hi, I'm VIP",
        <span class="hljs-keyword">protected</span> e3: <span class="hljs-built_in">string</span> = "Hello, I'm can be used be the inheritance",
    </span>) { }

    e4() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"%c Here, just doing some Class E stuff"</span>, <span class="hljs-string">"color: pink; background-color: black"</span>,);
    }
}
<span class="hljs-keyword">class</span> F <span class="hljs-keyword">extends</span> E {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        e1: <span class="hljs-built_in">number</span>, <span class="hljs-comment">// for the super class don't put the access type (public, private, etc)</span>
        <span class="hljs-keyword">public</span> f1: <span class="hljs-built_in">number</span>,
    </span>) {
        <span class="hljs-built_in">super</span>(e1);
    }

    f2() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Super thing 1 <span class="hljs-subst">${<span class="hljs-built_in">this</span>.e1}</span>`</span>);
        <span class="hljs-comment">// console.log(`Super thing 2 ${this.e2}`); // privates can be extended to the children</span>
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Super thing 3 <span class="hljs-subst">${<span class="hljs-built_in">this</span>.e3}</span>`</span>);

        <span class="hljs-built_in">super</span>.e4();
    }
}

<span class="hljs-keyword">const</span> ee = <span class="hljs-keyword">new</span> E(<span class="hljs-number">2000</span>);
<span class="hljs-keyword">const</span> ff = <span class="hljs-keyword">new</span> F(<span class="hljs-number">2501</span>, <span class="hljs-number">3000</span>);
<span class="hljs-built_in">console</span>.log(ee);
<span class="hljs-built_in">console</span>.log(ff);
ff.f2();
<span class="hljs-comment">// class G extends A, B, C, D, {} // it can only extend 1 class at the time</span>
</code></pre>
<h1 id="heading-static-methods">Static methods</h1>
<p>With the <code>static</code> keyword you can use properties and methods (mostly methods) without instantiating the class but with the <strong>class</strong> itself. Just keep in mind that the object instance <code>this</code> will not work as expected since there will be nothing instantiated yet.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* ------------------ Statics ----------------- */</span>
<span class="hljs-keyword">class</span> G {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> gg = "Good game, gg",
    </span>) { }

    <span class="hljs-keyword">static</span> g = <span class="hljs-string">"gg, GG, gg"</span>;
    <span class="hljs-keyword">static</span> ggGGgg() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`By the way, gg. <span class="hljs-subst">${<span class="hljs-built_in">this</span>.gg}</span>. Woops, I forgot that you need to initialize my first, unless... <span class="hljs-subst">${<span class="hljs-built_in">this</span>.g}</span>...`</span>);
    }
}
G.ggGGgg();
<span class="hljs-built_in">console</span>.log(G.g)
</code></pre>
<h1 id="heading-abstract-classes">Abstract Classes</h1>
<p>An abstract class is the class you don’t want to instantiate because they are too open in its definition and too vague to make an object out of it. Instead, what you wanna do is to define it and let other classes inherit from it. That’s the whole point of an abstract class.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* ----------------- Abstract ----------------- */</span>
<span class="hljs-comment">// when a class is too general</span>
<span class="hljs-comment">// and you don't want to allow instances of that class</span>
<span class="hljs-comment">// but you still want to inherit</span>
<span class="hljs-comment">// then you can use an abstract class</span>
<span class="hljs-keyword">interface</span> ILiving {
    name: <span class="hljs-built_in">string</span>;
    exists(): <span class="hljs-built_in">void</span>;
}
<span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> LivingThing <span class="hljs-keyword">implements</span> ILiving { <span class="hljs-comment">// ignore the "interface" and "implements" for now</span>
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> name: <span class="hljs-built_in">string</span> = "perrito",
    </span>) { }

    exists(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Existing"</span>);
    }
}

<span class="hljs-comment">// const livingThing = new LivingThing("Creature"); // Just don't, ok?</span>
<span class="hljs-keyword">class</span> Dog <span class="hljs-keyword">extends</span> LivingThing {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        name: <span class="hljs-built_in">string</span>,
        <span class="hljs-keyword">public</span> power: <span class="hljs-built_in">string</span>,
    </span>) {
        <span class="hljs-built_in">super</span>(name);
    }

    move(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Moving using 4 legs"</span>);
    }
}
<span class="hljs-keyword">const</span> dog = <span class="hljs-keyword">new</span> Dog(<span class="hljs-string">"Perrito"</span>, <span class="hljs-string">"Perfection"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Extending from abstract class"</span>, dog);
dog.exists();
dog.move();
</code></pre>
<h1 id="heading-interfaces-in-classes">Interfaces in classes</h1>
<p>Interfaces are related to objects and only exist on Typescript, not in Javascript. They declare what <strong>properties</strong> and <strong>methods</strong> the object will have and what <strong>type</strong> of data it’ll manage.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> H {
    h1: <span class="hljs-built_in">number</span>;
    h2(): <span class="hljs-built_in">number</span>;
}
</code></pre>
<p>Like classes, they can extend from each other. But, there is no such thing as <strong>polymorphism,</strong> which I’ll explain in another moment, but means that you can’t overwrite a property, for example <code>h1</code> with another interface.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* ---------------- Interfaces ---------------- */</span>
<span class="hljs-keyword">interface</span> H {
    h1: <span class="hljs-built_in">number</span>;
    h2(): <span class="hljs-built_in">number</span>;
}
<span class="hljs-keyword">interface</span> I {
    i1: <span class="hljs-built_in">string</span>;
    i2: ILiving;
}
<span class="hljs-keyword">interface</span> J <span class="hljs-keyword">extends</span> H, I {
    j1: <span class="hljs-built_in">boolean</span>;
}
</code></pre>
<p>And you use the keyword <code>implements</code> to use them in your classes.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> K <span class="hljs-keyword">implements</span> H, I, J { <span class="hljs-comment">// in this example implementing "H" and "I" are optionals since "J" already does that</span>
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> h1: <span class="hljs-built_in">number</span>,

        <span class="hljs-keyword">public</span> i1: <span class="hljs-built_in">string</span>,
        <span class="hljs-keyword">public</span> i2: ILiving,

        <span class="hljs-keyword">public</span> j1: <span class="hljs-built_in">boolean</span>,
    </span>) {}

    h2() {
        <span class="hljs-keyword">return</span> <span class="hljs-number">66</span>;
    }
}
<span class="hljs-keyword">const</span> kk = <span class="hljs-keyword">new</span> K(<span class="hljs-number">44</span>, <span class="hljs-string">"Welcome"</span>, dog, <span class="hljs-literal">true</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Interfaces and classes =&gt;"</span>, kk)
</code></pre>
<hr />
<p>Well, there you have it. A complete guide to Object Oriented Programming using Typescript. If you have anything to add to it please comment on it or reach out to me through my social media:</p>
<p><a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://medium.com/@henryjperez">Medium</a> (For more opinion-based posts), and here on <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a> and my <a target="_blank" href="https://dev.henryjperez.com/">Hashnode blog</a>. Also, follow me if you want XD</p>
<p>Remember that <a target="_blank" href="https://github.com/henryjperez/ts_oop--tutorial">here's the repository</a> with all the code.</p>
<p>Have a nice day and until next time. Bye.</p>
]]></content:encoded></item><item><title><![CDATA[GitHub Actions: How to Compile and release a React Native Android app]]></title><description><![CDATA[GitHub Actions is a tool integrated into Github to perform tasks related to the repository given an “event”.
I must give credit to this post and its Youtube video because I was of great help in this regard.
If you’re in a hurry, here’s the repo conta...]]></description><link>https://dev.henryjperez.com/gh-actions-react-native-android</link><guid isPermaLink="true">https://dev.henryjperez.com/gh-actions-react-native-android</guid><category><![CDATA[React Native]]></category><category><![CDATA[React]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Sat, 18 Mar 2023 23:56:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679183531996/3a28b5b1-7c25-4bcc-81cc-62bc83267fbe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>GitHub Actions</strong> is a tool integrated into Github to perform tasks related to the repository given an “event”.</p>
<p>I must give credit to this <a target="_blank" href="https://www.andrewhoog.com/post/how-to-build-react-native-android-app-with-github-actions/">post</a> and its <a target="_blank" href="https://www.youtube.com/watch?v=_uRbEyBa9q0">Youtube video</a> because I was of great help in this regard.</p>
<p>If you’re in a hurry, here’s the <a target="_blank" href="https://github.com/henryjperez/gh-actions_react-native-release--tutorial">repo</a> containing the whole file of this tutorial.</p>
<h1 id="heading-how-github-actions-works">How GitHub Actions works</h1>
<p>As I said it’s a tool integrated into GitHub to automate processes related to the repository. It works by declaring a <code>.yml</code> (you can find a complete view of <strong>YAML</strong> files in this <a target="_blank" href="https://dev.henryjperez.com/the-yaml-files">article</a>) in the relative of your repo: <code>/.github/workflows/</code></p>
<p>In those files will live the configurations of the tasks that will be executed when a given event occurs on the repo: push, pull requests, issues, tags, etc.</p>
<h1 id="heading-where-to-begin">Where to begin?</h1>
<p>Well, if you’re completely new to this I suggest starting to create a folder in the root of your project called <code>.github</code>. Inside there, create another folder called <code>workflows</code> (yes, this is the path that I mentioned before).</p>
<p>Then create a file with the <code>.yml</code> extension. You can call it whatever you want but I’ll call it: <code>build-android.yml</code>.</p>
<p>And finally, enable <strong>Github Actions</strong> in the <strong><em>Actions</em></strong> tab:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679182749953/562d8ac5-3a42-4140-be39-05f9fca08b3e.png" alt="Actions Tab in GitHub" class="image--center mx-auto" /></p>
<p>With that, we are ready to begin.</p>
<h2 id="heading-considerations-for-this-tutorial">Considerations for this tutorial</h2>
<p>You don’t need to be the owner of the repository to make this tutorial. If you have access to it like a contributor it’s enough.</p>
<p>I’ll gonna compile multiple .apk files for different architectures of CPUs, and if you only gonna compile one .apk then you can do it just fine.</p>
<h1 id="heading-steps">Steps</h1>
<h2 id="heading-name-the-action">Name the Action</h2>
<p>At the top of the file put whatever name you want the <strong>action</strong> to have. You can do it like this:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">Android</span> <span class="hljs-string">.apk</span>
</code></pre>
<h2 id="heading-name-of-the-runtime-optional">Name of the runtime (optional)</h2>
<p>By default, the action in the <strong>Actions</strong> tab will run with the name of the commit that triggers it, but you can change that by putting <code>run-name</code> in the file. Like this:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">Android</span> <span class="hljs-string">.apk</span>

<span class="hljs-attr">run-name:</span> <span class="hljs-string">"Building the .apk with the tag triggered by @$<span class="hljs-template-variable">{{ github.actor }}</span>"</span>
</code></pre>
<p>The workflow running will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679182842445/7a70c102-27be-4ee3-9a6c-a4ae98597ee6.png" alt class="image--center mx-auto" /></p>
<p>The <code>${{ [github.actor](http://github.actor) }}</code> is a variable that <strong>Github</strong> provides with the user that triggered the <strong>action</strong>: <a target="_blank" href="https://docs.github.com/en/actions/learn-github-actions/contexts#github-context"><strong>GitHub Object</strong></a><strong>.</strong></p>
<h2 id="heading-event-trigger">Event Trigger</h2>
<p>In this part, you can put any event that you see fit, but since this is a tutorial to create a release with the output, then it’s necessary to use <strong>git tags</strong> to trigger the <strong>action</strong>.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">Android</span> <span class="hljs-string">.apk</span>

<span class="hljs-attr">run-name:</span> <span class="hljs-string">"Building the .apk with the tag triggered by @$<span class="hljs-template-variable">{{ github.actor }}</span>"</span>

<span class="hljs-attr">permissions:</span>
  <span class="hljs-attr">contents:</span> <span class="hljs-string">write</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">tags:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"v*"</span>
</code></pre>
<p>The <code>"v*"</code> means that the tag name must start with <code>v</code>, but you can put it like this to trigger it at any <strong>tag</strong>: <code>"*"</code>.</p>
<h2 id="heading-jobs">Jobs</h2>
<p><strong>Jobs</strong> are different processes that can run in parallel (or in sequence) in <strong>GitHub Actions</strong>. For this tutorial, we’ll not gonna worry too much about it, but I’ll leave you some resources for you to deep dive into it:</p>
<p><a target="_blank" href="https://docs.github.com/en/actions/using-jobs/using-jobs-in-a-workflow">Github Actions Job Objects</a></p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=eB0nUzAI7M8">Youtube: 5 Ways to DevOps-ify your App - Github Actions Tutorial</a></p>
<p>For now, I’ll gonna call this <strong><em>job</em></strong> as <code>build</code> (but you can call it otherwise if you want) and say it to run on the <strong>latest version of Ubuntu</strong>:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
</code></pre>
<h2 id="heading-steps-object">Steps Object</h2>
<p>Before we start giving instructions on how to compile the app, first let’s declare the <code>step</code> object that will wrap the processes:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
</code></pre>
<h2 id="heading-setting-the-repository">Setting the repository</h2>
<p>Now, this is the part that we all have been waiting for: The <strong>Actions</strong> of <strong>GitHub Actions</strong>.</p>
<p>To use them you need to declare a <code>name</code> and a <code>uses</code> parameter. You’ll see the pattern with the rest of the tutorial.</p>
<p>Use the <a target="_blank" href="https://github.com/marketplace/actions/checkout">checkout action</a> to move to the root of your project:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">repository</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
</code></pre>
<h2 id="heading-installing-java">Installing Java</h2>
<p>Use the <a target="_blank" href="https://github.com/marketplace/actions/setup-java-jdk">Java action</a> with the <strong>Gradle</strong> version:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Java</span>
    <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-java@v3</span>
    <span class="hljs-attr">with:</span>
      <span class="hljs-attr">java-version:</span> <span class="hljs-string">"11"</span>
      <span class="hljs-attr">distribution:</span> <span class="hljs-string">"adopt"</span>
      <span class="hljs-attr">cache:</span> <span class="hljs-string">"gradle"</span>
</code></pre>
<h2 id="heading-validate-gradle-optional">Validate Gradle (optional)</h2>
<p>I’ll not gonna lie to you, this is something that I saw in the tutorial that I mention but I suppose that you can do it without it anyway.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Validate</span> <span class="hljs-string">Gradle</span> <span class="hljs-string">wrapper</span>
  <span class="hljs-attr">uses:</span> <span class="hljs-string">gradle/wrapper-validation-action@v1</span>
</code></pre>
<h2 id="heading-installing-nodejs">Installing Node.js</h2>
<p>Setup node with the <a target="_blank" href="https://github.com/marketplace/actions/setup-node-js-environment">GitHub Action</a>:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Node</span>  
  <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v3</span>
  <span class="hljs-attr">with:</span>
    <span class="hljs-attr">node-version:</span> <span class="hljs-string">'16'</span>
</code></pre>
<p>With this, you will set up <code>yarn</code> and <code>npm</code> if you need them. In my case, I’ll use <code>yarn</code> for the rest of the tutorial, but it will depend on your use case.</p>
<h2 id="heading-installing-dependencies-and-building-the-project">Installing dependencies and building the project</h2>
<p>As I said, I’ll use <code>yarn</code> for this but it will depend on you.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Yarn</span> <span class="hljs-string">Install</span>
  <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">install</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">application</span>
  <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">release</span>
</code></pre>
<p>The <code>release</code> script in the <code>package.json</code> file looks like this:</p>
<pre><code class="lang-json"><span class="hljs-string">"release"</span>: <span class="hljs-string">"cd android &amp;&amp; ./gradlew assembleRelease"</span>,
</code></pre>
<h2 id="heading-list-the-compiled-files-optional">List the compiled files (optional)</h2>
<p>This is just to see the name of the .apk files in case you need to see them to do something else.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">List</span> <span class="hljs-string">the</span> <span class="hljs-string">.apks</span> <span class="hljs-string">compiled</span>
  <span class="hljs-attr">run:</span> <span class="hljs-string">ls</span> <span class="hljs-string">./android/app/build/outputs/apk/release/</span> <span class="hljs-string">-hal</span>
</code></pre>
<h2 id="heading-changing-the-name-of-the-main-apk-file-optional">Changing the name of the main .apk file (optional)</h2>
<p>This is not necessary, but I’ll add it anyways because it’s better to download the .apk, when needed, with the version that has a semantic name.</p>
<p>In this case, I’ll rename the <code>app-universal-release.apk</code>, but in your case, it might look different. So be aware of that.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Rename</span> <span class="hljs-string">the</span> <span class="hljs-string">.apk</span> <span class="hljs-string">to</span> <span class="hljs-string">the</span> <span class="hljs-string">tag</span> <span class="hljs-string">version</span>
  <span class="hljs-attr">run:</span> <span class="hljs-string">mv</span> <span class="hljs-string">./android/app/build/outputs/apk/release/app-universal-release.apk</span> <span class="hljs-string">./android/app/build/outputs/apk/release/app-name_${{</span> <span class="hljs-string">github.ref_name</span> <span class="hljs-string">}}.apk</span>
</code></pre>
<p>The <code>{{GitHub.ref_name }}</code> has the version name of the <strong><em>git tag</em></strong>.</p>
<h2 id="heading-creating-release-and-uploading-files">Creating Release and Uploading Files</h2>
<p>Finally, the <a target="_blank" href="https://github.com/marketplace/actions/gh-release">GH Release Action</a> to create the release and push the .apk compiled.</p>
<p>As I said, I’ll upload many files because I’m compiling a .apk for each CPU architecture, in your case it could be only one, but don’t worry I’ll show you how to do it as well.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Create</span> <span class="hljs-string">Release</span> <span class="hljs-string">and</span> <span class="hljs-string">Uploading</span> <span class="hljs-string">Files</span>
  <span class="hljs-attr">uses:</span> <span class="hljs-string">softprops/action-gh-release@v1</span>
  <span class="hljs-attr">if:</span> <span class="hljs-string">startsWith(github.ref,</span> <span class="hljs-string">'refs/tags/'</span><span class="hljs-string">)</span>
  <span class="hljs-attr">with:</span>
    <span class="hljs-attr">files:</span> <span class="hljs-string">|
      android/app/build/outputs/apk/release/app-arm64-v8a-release.apk
      android/app/build/outputs/apk/release/app-armeabi-v7a-release.apk
      android/app/build/outputs/apk/release/app-x86_64-release.apk
      android/app/build/outputs/apk/release/app-x86-release.apk
      android/app/build/outputs/apk/release/app-name_${{ github.ref_name }}.apk</span>
</code></pre>
<p>In the <code>files</code> part, in case you want to upload only one file, do it like this:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">files:</span> <span class="hljs-string">android/app/build/outputs/apk/release/app-name_${{</span> <span class="hljs-string">github.ref_name</span> <span class="hljs-string">}}.apk</span>
</code></pre>
<p>Or</p>
<pre><code class="lang-yaml"><span class="hljs-attr">files:</span> <span class="hljs-string">android/app/build/outputs/apk/release/app-universal-release.apk</span>
</code></pre>
<h1 id="heading-results">Results</h1>
<p>Well, the result would look something like this:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">Android</span> <span class="hljs-string">.apk</span>

<span class="hljs-attr">run-name:</span> <span class="hljs-string">"Building the .apk with the tag triggered by @$<span class="hljs-template-variable">{{ github.actor }}</span>"</span>

<span class="hljs-attr">permissions:</span>
  <span class="hljs-attr">contents:</span> <span class="hljs-string">write</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">tags:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"v*"</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-comment"># runs-on: ubuntu-22.04 # this is the Ubuntu version that this was created on</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">repository</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Java</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-java@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">java-version:</span> <span class="hljs-string">"11"</span>
          <span class="hljs-attr">distribution:</span> <span class="hljs-string">"adopt"</span>
          <span class="hljs-attr">cache:</span> <span class="hljs-string">"gradle"</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Validate</span> <span class="hljs-string">Gradle</span> <span class="hljs-string">wrapper</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">gradle/wrapper-validation-action@v1</span>

      <span class="hljs-comment"># Node, Yarn and NPM</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Node</span>  
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">node-version:</span> <span class="hljs-string">'16'</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Yarn</span> <span class="hljs-string">Install</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">install</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">application</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">release</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">List</span> <span class="hljs-string">the</span> <span class="hljs-string">.apks</span> <span class="hljs-string">compiled</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">ls</span> <span class="hljs-string">./android/app/build/outputs/apk/release/</span> <span class="hljs-string">-hal</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Rename</span> <span class="hljs-string">the</span> <span class="hljs-string">.apk</span> <span class="hljs-string">to</span> <span class="hljs-string">the</span> <span class="hljs-string">tag</span> <span class="hljs-string">version</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">mv</span> <span class="hljs-string">./android/app/build/outputs/apk/release/app-universal-release.apk</span> <span class="hljs-string">./android/app/build/outputs/apk/release/app_name_${{</span> <span class="hljs-string">github.ref_name</span> <span class="hljs-string">}}.apk</span>


      <span class="hljs-comment"># Creating and Uploading the releases</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Create</span> <span class="hljs-string">Release</span> <span class="hljs-string">and</span> <span class="hljs-string">Uploading</span> <span class="hljs-string">Files</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">softprops/action-gh-release@v1</span>
        <span class="hljs-attr">if:</span> <span class="hljs-string">startsWith(github.ref,</span> <span class="hljs-string">'refs/tags/'</span><span class="hljs-string">)</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">files:</span> <span class="hljs-string">|
            android/app/build/outputs/apk/release/app-arm64-v8a-release.apk
            android/app/build/outputs/apk/release/app-armeabi-v7a-release.apk
            android/app/build/outputs/apk/release/app-x86_64-release.apk
            android/app/build/outputs/apk/release/app-x86-release.apk
            android/app/build/outputs/apk/release/app_name_${{ github.ref_name }}.apk</span>
</code></pre>
<p>Remember that everything we did is in the <a target="_blank" href="https://github.com/henryjperez/gh-actions_react-native-release--tutorial">repository of this tutorial</a>.</p>
<p>After you commit the file and push a <strong>tag</strong> into your repository you’ll see something like this in the <strong>Actions</strong> tab:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679182869381/7d05ae91-1e80-480e-bac4-24e6ca1b8eab.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679182882648/786b0e6b-f3da-40ef-97eb-aab1b11638a2.png" alt class="image--center mx-auto" /></p>
<p>And you’ll also see the release:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679182891237/b763ae3f-e219-4fc6-86b1-05cd3f63e821.png" alt class="image--center mx-auto" /></p>
<hr />
<p>Well, that’s it for me now. Please let me know if it was useful to you or if you had any issues.</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://medium.com/@henryjperez">Medium</a> (For more opinion-based posts), and here on <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a> and my <a target="_blank" href="https://dev.henryjperez.com/">Hashnode blog</a>.</p>
<p>Have a nice day and until next time. Bye.</p>
]]></content:encoded></item><item><title><![CDATA[Functional programming in JavaScript]]></title><description><![CDATA[It's a programming paradigm that focuses on the use of functions as a primary building block of software. In JavaScript, functional programming is supported natively, which means that you can use it without any additional libraries or tools.
(And all...]]></description><link>https://dev.henryjperez.com/js-functional-programming</link><guid isPermaLink="true">https://dev.henryjperez.com/js-functional-programming</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[fundamentals]]></category><category><![CDATA[js]]></category><category><![CDATA[functions]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Thu, 16 Mar 2023 21:00:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1678998623831/4ead6c6f-5f0c-443c-a0a0-a9ef86103f44.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It's a programming paradigm that focuses on the use of functions as a primary building block of software. In JavaScript, functional programming is supported natively, which means that you can use it without any additional libraries or tools.</p>
<p>(And all the code that you are about to see here it's in this <a target="_blank" href="https://github.com/henryjperez/js_functional_programming--tutorial/tree/master">repo</a>)</p>
<p>Now, here are some of the key concepts of functional programming in JavaScript:</p>
<h1 id="heading-pure-functions">Pure functions</h1>
<p>A pure function is a function that always returns the same output for the same input, and does not have any side effects. In other words, it does not modify any external state or data. Pure functions are predictable, easy to test, and can be composed together to create more complex functions.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-comment">/*                Pure functions                */</span>
<span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-keyword">const</span> double = <span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> x * <span class="hljs-number">2</span>;
<span class="hljs-keyword">let</span> value = <span class="hljs-number">2</span>;
<span class="hljs-built_in">console</span>.group(<span class="hljs-string">'No matter the time executes the output will always be the same \ngiven the same value'</span>)
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))

value = <span class="hljs-number">3</span>
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))

value = <span class="hljs-number">12</span>
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))

value = <span class="hljs-number">234</span>
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.log(double(value))
<span class="hljs-built_in">console</span>.groupEnd()
</code></pre>
<p>In contrast, you can see what a <strong>not</strong> pure function would look like:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* ----------- Not so pure functions ---------- */</span>
<span class="hljs-keyword">const</span> ran = <span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> x * <span class="hljs-built_in">Math</span>.random();

<span class="hljs-built_in">console</span>.group(<span class="hljs-string">'It will always change no matter if is the same input'</span>)
<span class="hljs-built_in">console</span>.log(ran(value))
<span class="hljs-built_in">console</span>.log(ran(value))
<span class="hljs-built_in">console</span>.log(ran(value))
<span class="hljs-built_in">console</span>.groupEnd()
</code></pre>
<h1 id="heading-immutability">Immutability</h1>
<p>In functional programming, immutability is the idea that data should not be modified once it is created. Instead, new data is created based on the old data. This allows for more predictable and maintainable code.</p>
<h1 id="heading-higher-order-functions">Higher-order functions</h1>
<p>A higher-order function is a function that takes one or more functions as arguments or returns a function as its result. Higher-order functions are used extensively in functional programming.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-comment">/*            Higher Order Functions            */</span>
<span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">triple</span>(<span class="hljs-params">x</span>) </span>{
    <span class="hljs-keyword">return</span> x * <span class="hljs-number">3</span>;
}
<span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">16</span>, <span class="hljs-number">27</span>,];

<span class="hljs-keyword">const</span> result1 = numbers.map(<span class="hljs-function"><span class="hljs-params">y</span> =&gt;</span> y * <span class="hljs-number">3</span>);
<span class="hljs-keyword">const</span> result2 = numbers.map(triple);
<span class="hljs-comment">// const result3 = numbers.map(triple()) // map will execute the function, not you. You only declare it not call it</span>
<span class="hljs-comment">// result1 === result2</span>
<span class="hljs-comment">// result2 !== result3</span>

<span class="hljs-comment">// higher order function can also be</span>
<span class="hljs-comment">// a function which returns another function</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Higher order results"</span>, result1, result2, <span class="hljs-comment">/* result3 */</span>);
</code></pre>
<h1 id="heading-recursion">Recursion</h1>
<p>Recursion is a technique in which a function calls itself until a stopping condition is met. In functional programming, recursion is used instead of loops to iterate over data structures.</p>
<p>You can see that in this code of a <strong>deep copy</strong> of an object of JavaScript:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* --------------- Deep copy --------------- */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isObject</span>(<span class="hljs-params">element</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">typeof</span> element === <span class="hljs-string">"object"</span>;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isArray</span>(<span class="hljs-params">element</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.isArray(element);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deepCopy</span>(<span class="hljs-params">element</span>) </span>{ <span class="hljs-comment">// you can do this but with Freeze if you like (deepFreeze)</span>
    <span class="hljs-keyword">const</span> isObj= isObject(element);
    <span class="hljs-keyword">const</span> isArr = isArray(element);
    <span class="hljs-keyword">let</span> copy;

    <span class="hljs-keyword">if</span> (isArr) {
        copy = [];
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (isObj) {
        copy = {};
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> element;
    }

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> key <span class="hljs-keyword">in</span> element) {
        <span class="hljs-keyword">const</span> inKey = element[key];
        <span class="hljs-keyword">const</span> isKeyObject = isObject(inKey);

        <span class="hljs-keyword">if</span> (isKeyObject) {
            copy[key] = deepCopy(inKey)
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">if</span> (isArr) {
                copy.push(inKey);
            } <span class="hljs-keyword">else</span> {
                copy[key] = inKey;
            }
        }
    }
    <span class="hljs-keyword">return</span> copy;
}

<span class="hljs-keyword">const</span> objD1 = deepCopy(objA2);
<span class="hljs-built_in">console</span>.group(<span class="hljs-string">"Deep Copy"</span>)
<span class="hljs-built_in">console</span>.log(objD1, objA2)
objD1.a2 = <span class="hljs-number">75950</span>;
objD1.e2.f2 = <span class="hljs-number">6905589</span>
objA2.k2();
objD1.k2();
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After modifications"</span>)
<span class="hljs-built_in">console</span>.log(objD1, objA2)
<span class="hljs-built_in">console</span>.groupEnd(<span class="hljs-string">"Deep Copy"</span>)
</code></pre>
<h1 id="heading-function-composition">Function composition</h1>
<p>Function composition is the process of combining two or more functions to create a new function. This allows for more complex functionality to be built from simpler building blocks.</p>
<h1 id="heading-closures">Closures</h1>
<p>A closure is a function that has access to variables in its outer (enclosing) scope, even after the outer function has returned. This is possible because the variables are still being referenced by the inner function, and are not eligible for garbage collection. Closures are used extensively in functional programming and can be used to create private variables and functions, as well as to create higher-order functions. Here is an example of a closure in JavaScript:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-comment">/*                   Closures                   */</span>
<span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-keyword">const</span> rememberToSum = <span class="hljs-function"><span class="hljs-params">a</span> =&gt;</span> b =&gt; a + b;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rememberToSum</span>(<span class="hljs-params">a</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">b</span>) </span>{
        <span class="hljs-keyword">return</span> a + b;
    }
}
<span class="hljs-keyword">const</span> returnedSum = rememberToSum(<span class="hljs-number">5</span>);
<span class="hljs-built_in">console</span>.log(returnedSum(<span class="hljs-number">5</span>))
</code></pre>
<h1 id="heading-currying">Currying</h1>
<p>Currying is a technique in which a function that takes multiple arguments is converted into a sequence of functions that each take a single argument. This allows for more flexible function composition and partial function application. In JavaScript, you can use the <code>curry</code> function from the popular <code>lodash</code> library to curry functions. Here is an example of using <code>curry</code> to create a curried function:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-comment">/*                   Currying                   */</span>
<span class="hljs-comment">/* -------------------------------------------- */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">notCurredSumOfThree</span>(<span class="hljs-params">a, b, c</span>) </span>{
    <span class="hljs-keyword">return</span> a + b + c;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sumOfThree</span>(<span class="hljs-params">a1</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">b2</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">c3</span>) </span>{
            <span class="hljs-keyword">return</span> a1 + b2 + c3;
        }
    }
}
<span class="hljs-keyword">const</span> arrowSumOfThree = <span class="hljs-function"><span class="hljs-params">a</span> =&gt;</span> b =&gt; <span class="hljs-function"><span class="hljs-params">c</span> =&gt;</span> a + b + c; 

<span class="hljs-built_in">console</span>.log(notCurredSumOfThree(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>), sumOfThree(<span class="hljs-number">1</span>)(<span class="hljs-number">2</span>)(<span class="hljs-number">3</span>), arrowSumOfThree(<span class="hljs-number">1</span>)(<span class="hljs-number">2</span>)(<span class="hljs-number">3</span>));
</code></pre>
<p>Overall, functional programming in JavaScript can lead to more maintainable, predictable, and reusable code. It may take some time to get used to the functional programming paradigm, but it is worth exploring for any serious JavaScript developer.</p>
<hr />
<p>Well, that's it for now. I hope it was useful for you. Comment if you have any other suggestions or something to add, I'll be reading you.</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://medium.com/@henryjperez">Medium</a> (For more opinion-based posts), and here on <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a> and my <a target="_blank" href="https://dev.henryjperez.com/">Hashnode blog</a>.</p>
<p>Have a nice day and until next time. Bye.</p>
]]></content:encoded></item><item><title><![CDATA[The YAML Files]]></title><description><![CDATA[YAML
YAML is an information transfer language like JSON or XML. And it is used for its simplicity and consistency.
File Extention
These YAML files end with .yml or .yaml, either of them is correct.
Indentation
The indentation in YAML is essential, to...]]></description><link>https://dev.henryjperez.com/the-yaml-files</link><guid isPermaLink="true">https://dev.henryjperez.com/the-yaml-files</guid><category><![CDATA[YAML]]></category><category><![CDATA[GitHub Actions]]></category><category><![CDATA[redhat]]></category><category><![CDATA[xml]]></category><category><![CDATA[json]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Thu, 16 Mar 2023 01:21:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1678929840495/7316a5f6-42ad-4dc6-85b6-f788f1825bbc.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-yaml">YAML</h1>
<p><strong>YAML</strong> is an information transfer language like <strong><em>JSON</em></strong> or <strong><em>XML</em></strong>. And it is used for its simplicity and consistency.</p>
<h1 id="heading-file-extention">File Extention</h1>
<p>These YAML files end with <code>.yml</code> or <code>.yaml</code>, either of them is correct.</p>
<h1 id="heading-indentation">Indentation</h1>
<p>The indentation in YAML is essential, to make an indentation valid you need to use <strong><em>2 spaces per indentation</em></strong>. Indentation is used instead of curly brackets <code>{}</code>.</p>
<h1 id="heading-syntax">Syntax</h1>
<p>You don't end the line with a <code>;</code> or any other special character.</p>
<h2 id="heading-comments">Comments</h2>
<p>Use the <code>#</code> symbol to ignore whatever it is in front of this symbol until the end of the line.</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># variable: string commented</span>
<span class="hljs-attr">valid:</span> <span class="hljs-string">"not commented"</span>
</code></pre>
<h2 id="heading-objects">Objects</h2>
<p>You use indentation to denote that the variables below are methods of the object. YAML is sensitive to indentation so they all need to be at the same level of indentation.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">nameoftheobject:</span>
  <span class="hljs-attr">app:</span> <span class="hljs-string">some-name</span>
  <span class="hljs-attr">port:</span> <span class="hljs-number">9000</span>
  <span class="hljs-attr">version:</span> <span class="hljs-number">1.7</span>
</code></pre>
<h2 id="heading-lists">Lists</h2>
<p>Use the <code>-</code> symbol to make a list, remember to indent the variables that belong to that list. But you can also avoid indentation while using lists, so don't get confused when you see them in different forms of indentation. But all elements need to have the same indentation.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">microservices:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">app:</span> <span class="hljs-string">some-name</span>
    <span class="hljs-attr">port:</span> <span class="hljs-number">9000</span>
    <span class="hljs-attr">version:</span> <span class="hljs-number">1.7</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">app:</span> <span class="hljs-string">other-name</span>
    <span class="hljs-attr">port:</span> <span class="hljs-number">9002</span>
    <span class="hljs-attr">version:</span> <span class="hljs-number">1.9</span>
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">microservices:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">some-name</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">other-name</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">app:</span> <span class="hljs-string">dog</span>
    <span class="hljs-attr">port:</span> <span class="hljs-number">19</span>
    <span class="hljs-attr">versions:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-number">1.2</span>
    <span class="hljs-bullet">-</span> <span class="hljs-number">1.5</span>
    <span class="hljs-bullet">-</span> <span class="hljs-number">1.8</span>
</code></pre>
<p>You can also use brackets as a primitive.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">microservices:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">some-name</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">other-name</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">app:</span> <span class="hljs-string">dog</span>
    <span class="hljs-attr">port:</span> <span class="hljs-number">19</span>
    <span class="hljs-attr">versions:</span> [<span class="hljs-number">1.2</span>, <span class="hljs-number">1.5</span>, <span class="hljs-number">1.8</span>]
</code></pre>
<h2 id="heading-boolean">Boolean</h2>
<p><code>true</code> <code>false</code> <code>yes</code> <code>no</code> <code>on</code> and <code>off</code>, all of them are used as boolean values.</p>
<h3 id="heading-multiline-strings">Multiline strings</h3>
<p>Use the <code>|</code> symbol to make separate lines, and use the <code>&gt;</code> symbol to make a single line of the string.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">multilineString:</span> <span class="hljs-string">|
  This string is separated
  so there is no need to make a buzz
  this is how it will be shown</span>
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">multilineString:</span> <span class="hljs-string">&gt;
  This line will be shown as
  one line, no matter how long
  or how many breaks do I make</span>
</code></pre>
<h2 id="heading-environment-variables">Environment Variables</h2>
<p>Use the <code>$</code> <strong>before the name of the environment variable</strong> to use it.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">command:</span> <span class="hljs-string">mysql</span> <span class="hljs-string">-h</span> <span class="hljs-number">123.000</span><span class="hljs-number">.000</span> <span class="hljs-string">-u</span> <span class="hljs-string">root</span> <span class="hljs-string">$THIS_IS_A_PASSWORD</span> <span class="hljs-string">-e</span> <span class="hljs-string">'SELECT 1'</span>
</code></pre>
<h2 id="heading-placeholders">Placeholders</h2>
<p>Use the double curly brackets <code>{{}}</code>to use placeholders for templates.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">app:</span> {{ <span class="hljs-string">.Values.service.name</span> }}
</code></pre>
<h2 id="heading-multiple-yaml-files">Multiple YAML Files</h2>
<p>Use three dashes <code>---</code> to separate YAML files inside the same file.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">thisIsAVariable:</span> <span class="hljs-string">blah-blah-blah</span>

<span class="hljs-meta">---</span>
<span class="hljs-attr">thisIsAnotherFileInside:</span> <span class="hljs-string">this-is-another-file</span>
</code></pre>
<hr />
<p>Well, that's it for now. I hope it was useful for you. Comment if you have any other suggestions or something to add, I'll be reading you.</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://medium.com/@henryjperez">Medium</a> (For more opinion-based posts), and here on <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a> and my <a target="_blank" href="https://dev.henryjperez.com/">Hashnode blog</a>.</p>
<p>Have a nice day and until next time. Bye.</p>
]]></content:encoded></item><item><title><![CDATA[Typescript for JS developers: Setting up the environment on Node]]></title><description><![CDATA[Typescript is becoming more and more of a big deal. I wanted to learn it because people thought that it helps to prevent bugs and has so many features. And although it is to some extent, it doesn’t mean that it is easy to start within a real environm...]]></description><link>https://dev.henryjperez.com/typescript-for-js-developers-setting-up-the-environment-on-node</link><guid isPermaLink="true">https://dev.henryjperez.com/typescript-for-js-developers-setting-up-the-environment-on-node</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[backend]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Wed, 10 Nov 2021 22:24:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636574942266/OwS4ghtpB.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Typescript is becoming more and more of a big deal. I wanted to learn it because people thought that it helps to prevent bugs and has so many features. And although it is to some extent, it doesn’t mean that it is easy to start within a real environment.</p>
<h1 id="initialize-the-project">Initialize the project</h1>
<p>To quickly initialize the project just do:</p>
<pre><code class="lang-bash">npm init -y
</code></pre>
<p>Or if you want a more personalized project just do:</p>
<pre><code class="lang-bash">npm init
</code></pre>
<p>There it will ask you the following questions:</p>
<ul>
<li>Name of the package</li>
<li>Version</li>
<li>Description</li>
<li>Entry point</li>
<li>Test command</li>
<li>A git repository</li>
<li>Keywords</li>
<li>The name of the author</li>
<li>And the type of license</li>
</ul>
<h1 id="installing-the-dependencies">Installing the dependencies</h1>
<p>All the dependencies we’ll use are <em>typescript, nodemon, ts-node, tsconfig-paths</em> and <em>tsc-alias</em> as the main ones for development with typescript.</p>
<ul>
<li><strong>typescript</strong>: is the language compiler.</li>
<li><strong>nodemon</strong>: it listens to any change on the project and restarts it to run that change.</li>
<li><strong>ts-node</strong>: It helps to listen to the changes on a typescript project.</li>
<li><strong>tsconfig-paths</strong>: typescript has a feature that allows custom path names to the folders to avoid nested relative paths such as <code>”../../../../../../someFile.ts”</code>.</li>
<li><strong>tsc-alias</strong>: it will interpret those custom paths to relative routes on the compilation for production.</li>
</ul>
<p>One of the core features of Typescript is the <strong>type check</strong>. These are defined on the language, whether they are <code>strings</code>, <code>number</code> or <code>boolean</code> just to name a few, that makes sure that the code doesn’t use types of values that it wasn’t assigned to.</p>
<p>Considering the abode, we'll install an additional dependency for the code editor to understand the <strong>intellisense</strong> (code completion) part of the development in node to understand typescript as well: <em>@types/node</em>.</p>
<pre><code class="lang-bash">npm install typescript nodemon ts-node tsconfig-paths @types/node --save-dev
</code></pre>
<p>Remember that <code>--save-dev</code> (<code>-D</code> for short) it’s used for dependencies that are <strong>only require in development</strong>. As a side note, I recommend <strong>add</strong> <code>--save-exact</code> (<code>-E</code> for short) to <code>npm install</code> command, this will install the exact dependencies each time that the <code>package.json</code> file is used.</p>
<pre><code class="lang-bash">npm install typescript nodemon ts-node tsconfig-paths tsc-alias @types/node -ED
</code></pre>
<p>This is because, by default, npm install dependencies as “<em>from this version upwards</em>” and you can distinguish them with the <code>^</code> symbol at the beginning of each version.</p>
<pre><code class="lang-json"><span class="hljs-string">"devDependencies"</span>: {
    <span class="hljs-attr">"@types/node"</span>: <span class="hljs-string">"^16.11.7"</span>,
    <span class="hljs-attr">"nodemon"</span>: <span class="hljs-string">"^2.0.15"</span>,
    <span class="hljs-attr">"ts-node"</span>: <span class="hljs-string">"^10.4.0"</span>,
    <span class="hljs-attr">"tsc-alias"</span>: <span class="hljs-string">"^1.4.0"</span>,
    <span class="hljs-attr">"tsconfig-paths"</span>: <span class="hljs-string">"^3.11.0"</span>,
    <span class="hljs-attr">"typescript"</span>: <span class="hljs-string">"^4.4.4"</span>
  }
</code></pre>
<p>As opposed to:</p>
<pre><code class="lang-json"><span class="hljs-string">"devDependencies"</span>: {
    <span class="hljs-attr">"@types/node"</span>: <span class="hljs-string">"16.11.7"</span>,
    <span class="hljs-attr">"nodemon"</span>: <span class="hljs-string">"2.0.15"</span>,
    <span class="hljs-attr">"ts-node"</span>: <span class="hljs-string">"10.4.0"</span>,
    <span class="hljs-attr">"tsc-alias"</span>: <span class="hljs-string">"1.4.0"</span>,
    <span class="hljs-attr">"tsconfig-paths"</span>: <span class="hljs-string">"3.11.0"</span>,
    <span class="hljs-attr">"typescript"</span>: <span class="hljs-string">"4.4.4"</span>
  }
</code></pre>
<h1 id="setting-typescript">Setting typescript</h1>
<p>Typescript has a way to configure it to the project at hand. Use the following command to start from scratch:</p>
<pre><code class="lang-bash">npx tsc --init
</code></pre>
<p>This will generate a <code>tsconfig.json</code> file. This <code>json</code> has all the parameters that typescript accepts for configuration, in this case, most of them are <em>commented</em>. We’ll get there, for now, create a folder (or directory) at the root of the project called <em>src/</em>. For that you can simply use the following command:</p>
<pre><code><span class="hljs-keyword">mkdir</span> src
</code></pre><p>Inside that folder create the main file, in this case, it will be called <code>index</code> with the <code>.ts</code> extension. You can use <strong>Vim</strong> or any other text editor to create it. In this case, I will use <code>touch</code>:</p>
<pre><code class="lang-bash">touch index.ts
</code></pre>
<p>In it, write a simple code like:</p>
<pre><code class="lang-ts"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"hi, this is working"</span>);
</code></pre>
<p>And in the <code>src</code> folder create another directory named <code>example</code> and <code>file.ts</code> in that same folder. You can simply use this to do those things in one line:</p>
<pre><code class="lang-bash">mkdir src/example &amp;&amp; touch src/example/file.ts
</code></pre>
<h2 id="configuring-typescript">Configuring Typescript</h2>
<p>Remember when I told you to use the <code>npx tsc --init</code> command to generate the tsconfig file? Well, add at the beginning of the <code>tsconfig.json</code> the following code or uncomment the parts where this are located and put:</p>
<pre><code class="lang-json">    <span class="hljs-string">"lib"</span>: [<span class="hljs-string">"ESNext"</span>],
    <span class="hljs-string">"allowJs"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"outDir"</span>: <span class="hljs-string">"./dist"</span>,
    <span class="hljs-string">"rootDir"</span>: <span class="hljs-string">"./src"</span>,
    <span class="hljs-string">"baseUrl"</span>: <span class="hljs-string">"./"</span>,
    <span class="hljs-string">"paths"</span>: {
      <span class="hljs-attr">"@example/*"</span>: [<span class="hljs-string">"src/example/*"</span>]
    },
</code></pre>
<h2 id="putting-all-the-installed-dependencies-together">Putting all the installed dependencies together</h2>
<p>The simple version is this: Add the following code to the <code>package.json</code> replacing the current <code>scripts</code> section in the file:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"NODE_ENV=production node dist/index.js"</span>,
    <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"NODE_ENV=development nodemon src/index.ts --exec 'ts-node -r tsconfig-paths/register'"</span>,
    <span class="hljs-attr">"build"</span>: <span class="hljs-string">"tsc --project tsconfig.json &amp;&amp; tsc-alias -p tsconfig.json"</span>,
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"echo \"Error: no test specified\" &amp;&amp; exit 1"</span>
  },
</code></pre>
<p>Now run:</p>
<pre><code class="lang-bash">npm run build
</code></pre>
<p>You’ll see a <code>dist</code> folder right on the root of the project, that’s the compilation of the typescript code to javascript. Run:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>And it should output something like this:</p>
<pre><code class="lang-bash">&gt; ts_setup@1.0.0 start
&gt; NODE_ENV=production node dist/index.js

hi, this is working
</code></pre>
<p>Finally, in the <code>index.ts</code> of the <code>src</code> folder, replace it with the following code:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> variable <span class="hljs-keyword">from</span> <span class="hljs-string">"@example/file"</span>;

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"hi, this is working"</span>, variable);
</code></pre>
<p>The output should be something like this:</p>
<pre><code class="lang-bash">hi, this is working { x: <span class="hljs-string">'there'</span>, y: <span class="hljs-string">'hello'</span>, z: <span class="hljs-string">'hello, there'</span> }
</code></pre>
<p>You can even run <code>npm run build</code> and <code>npm start</code> for production.</p>
<p>You can find the source code on <a target="_blank" href="https://github.com/henryjperez/ts_setup--tutorial">in here</a>.</p>
<p>If you have any idea or want to point out some mistake that I made, write a comment below, I will read it and I'm sure that we will find a solution for it. I hope that you make fantastic sites with this information that I wrote.</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://medium.com/@henryjperez">Medium</a> (For more opinion based posts), and here on <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a> and my <a target="_blank" href="https://henryjperez.hashnode.dev/">Hashnode blog</a>.</p>
<p>Have a nice day and until next time. Bye.</p>
]]></content:encoded></item><item><title><![CDATA[Typography Crash Course]]></title><description><![CDATA[Typography is the graphic representation of the written word.
Throughout history, people expressed their ideas through language. They give them form and shape words. However, memory can only last that much. With time, those who communicated and share...]]></description><link>https://dev.henryjperez.com/typography-crash-course</link><guid isPermaLink="true">https://dev.henryjperez.com/typography-crash-course</guid><category><![CDATA[Design]]></category><category><![CDATA[Developer]]></category><category><![CDATA[UX]]></category><category><![CDATA[UI]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Wed, 10 Nov 2021 16:28:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636559720831/GFXuRkRo7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Typography <strong>is the graphic representation of the written word</strong>.</p>
<p>Throughout history, people expressed their ideas through language. They give them <strong>form</strong> and <strong>shape</strong> words. However, memory can only last that much. With time, those who communicated and shared knowledge fated away and so much of their knowledge.</p>
<p>To perpetuate our ideas we started to represent language visually. This changed everything. Not only you could keep the thoughts and ideas longer, but also manipulate them. To play it over and over in your head until you understood what the author was talking about.</p>
<p>Now we can know what someone from different ages and countries was writing about. Communication rise, especially when started to product it quicker like with print or, nowadays, the internet.</p>
<h1 id="yeah-yeah-but-why-does-it-matter">Yeah yeah, but why does it matter?</h1>
<p>Ideas are influenced by the way they are written. Different styles convey different messages. When the language is spoken we can understand the content and also the way it was delivered. The intention behind that message.</p>
<p><strong>We can't know for sure how the reader will interpret our words</strong>.</p>
<p>Words help to communicate a message, <strong><em>good</em></strong> <strong>typography helps to connect words</strong>. That means that the visual implementation makes it easier to read the content of words, can set a brand apart, or just make the information more accessible overall.</p>
<p>You can make something aesthetically appealing and deliver a good narrative. Set your identity with what you want to tell.</p>
<p>Bad typography can confuse and diverge your content from your message.</p>
<p>So, be sure to pursue aesthetics and meaning in your writings. Because everything is taken into account.</p>
<h1 id="typefaces-and-fonts">Typefaces and Fonts</h1>
<h2 id="typefaces">Typefaces</h2>
<p>When I talk about <strong>typefaces</strong> I'm referring to the whole set of letters and symbols that share the same intended design.</p>
<h2 id="font">Font</h2>
<p>Fonts refer to the <strong>weight</strong> and <em>italic</em> style variations of a <strong>typeface</strong>. In short, it's an instance of a typeface.</p>
<h1 id="types-of-typefaces">Types of typefaces</h1>
<h2 id="serif">Serif</h2>
<p>They are typefaces with decoration at the extremes of each letter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636560084085/OyfOkvE08.jpeg" alt="brett-jordan-M9NVqELEtHU-unsplash.jpg" /></p>
<h2 id="sans-serif">Sans-serif</h2>
<p>Typefaces without any decorations at the extremes of each letter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636561291617/lujydC9_X.jpeg" alt="damon-lam-P-KoSvCU7mo-unsplash.jpg" /></p>
<h2 id="monospace">Monospace</h2>
<p>In monospace each letter and symbol update the same space no matter the width of each one.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636561323335/d3aAcDPqJ.jpeg" alt="gabriel-heinzer-g5jpH62pwes-unsplash.jpg" /></p>
<h2 id="scripts">Scripts</h2>
<p>Are hand-written typestyles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636561341310/Pw4-CPvpc.jpeg" alt="wander-creative-QaOXnxNu6FQ-unsplash.jpg" /></p>
<h1 id="how-to-choose-a-typeface-or-font-family">How to choose a typeface or font family</h1>
<p>Well, this is the part where I say that it depends. You see, I learn that as much study and analysis typography has, in the end, it's not an exact science. Sometimes you need to try different types and pick the one that gives the message that you want, in the context that you want and the medium that you're in.</p>
<p>Having said that, there are still some things to consider when choosing a typeface like the mood of the message or the medium that it will be seen.</p>
<p>Choosing the right type will make it more <strong>accessible</strong> for everyone who reads it.</p>
<h2 id="the-mood">The mood</h2>
<p><em>Formal</em> texts are associated often with <em>serif</em>, but <em>script</em> types can also be formal. And the more casual ones are the <em>sans-serif</em> which are good for context without formalities.</p>
<h2 id="print-vs-digital">Print vs Digital</h2>
<p>It's believed that the <em>serif</em> type will be easier to read on small printed elements like books or newspapers. The <em>sans-serifs</em> are used more often on digital devices and magazines.</p>
<h2 id="white-space">White Space</h2>
<p>It’s the area between elements.</p>
<p>Although is called <strong>whitespace</strong>, that doesn’t always need to be white. The main purpose is to allow text <em>to breathe</em>.</p>
<h2 id="title-vs-text">Title vs Text</h2>
<p>Texts need to be easy to read even on small fonts, things like the height difference between caps and small caps are taken into account, in this case, a lower gap between those two is important for readability.</p>
<p>Titles can have more freedom in that regard, but they need to be trimmed to occupate as much space as possible without breaking into the next line. For that reason, the space between letters can be less than the normal text.</p>
<h1 id="size-contrast-and-hierarchy">Size, Contrast, and Hierarchy</h1>
<p>On the designing of typography, always use relative size units like <strong>em</strong> (relative to a specific part) or <strong>rem</strong> (relative to the root font size of the given document).</p>
<h2 id="contrast">Contrast</h2>
<p>The color of the font and the color of the background are really important to decide the contrast.</p>
<p>A proportion would be between 4.5 for texts and background and 3.1 for titles.</p>
<h2 id="size">Size</h2>
<h3 id="text">Text</h3>
<p>Somewhere between 16px and 24px.</p>
<p><strong>The length of the paragraph</strong> is measured on letter count than on absolute sizes. A maximum length would be between 50 to 70 letters per line. But, of course, that depends on the size of the screen. In either case, the idea is to leave <strong>whitespace</strong> for the content to rest and make it easy to read.</p>
<p>You can use a max length of 30em and work from there.</p>
<h3 id="tittle">Tittle</h3>
<p>Between 26px and around 40px.</p>
<h2 id="hierarchy">Hierarchy</h2>
<p>Hierarchy is the distinction between one element with another, and it is used to guide the reader through the text with different types of emphasis.</p>
<p>You can use size, contrast, whitespace, and fonts to create an organized implementation of the elements.</p>
<p>A good rules of thumb with size is to start with 16px and add an 8x increase (24px, 32px, 40px, etc). But, don't forget the relative units of <code>em</code> and <code>rem</code>.</p>
<p>In contrast, make sure that the colors aren't "<em>too vibrant</em>" with each other.</p>
<h2 id="alignment">Alignment</h2>
<ul>
<li><strong>Centered</strong> text can be used in titles, but it’s a good idea on regular text. Remember that text needs to be easy to read. But you can center the block of text on which the content rests.</li>
<li><strong>Justified</strong> alignment is more common in printed media, especially newspapers which need them to divide the content into columns and justify alignment takes advantage of that.</li>
<li><strong>Left</strong> alignment is especially useful for regular text, but it can be used on titles as well.</li>
<li><strong>Right</strong> alignment. Since we read from left to right, I wouldn’t recommend using it. But, like many things, there are exceptions. This isn’t an exact science, so you can experiment if you want.</li>
</ul>
<p>Finally, choosing the right typography forces you to be conscious about the style, intention, and mood you want to deliver. So don't be afraid to experiment and use what fit into your message.</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://medium.com/@henryjperez">Medium</a> (For more opinion based posts), and here on <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a> and my <a target="_blank" href="https://henryjperez.hashnode.dev/">Hashnode blog</a>.</p>
<p>Have a nice day and until next time. Bye.</p>
]]></content:encoded></item><item><title><![CDATA[E-commerce UX for the busy developer]]></title><description><![CDATA[It is a mistake to think of an E-commerce platform as just an online store. A poor design makes it hard for your customer to interact with your business. Which leads to low sales, customer abandonment, and a loss in revenue.
The key thing here is the...]]></description><link>https://dev.henryjperez.com/e-commerce-ux</link><guid isPermaLink="true">https://dev.henryjperez.com/e-commerce-ux</guid><category><![CDATA[UX]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[course]]></category><category><![CDATA[Design]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Mon, 08 Nov 2021 04:49:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636339836206/DDAuCPrDC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is a mistake to think of an E-commerce platform as <strong>just</strong> an online store. A poor design makes it hard for your customer to interact with your business. Which leads to low sales, customer abandonment, and a loss in revenue.</p>
<p>The key thing here is the word “<em>just</em>”. It includes a lot more that doesn’t exist in a conventional shop. It takes into consideration a lot more like the number of clicks, pages visited and time inside the page.</p>
<p>It’s important to take seriously the design of every e-commerce store since it is the bridge between your customers and your business.</p>
<p>This article is not a must-do guide for the experience of a user of your e-commerce site. It’s just a list of considerations to take into account when developing one. There is no such thing as a definitive answer in a field that is constantly evolving. And it is up to you to use this and any information that you encounter with the most care. Use your experience, your intuition, and the metrics of the site to determine what works for you.</p>
<h2 id="heading-customers">Customers</h2>
<p>We can all agree that everyone is not the same. Your customers will explore your page with different goals in mind. Here is a brief consideration of the type of customer:</p>
<ul>
<li><p><strong>Based on the Product</strong>: They know what they are looking for. They have a goal in mind and they are going to find it. Give them the tools to achieve that goal.</p>
</li>
<li><p><strong>Based on the Navigation</strong>: They have time. They want to search and see things around them. They might stop the search one day only to continue the next one.</p>
</li>
<li><p><strong>Based on the Investigation</strong>: They would like to have all the information possible to make an informed decision. Things like prices, quality pictures, addresses, and reviews. Every relevant information that you could give them.</p>
</li>
<li><p><strong>Bounty hunters</strong>: They want to buy the best products for the best price. Things like the discounts right next to the “original” price it’s very compelling to them.</p>
</li>
<li><p><strong>Occasional purchase</strong>: They could be one of the above but they could have found your e-commerce by chance, or by a gift card or something. Make sure that your site allows you to buy without registering or at least explain the benefits of doing it.</p>
</li>
</ul>
<p>With that notion in mind, let’s dive into the specifics.</p>
<h3 id="heading-search">Search</h3>
<p>The search must be at the heart of your business. Google made a whole empire based on a search engine. Youtube, at its core, is a place to search and watch videos, without the search component the platform would be a flop. Let customers go forward and back whenever they want.</p>
<p>Pay attention to the categories and subcategories of navigation. Remember to allow the exploration of a category as a whole instead of just automatically using a subcategory.</p>
<p>The <strong>search bar</strong> is very important. Take it very seriously. If you can add relevant suggestions and autocompletion then do it. And don’t forget to make it as simple and intuitive as possible, but with additional options for advanced users who want to make a specific type of search.</p>
<p>And don’t hesitate to add filters.</p>
<h3 id="heading-make-accessible-the-information-about-the-product">Make accessible the information about the product</h3>
<p>Well, this is not only to make your business more transparent to your customers but also because it allows people to analyze and compare the products that you're offering. Whether with another store or other products that you have in stock, people will make comparisons, so make that information accessible.</p>
<p>Again, make a detailed description. Don’t saturate. You can make a summary, add a button to "<em>read more</em>" or do anything that alludes to the information that you have without clouding the page with information.</p>
<p>Make the price comparison easy, like adding the <s>original price</s>, the <strong>discounted price</strong> and how much the customer is saving. Also, remember that offers help to cause that sense of urgency.</p>
<p>Some people will give you their email for a newsletter, but only if you make it clear that they will find out more discounted prices, rare products, or relevant information for them.</p>
<p>Add information about the company. This will make it seem trustworthy and will send a message of professionalism to everyone who visits your e-commerce, investors included. That's related to the social proof that you need.</p>
<h4 id="heading-make-a-similar-products-or-suggested-products-section-on-the-product-detail">Make a "<em>similar products</em>" or "<em>suggested</em>" products section on the product detail</h4>
<p><strong>This is only an idea</strong> since it could backfire by leading to decision fatigue of the abundance of choices. So bear in mind that you need to make the information digestible. That's related to <strong>information theory</strong>.</p>
<h3 id="heading-social-component">Social Component</h3>
<ul>
<li><p>Allow people to share this product.</p>
</li>
<li><p>Add links to similar products.</p>
</li>
<li><p>Highlight products on offer or new products or more bought or whatever.</p>
</li>
<li><p>Comments and reviews, both good and bad because both sides of the opinions are valuable and it will make your site more transparent.</p>
</li>
</ul>
<h3 id="heading-buying-process">Buying process</h3>
<ul>
<li><p><strong>Simplify the shopping and checkout process</strong>.</p>
</li>
<li><p>Make easy the usage of coupons, you can apply them automatically if necessary.</p>
</li>
<li><p>Make e-commerce able to buy without registration.</p>
</li>
<li><p>Clear distribution of the information.</p>
</li>
</ul>
<h2 id="heading-pages">Pages</h2>
<h3 id="heading-home">Home</h3>
<p>It needs to answer the doubts of the customers. You can use it to show the catalog or to show links to where to find those catalogs or something.</p>
<p>The home page is meant to be the first thing that your customers will see, just like a shelf in a store. You can ask yourself, what products do you want to show first to the customers? What things can you show them so that they keep buying?</p>
<ul>
<li><p>Make it clear that this is e-commerce.</p>
</li>
<li><p>Allow them to buy on the home page.</p>
</li>
<li><p>Give them access to the catalog.</p>
</li>
<li><p>Information architecture.</p>
</li>
<li><p>Buying and selling process: types of payments, devolution policy, delivery options, etc.</p>
</li>
<li><p>Build thrust:</p>
<ul>
<li><p>Customer services.</p>
</li>
<li><p>Privacy policies?</p>
</li>
<li><p>Information about the company.</p>
</li>
</ul>
</li>
<li><p>Make the <strong>URL</strong> as simple as possible.</p>
</li>
<li><p>Make it simple, with this I mean don't saturate with information and link the customers.</p>
</li>
<li><p>Make it clear what and how you sell so that customers can understand it as soon as possible.</p>
</li>
<li><p>Add links to relevant information like policies, solutions or navigation, etc.</p>
</li>
</ul>
<h4 id="heading-be-concise">Be concise</h4>
<p>The navigation must be clear and repeat like a pattern. Be consistent on the whole website.</p>
<p>Things like menus must be always accessible, and make it easy to access core functions like shopping cart, catalog, etc.</p>
<h3 id="heading-category-pages">Category pages</h3>
<p>They show and present the categories to the users. They are the bridge between choosing a category and a product or a list of products.</p>
<p>They represent order, so they can't be messy. And don't automatically move users to the subcategories. Don't saturate them with information. And show the levels of navigation so the user can move in the app and categories.</p>
<h3 id="heading-product-list-pages">Product List pages</h3>
<ul>
<li><p>Present.</p>
</li>
<li><p>Show.</p>
</li>
<li><p>Categorize.</p>
</li>
</ul>
<p>Show the name of the product, price (always), add other options if they are available, availability now and in the near future, pagination (it tells that there are more products), and don't overwhelm with the suggestions, and quality images (this is important because many people buy after seeing a good set of images and show detailed views and everything).</p>
<p>Show which links they have seen (like Google does), and add personalized products and attention. Add filters and orders for choosing the sort order and filters and such.</p>
<h3 id="heading-product-page">Product page</h3>
<p>This is where the user starts to make the choices in the buying process. <strong>This is the best sales agent</strong> for your site. They will compare your products with those of your competition.</p>
<ul>
<li><p>Reviews</p>
</li>
<li><p>Images: don't forget not only to show the product itself but also in context.</p>
</li>
<li><p>Description: They want clear descriptions, you can add different stages of the descriptions, like the technical ones on one side, and the general description on the other.</p>
</li>
<li><p>Price.</p>
</li>
<li><p>Discount: you can add them automatically if they have a coupon or something that it's related to some promotion, and show the discount price and all its benefits.</p>
</li>
<li><p>Name.</p>
</li>
<li><p>Availability.</p>
</li>
<li><p>A clear way to buy or add to a cart or something.</p>
</li>
<li><p>Categories.</p>
</li>
<li><p>Navigation.</p>
</li>
<li><p>Zoom into the images.</p>
</li>
<li><p>Delivery and buying options.</p>
</li>
<li><p>Variations.</p>
</li>
</ul>
<p><strong>Talk in the language of the users</strong>. What you show is what you sell, don't make shady businesses with fake images or descriptions.</p>
<h4 id="heading-reviews">Reviews</h4>
<p>Show the good and the bad ones, present summaries and <em>show more</em> options for the reviews.</p>
<h3 id="heading-checkout">Checkout</h3>
<ul>
<li><p>Order the steps just like the users expects them.</p>
</li>
<li><p>Show the progress and the steps in the process.</p>
</li>
<li><p>Minimize distractions.</p>
</li>
<li><p>Add clear buttons for the process, like a go-back option, the step before, the step forward, and the cancel, (save the state of the whole thing on redux or something).</p>
</li>
<li><p>Only ask for relevant information about that shopping process.</p>
</li>
<li><p>Justify why are you asking for each piece of information, and add a description of the name of that field, use a title attribute, or use HTML and CSS to make a floating info panel on hover.</p>
</li>
</ul>
<h4 id="heading-forms">Forms</h4>
<ul>
<li><p>Don't ask for the same information or information that you already have</p>
</li>
<li><p>Update the information each time that it changes for the next checkout</p>
</li>
<li><p>Autocomplete the fields with the info that you have, but allow them to be changed.</p>
</li>
<li><p>Use clear tags and add hover descriptions to those fields</p>
</li>
<li><p>Generate long enough input fields for each field. And make sure to use the right tags for input, like numbers for numbers, and text for text.</p>
</li>
<li><p>Some users will use the "Enter" or "Return" keys to go to the next step.</p>
</li>
<li><p>Allow users to correct or change their info at any point.</p>
</li>
<li><p>Don't preselect like you were the user.</p>
</li>
</ul>
<h4 id="heading-error-messages">Error messages</h4>
<p>They need to explain what went wrong. Be clear and concise.</p>
<p>They must appear next to the input field and don't overwrite the other fields.</p>
<p>They need to explain how to correct and solve the problem and be clear and concise.</p>
<p>Use red for the errors, because if you use it in other messages or things on the app then it will lose effectiveness. Take into consideration the users with visual impairments</p>
<p>Solve or show a possible error before it becomes a barrier when pressing the button or "enter".</p>
<p>Explain what you want with each field so that the error is less recurrent</p>
<h2 id="heading-shopping-cart">Shopping cart</h2>
<p>You need to show that the cart works and that it makes sounds or animations or something each time that they add something. The user must be able to config that.</p>
<p>Make clear the "<em>buy</em>" button and the "<em>add to cart</em>" button. The button "<em>remove from the cart</em>". And the quantity and total and discounts next to the total, be creative, remember that there aren't clear rules on this, only suggestions.</p>
<p>Explain what to do when the buyer and the receiver are different, like using a QR code or something.</p>
<p>Show what is on the cart.</p>
<p>The cart must be present at all times on the pages.</p>
<p>Add a "keep buying" button.</p>
<p>show links to the policies like devolution and such, and don't overwhelm with information.</p>
<p>Allow to change and modify the content of the cart. Always save the state of the cart.</p>
<h2 id="heading-navigation">Navigation</h2>
<p>Avoid empty categories and/or catalogs. Remember <strong>that with each click the user must get closer to reaching their goal</strong>.</p>
<p>Categories trees, bread crumbs, and stand-alone categories and subcategories are important.</p>
<p>Show relevant information and navigation for the user, you can highlight some products in the navigation.</p>
<p>Some products are part of multiple categories or needs.</p>
<h3 id="heading-app-navigation">App Navigation</h3>
<p>Remember to pay attention to trends or make your own, the tabs were really important, nowadays are the bottom tabs and drawers.</p>
<p>The hamburger menu and such are easy to recognize. It needs more than 4 categories, and if there is a lot of information it will become a disaster, and for those users that don't use too much internet then it might not be that intuitive.</p>
<p>The bottom navigation allows exploring the app with the dumb.</p>
<h2 id="heading-registration">Registration</h2>
<p>It must be optional, and they need to offer clear benefits to justify the process to the users.</p>
<p>You can use the email as usernames, don't have to allow them to create a username. But it's up to you.</p>
<p>If it is obligatory the registration, explain why and the advantages.</p>
<p>Give space for:</p>
<ul>
<li><p>registered users.</p>
</li>
<li><p>about to register.</p>
</li>
<li><p>guess users.</p>
</li>
</ul>
<p>Add the logout button.</p>
<h2 id="heading-delivery-and-shipping-options">Delivery and shipping options</h2>
<ul>
<li><p>Show the price of the shipping.</p>
</li>
<li><p>Allow them to choose.</p>
</li>
<li><p>Don't show choices that do not apply to the user or product.</p>
</li>
<li><p>Show info about the delivery company, and possibly about the delivery person.</p>
</li>
<li><p>Show the estimated date or time of the delivery.</p>
</li>
<li><p>All in one price, even if they are more than one product.</p>
</li>
<li><p>Allow the user to add instructions for the delivery.</p>
</li>
<li><p>Add the precedence of the product (this is completely optional, it depends on the type of product and business).</p>
</li>
<li><p>Show complete information like phone number, localization, and times. And, if applicable, the delivery options or where to pick up the product.</p>
</li>
</ul>
<h2 id="heading-totals-and-cost">Totals and cost</h2>
<ul>
<li><p>Show all the individual costs.</p>
</li>
<li><p>Show the discount costs.</p>
</li>
<li><p>Show the total cost.</p>
</li>
<li><p>Show the total cost with the discounts.</p>
</li>
<li><p>Add instructions when where to find the info that we are asking</p>
</li>
<li><p>Show familiar images like a credit card for payments.</p>
</li>
<li><p>Allow adding coupons in the right place to avoid friction.</p>
</li>
<li><p>Show the money available like in a gift card or the wallet or general balance or whatever.</p>
</li>
<li><p>Make simple code names.</p>
</li>
</ul>
<h2 id="heading-resume-page">Resume (page)</h2>
<p>Show all the details in a resumed way (and <em>view more</em> if you need to) of the buy.</p>
<p>Add in the whole process the option to cancel the process.</p>
<p>Show all that information and allow the user to confirm.</p>
<p>You can think of it as a ticket:</p>
<ul>
<li><p>A "thank you" + name or something.</p>
</li>
<li><p>A number of the buy or whatever.</p>
</li>
<li><p>Info for the follow-up of the process.</p>
</li>
<li><p>A PDF or a printable option for the user.</p>
</li>
<li><p>A "<em>keep shopping</em>" button.</p>
</li>
<li><p>A logout button (this one is optional, for the users that want to exit the process securely).</p>
</li>
</ul>
<p>And, that's it. Remember, these aren't absolute rules to follow, they are only suggestions. It's up to you to find the best user experience for your e-commerce, and that's the most exciting part.</p>
<p>If you have any idea or want to point out some mistake that I made, write a comment below, I will read it and I'm sure that we will find a solution for it. I hope that you make fantastic sites with this information that I wrote.</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://github.com/henryjperez">Github</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://medium.com/@henryjperez">Medium</a> (For more opinion based posts), and here on <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a> and my <a target="_blank" href="https://henryjperez.hashnode.dev/">Hashnode blog</a>.</p>
<p>Have a nice day and until next time. Bye.</p>
]]></content:encoded></item><item><title><![CDATA[Git Branches: A Crash Course Guide]]></title><description><![CDATA[Branches are a core feature of Git which allows us to work with different versions in parallel histories.
Note: throughout this tutorial, I’ll be using < and > symbols to show the commands, however, these symbols are not required to implement them. I...]]></description><link>https://dev.henryjperez.com/git-branches</link><guid isPermaLink="true">https://dev.henryjperez.com/git-branches</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[tools]]></category><category><![CDATA[Devops]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Henry J. Perez]]></dc:creator><pubDate>Wed, 03 Nov 2021 06:55:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635921995405/xfUGa1Esb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Branches</strong> are a core feature of <strong>Git</strong> which allows us to work with different versions in <strong>parallel</strong> histories.</p>
<p><strong>Note</strong>: throughout this tutorial, I’ll be using <code>&lt;</code> and <code>&gt;</code> symbols to show the commands, however, these symbols are <strong>not</strong> <strong>required</strong> to implement them. I just wanted to comment on it 😎. Now, let’s go with the article.</p>
<h2 id="heading-creating-branches">Creating Branches</h2>
<p>The names <strong>can’t</strong> have <strong>spaces</strong>. If you need to make a <strong>separation</strong> use symbols like: <code>-</code> or <code>_</code>.</p>
<pre><code class="lang-sh">git branch &lt;new-branch&gt;
</code></pre>
<h2 id="heading-git-checkout-vs-git-switch">git checkout vs git switch</h2>
<p>You can have as many branches as you want in the repository; to switch between a branch and another there are two commands: <code>git checkout</code> and <code>git switch</code>.</p>
<p>Git <strong>checkout</strong> is used on many other aspects of <strong>Git</strong> besides branches; while <code>git switch</code> is used only for branches which decreases the margin for error and it’s the best way to switch branches.</p>
<p><strong>I recommend</strong> <code>git switch</code>.</p>
<h2 id="heading-renaming">Renaming</h2>
<p>To change the name of the branch you’re in:</p>
<pre><code class="lang-sh">git branch -m &lt;head-branch-new-name&gt;
</code></pre>
<p>To rename a specific branch:</p>
<pre><code class="lang-sh">git branch -m &lt;old-name-branch&gt; &lt;new-name-branch&gt;
</code></pre>
<h2 id="heading-delete-branches">Delete Branches</h2>
<p>To delete branches locally:</p>
<pre><code class="lang-sh">git branch -d &lt;branch&gt;
</code></pre>
<pre><code class="lang-sh">git push origin --delete &lt;branch&gt;
</code></pre>
<p>And to delete a branch from the <strong>remote</strong> repository use this command:</p>
<pre><code class="lang-sh">git push origin :&lt;branch&gt;
</code></pre>
<p>Just <strong>make sure</strong> that <strong>nobody</strong> in your team <strong>depends</strong> on the changes in that <strong>branch</strong>.</p>
<h2 id="heading-merge">Merge</h2>
<p><code>git merge</code> works to <strong>integrate</strong> the changes between <strong>branches</strong>. This integration is commonly referred to as “<em>merge</em>”; it keeps the branch history of “<em>commits</em>” intact and creates a new “<em>commit</em>” for the branch receiving the changes.</p>
<p>First, switch to the branch in which you want to receive the changes, then use the following command:</p>
<pre><code class="lang-sh">git merge &lt;incoming-branch&gt;
</code></pre>
<h2 id="heading-rebase">Rebase</h2>
<p>It's another way of <strong>integrating</strong> the <strong>changes</strong> of a <strong>commit</strong> history between two branches. It changes the commit history by making the integration a <strong>straight line</strong> and not a combination of branches.</p>
<p>Like in <code>git merge</code>, you have to switch to the branch in which you want to receive the changes, then use the command:</p>
<pre><code class="lang-sh">git rebase &lt;incoming-branch&gt;
</code></pre>
<h2 id="heading-comparing-branches">Comparing Branches</h2>
<p>Check which commits are in <strong>branch-b</strong>, but not on <strong>branch-a</strong>.</p>
<p>To check which <strong>commits</strong> are in one branch (<em>branch-b</em>) and not in another (<em>branch-a</em>) use this command:</p>
<pre><code class="lang-sh">git <span class="hljs-built_in">log</span> &lt;branch-a&gt;..&lt;branch-b&gt;
</code></pre>
<p>You can <strong>also</strong> use it to compare them with the <strong>remote branches</strong>.</p>
<p>It was a short post but I just wanted to challenge myself to write so I told myself that I was gonna do this no matter what, so here it is. I hope I was useful to you.</p>
<p>That’s it for me, but you can follow me on <a target="_blank" href="https://www.linkedin.com/in/henryjperez/">LinkedIn</a>, <a target="_blank" href="https://twitter.com/henryjperez">Twitter</a>, <a target="_blank" href="https://www.instagram.com/henryjperez/">Instagram</a>, <a target="_blank" href="https://www.facebook.com/henryjperezr">Facebook</a>, <a target="_blank" href="https://github.com/henryjperez/">Github</a>, <a target="_blank" href="https://www.reddit.com/user/henryjperez">Reddit</a> and here in <a target="_blank" href="https://hashnode.com/@henryjperez">Hashnode</a>. Also, you can subscribe to my newsletter down below 👇. Well, see ya!</p>
]]></content:encoded></item></channel></rss>