<?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[How to dev]]></title><description><![CDATA[Articles about programming. JavaScript and general advice for beginners in the industry.]]></description><link>https://how-to.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1642449197899/6x_ms8Sjb.jpeg</url><title>How to dev</title><link>https://how-to.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 05:46:31 GMT</lastBuildDate><atom:link href="https://how-to.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Changes in programming made possible with AI]]></title><description><![CDATA[I’ve been working in programming for the last 16 years. Let’s see what changes I see in our industry that are enabled by generative AI.
Rapid prototyping
The last few months, I’ve been working on a set of WordPress plugins, related to event organizat...]]></description><link>https://how-to.dev/changes-in-programming-made-possible-with-ai</link><guid isPermaLink="true">https://how-to.dev/changes-in-programming-made-possible-with-ai</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[AI]]></category><category><![CDATA[SaaS]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Mon, 22 Dec 2025 13:22:21 GMT</pubDate><content:encoded><![CDATA[<p>I’ve been working in programming for the last 16 years. Let’s see what changes I see in our industry that are enabled by generative AI.</p>
<h2 id="heading-rapid-prototyping">Rapid prototyping</h2>
<p>The last few months, I’ve been working on a set of WordPress plugins, related to event organization. With the help of AI, I’m able to get a minimal viable version of a feature that got to my mind in hours—which makes the whole development process more fun and faster. Before AI, I was trying to “measure twice and cut once” while programming—trying to minimize the waste, the expensive, development time. Currently, I’m building quick and dirty, first version with heavy help of Claude, and then I’m improving the code when (or if) I end up using it.</p>
<h2 id="heading-easy-technology-switch">Easy technology switch</h2>
<p>Use of generative AI makes it easy to switch technology. My professional experience in the last decade was mostly in AngularJS—an outdated, frontend framework. AI, allows me to start building things with other technologies, and learning while doing something practical—which is my favourite way of learning.</p>
<h2 id="heading-priority-shift-from-programming-to-solution-building">Priority shift from programming to solution building</h2>
<p>AI makes the skill of <em>speaking the machine’s language</em> less important—right now, it can make the code that compile just fine in no time. But this doesn’t make the programmer’s job redundant—it just shifts the value to solution building. We can spend more time understanding the business case of users of our application, and spend less time turning it into code that can runs on a machine.</p>
<h2 id="heading-conclusions">Conclusions</h2>
<p>For me personably, the biggest shift is that as a sole developer, I can easily start building a solution and try turning it into a product. Things that before felt like a bit too much to chew for a team of one, feels much more reachable right now. The current technology opens a possibility to build and run a micro-SaaS, especially if combined with affordable prices for the customers.</p>
]]></content:encoded></item><item><title><![CDATA[Advantages of unit testing—with examples in Jasmine]]></title><description><![CDATA[Writing unit tests takes time and effort. Nonetheless, many teams insist on writing them anyway—that’s because of the benefits they bring to a project. Those benefits are mainly the following:

fast feedback—unit tests speed up each iteration of twea...]]></description><link>https://how-to.dev/advantages-of-unit-testingwith-examples-in-jasmine</link><guid isPermaLink="true">https://how-to.dev/advantages-of-unit-testingwith-examples-in-jasmine</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Testing]]></category><category><![CDATA[jasmine]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Thu, 15 Feb 2024 21:53:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1708033973361/65c6a803-3c45-43a7-a578-84c7e27c83f8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Writing unit tests takes time and effort. Nonetheless, many teams insist on writing them anyway—that’s because of the benefits they bring to a project. Those benefits are mainly the following:</p>
<ul>
<li>fast feedback—unit tests speed up each iteration of tweaking the code, and those gains can offset at least some time spent on writing tests.</li>
<li>Explicit expectations—clear communication of what is expected from the code. </li>
<li>Attention to edge cases—good unit tests will provide examples for every edge case that developers can think of.</li>
<li>Easy refactoring—an infrastructure to support code evolution in the long term.</li>
</ul>
<p>Let’s see those benefits in more details:</p>
<h2 id="heading-fast-feedback">Fast feedback</h2>
<p>Computers excel at well-defined, repetitive tasks. When you write unit tests, you write code that will verify whether your program does what it was meant to do. With automated verification in place, you can check your code very quickly. In my work, I have 3200+ that run just under14 seconds. With such performance, you can retest your whole codebase every time when you save your code. After I got more experience with writing unit tests, it started to feel that the time I saved with the quicker feedback loop returns the time I invested in writing tests.</p>
<p>As an example, let’s see update unit tests for the <code>translate</code> method introduced in my <a target="_blank" href="https://how-to.dev/pure-functions-and-basic-tests-in-jasmine">last article</a>:</p>
<pre><code class="lang-JavaScript">  describe(<span class="hljs-string">"translate"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should translate to supported languages"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(translate(<span class="hljs-string">"hello"</span>, <span class="hljs-string">"en"</span>)).toEqual(<span class="hljs-string">"Hello!"</span>);
      expect(translate(<span class="hljs-string">"hello"</span>, <span class="hljs-string">"pl"</span>)).toEqual(<span class="hljs-string">"Cześć!"</span>);
    });

    it(<span class="hljs-string">"should default to english if language missing"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(translate(<span class="hljs-string">"hello"</span>, <span class="hljs-string">"fr"</span>)).toEqual(<span class="hljs-string">"Hello!"</span>);
    });

    it(<span class="hljs-string">"should return the key if translation is missing"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(translate(<span class="hljs-string">"farewell"</span>, <span class="hljs-string">"en"</span>)).toEqual(<span class="hljs-string">"farewell"</span>);
      expect(translate(<span class="hljs-string">"farewell"</span>, <span class="hljs-string">"pl"</span>)).toEqual(<span class="hljs-string">"farewell"</span>);
      expect(translate(<span class="hljs-string">"farewell"</span>, <span class="hljs-string">"fr"</span>)).toEqual(<span class="hljs-string">"farewell"</span>);
    });
  });
</code></pre>
<p>Running those tests happens in the blink of an eye:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>

&gt; testing-example@1.0.0 <span class="hljs-built_in">test</span>
&gt; jasmine

Randomized with seed 31262
Started
...


Ran 3 of 21 specs
3 specs, 0 failures
Finished <span class="hljs-keyword">in</span> 0.003 seconds
Incomplete: fit() or fdescribe() was found
Randomized with seed 31262 (jasmine --random=<span class="hljs-literal">true</span> --seed=31262
</code></pre>
<h2 id="heading-explicit-expectation">Explicit expectation</h2>
<p>Another big advantage of unit tests is stating the expectations explicitly in the code. For example, the data formatting function <code>shortDate</code> could do one of the following things when provided with an argument that is not a date:</p>
<ul>
<li>throw an error,</li>
<li>return undefined, or</li>
<li>return empty string.</li>
</ul>
<p>Each of those choices could be a good idea in some places, so it could happen that at some point the exact behavior will be changed. I like adding special cases like this to the test, so the future developer will be reminded that some code can depend on specific behavior when they start changing the API.</p>
<p><code>shortDate</code> tests, updated to cover invalid inputs:</p>
<pre><code class="lang-JavaScript">  describe(<span class="hljs-string">"shortDate"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should correctly format date"</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-string">"2023-11-02"</span>);
      expect(shortDate(date)).toEqual(<span class="hljs-string">"2023-11-02"</span>);
    });

    it(<span class="hljs-string">"should fail gracefully for no-dates"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(shortDate(<span class="hljs-string">""</span>)).toEqual(<span class="hljs-string">""</span>);
      expect(shortDate({})).toEqual(<span class="hljs-string">""</span>);
      expect(shortDate(<span class="hljs-number">1</span>)).toEqual(<span class="hljs-string">""</span>);
      expect(shortDate()).toEqual(<span class="hljs-string">""</span>);
    });
  });
</code></pre>
<h2 id="heading-attention-to-edge-cases">Attention to edge cases</h2>
<p>When I write the implementation for a method, I think about the happy path—everything going as expected. When I write unit tests, I think about everything that can go wrong:</p>
<ul>
<li>some arguments missing,</li>
<li>wrong data type, or</li>
<li>invalid combinations or arguments—such as dividing 0 by 0.</li>
</ul>
<p>Covering those edge cases makes the tests really helpful. A few examples form the demo repository:</p>
<p><code>greet</code> tests:</p>
<pre><code class="lang-JavaScript">  describe(<span class="hljs-string">"greet"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should greet by name and surname"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(greet(<span class="hljs-string">"Lorem"</span>, <span class="hljs-string">"Ipsum"</span>)).toEqual(<span class="hljs-string">"Hello Lorem Ipsum!"</span>);
    });

    it(<span class="hljs-string">"should fail gracefully for missing arguments"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(greet(<span class="hljs-string">"Lorem"</span>)).toEqual(<span class="hljs-string">"Hello Lorem!"</span>);
      expect(greet(<span class="hljs-literal">undefined</span>, <span class="hljs-string">"Ipsum"</span>)).toEqual(<span class="hljs-string">"Hello Ipsum!"</span>);
      expect(greet()).toEqual(<span class="hljs-string">"Hello!"</span>);
    });
  });
</code></pre>
<p><code>applyDiscount</code> tests:</p>
<pre><code class="lang-JavaScript">  describe(<span class="hljs-string">"applyDiscount"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should lower the price accordingly"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(applyDiscount(<span class="hljs-number">120</span>, <span class="hljs-number">25</span>)).toEqual(<span class="hljs-number">90</span>);
      expect(applyDiscount(<span class="hljs-number">8</span>, <span class="hljs-number">50</span>)).toEqual(<span class="hljs-number">4</span>);
    });

    it(<span class="hljs-string">"should manage rounding error"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(applyDiscount(<span class="hljs-number">0.1</span>, <span class="hljs-number">40</span>)).toEqual(<span class="hljs-number">0.06</span>);
    });

    it(<span class="hljs-string">"should round results to 0.01"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(applyDiscount(<span class="hljs-number">1.11</span>, <span class="hljs-number">25</span>)).toEqual(<span class="hljs-number">0.83</span>);
    });

    it(<span class="hljs-string">"should return NaN for corrupt inputs"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(applyDiscount(<span class="hljs-string">""</span>, <span class="hljs-number">40</span>)).toBeNaN();
      expect(applyDiscount(<span class="hljs-number">40</span>)).toBeNaN();
      expect(applyDiscount()).toBeNaN();
    });

    it(<span class="hljs-string">"should throw errors on discount percentage outside 0-100 range"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(<span class="hljs-function">() =&gt;</span> applyDiscount(<span class="hljs-number">120</span>, <span class="hljs-number">125</span>)).toThrowError();
      expect(<span class="hljs-function">() =&gt;</span> applyDiscount(<span class="hljs-number">120</span>, <span class="hljs-number">-25</span>)).toThrowError();
    });
  });
</code></pre>
<p><code>calculatePrice</code> tests:</p>
<pre><code class="lang-JavaScript">  describe(<span class="hljs-string">"calculatePrice"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should find a price of many products"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(calculatePrice(<span class="hljs-number">4</span>, <span class="hljs-number">3</span>)).toEqual(<span class="hljs-number">12</span>);
      expect(calculatePrice(<span class="hljs-number">9</span>, <span class="hljs-number">0.5</span>)).toEqual(<span class="hljs-number">4.5</span>);
    });

    it(<span class="hljs-string">"should manage rounding error"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(calculatePrice(<span class="hljs-number">0.1</span>, <span class="hljs-number">0.4</span>)).toEqual(<span class="hljs-number">0.04</span>);
    });

    it(<span class="hljs-string">"should round results to 0.01"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(calculatePrice(<span class="hljs-number">1.11</span>, <span class="hljs-number">0.5</span>)).toEqual(<span class="hljs-number">0.56</span>);
    });

    it(<span class="hljs-string">"should return NaN for corrupt inputs"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(calculatePrice(<span class="hljs-string">""</span>, <span class="hljs-number">40</span>)).toBeNaN();
      expect(calculatePrice(<span class="hljs-number">40</span>)).toBeNaN();
      expect(calculatePrice()).toBeNaN();
    });
  });
</code></pre>
<h2 id="heading-easy-refactoring">Easy refactoring</h2>
<p>Once I have all expectations for my code defined, it’s effortless to refactor it. We can safely reorganize the code, improving the quality while maintaining the behavior. Removing friction from code improvements is where we see plenty of long-term benefits from unit testing. When your team is enabled to improve code without the fear that they will break something, they are more likely to try improving things.</p>
<p>On the flip side, code that nobody can change without causing some unexpected changes is code that is very difficult and risky to improve. Unit tests are often a barrier that prevents code from entering into a spiral of growing complexity and unmaintainability.</p>
<p><code>ellipsis</code> tests are a good example of checking all the behavior we could possibly care about:</p>
<pre><code class="lang-JavaScript">  describe(<span class="hljs-string">"ellipsis"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should shorten long text at 50 chars"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(
        ellipsis(
          <span class="hljs-string">"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa."</span>
        )
      ).toEqual(<span class="hljs-string">"Lorem ipsum dolor sit amet, consectetur adipiscing…"</span>);
    });

    it(<span class="hljs-string">"should leave short text unchanged"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(ellipsis(<span class="hljs-string">"Lorem ipsum sin dolor"</span>)).toEqual(
        <span class="hljs-string">"Lorem ipsum sin dolor"</span>
      );
    });

    it(<span class="hljs-string">"should shorten to custom length"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(ellipsis(<span class="hljs-string">"Lorem ipsum sin dolor"</span>, <span class="hljs-number">10</span>)).toEqual(<span class="hljs-string">"Lorem ipsu…"</span>);
    });

    it(<span class="hljs-string">"should return unchanged non-string argument"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(ellipsis(<span class="hljs-number">11</span>)).toEqual(<span class="hljs-number">11</span>);
      expect(ellipsis({ <span class="hljs-attr">lorem</span>: <span class="hljs-string">"ipsum"</span> })).toEqual({ <span class="hljs-attr">lorem</span>: <span class="hljs-string">"ipsum"</span> });
    });

    it(<span class="hljs-string">"should ignore second argument if not number"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(
        ellipsis(
          <span class="hljs-string">"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa."</span>,
          {}
        )
      ).toEqual(<span class="hljs-string">"Lorem ipsum dolor sit amet, consectetur adipiscing…"</span>);
    });
  });
</code></pre>
<h2 id="heading-summary">Summary</h2>
<p>The cost/benefit balance will depend a lot on the type of project and the team that works on it. For benefits to show, you need a certain quality of tests—and this can be difficult if nobody on your team has experience with building unit tests. The communication benefits are greater when you have a bigger team—so different people work on the code; or when the projects live a long time—so people need a reminder about their past decisions. Long-term benefits of enabled refactoring will appear only if the project exists long enough such that the need for refactoring has a chance to arise.</p>
]]></content:encoded></item><item><title><![CDATA[Pure functions and basic tests in Jasmine]]></title><description><![CDATA[Pure functions are the perfect case for unit testing. For a given input, we always expect the same output—there is no internal state involved. Let’s take a look at a few examples and some simple tests that check if the methods work as expected.
Jasmi...]]></description><link>https://how-to.dev/pure-functions-and-basic-tests-in-jasmine</link><guid isPermaLink="true">https://how-to.dev/pure-functions-and-basic-tests-in-jasmine</guid><category><![CDATA[Testing]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jasmine]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Thu, 08 Feb 2024 22:23:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707430973909/7ea4ea88-9f80-437d-99e6-6d88c0fdd7d2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Pure functions are the perfect case for unit testing. For a given input, we always expect the same output—there is no internal state involved. Let’s take a look at a few examples and some simple tests that check if the methods work as expected.</p>
<h2 id="heading-jasmine">Jasmine</h2>
<p>Jasmine is a unit test framework for JavaScript. It can run tests in both Node.js or on the browser. It’s used in the Angular framework, and it’s especially popular in projects based on Angular. It’s a solid choice for Vanilla JS projects, or projects based on other frameworks as well.</p>
<h2 id="heading-happy-path-testing">Happy path testing</h2>
<p>Happy path testing is when we test a method with inputs that it’s expected to work normally using. The arguments are valid and within reasonable ranges. Those tests check if the method does its job correctly—the test cases should be straightforward examples of how the method is explained in its documentation.</p>
<p>Pseudocode examples:</p>
<ul>
<li><code>expect(add(2, 2)).toBe(4)</code>,</li>
<li><code>expect(concatenate(“Lorem”, “Ipsum”)).toBe(“LoremIpsum”)</code></li>
</ul>
<p>Those tests are meant to automatically catch it anytime the method key behavior is broken.</p>
<h2 id="heading-methods">Methods</h2>
<p>Let’s see a few simple methods: simple operations that we might need in some real-world application.</p>
<p>All implementations are greatly simplified—all methods will break in an ugly way if only we provide them with parameters that differ slightly from what is expected. The code is far from being robust.</p>
<h3 id="heading-greet">greet</h3>
<p>Method that greets the user with their name and surname:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name, surname</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">`Hello <span class="hljs-subst">${name}</span> <span class="hljs-subst">${surname}</span>!`</span>;
}
</code></pre>
<h3 id="heading-shortdate">shortDate</h3>
<p><code>shortDate</code> is a formatting method that takes a date object and returns it formatted as a short string. The code: </p>
<pre><code class="lang-JS"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">shortDate</span>(<span class="hljs-params">date</span>) </span>{
  <span class="hljs-keyword">return</span> date.toISOString().substring(<span class="hljs-number">0</span>, <span class="hljs-number">10</span>);
}
</code></pre>
<h3 id="heading-ellipsis">ellipsis</h3>
<p><code>ellipsis</code> takes a long text string and an optional length parameter and then trims the string to fit within the limit:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ellipsis</span>(<span class="hljs-params">text, length = <span class="hljs-number">50</span></span>) </span>{
  <span class="hljs-keyword">if</span> (text.length &gt; length) {
    <span class="hljs-keyword">return</span> text.substring(<span class="hljs-number">0</span>, length) + <span class="hljs-string">"…"</span>;
  }

  <span class="hljs-keyword">return</span> text;
}
</code></pre>
<h3 id="heading-translate">translate</h3>
<p>A method that provides translated string values for a <code>key</code> and <code>lang</code> pair. It’s a simplified implementation of what could be replaced with more advanced translating libraries.</p>
<pre><code class="lang-JS"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">translate</span>(<span class="hljs-params">key, lang = <span class="hljs-string">"en"</span></span>) </span>{
  <span class="hljs-keyword">switch</span> (lang) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"en"</span>:
      <span class="hljs-keyword">switch</span> (key) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"hello"</span>:
          <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello!"</span>;
      }
    <span class="hljs-keyword">case</span> <span class="hljs-string">"pl"</span>:
      <span class="hljs-keyword">switch</span> (key) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"hello"</span>:
          <span class="hljs-keyword">return</span> <span class="hljs-string">"Cześć!"</span>;
      }
  }
}
</code></pre>
<h3 id="heading-applydiscount">applyDiscount</h3>
<p>Method to apply a percentage discount to a price. It can feel like overkill with this naive implementation, but later when we start investigating edge cases it will get much more interesting.  </p>
<pre><code class="lang-JS"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">applyDiscount</span>(<span class="hljs-params">price, discountPercentage</span>) </span>{
  <span class="hljs-keyword">return</span> price - (price * discountPercentage) / <span class="hljs-number">100</span>;
}
</code></pre>
<h3 id="heading-calculateprice">calculatePrice</h3>
<p>This one calculates the total price when buying multiple units at a given price. It will also get more complicated after adding interesting edge cases.</p>
<pre><code class="lang-JS"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculatePrice</span>(<span class="hljs-params">unitPrice, quantity</span>) </span>{
  <span class="hljs-keyword">return</span> unitPrice * quantity;
}
</code></pre>
<h2 id="heading-complete-js-code">Complete JS code</h2>
<p>The complete JS code, <code>src/main.js</code>:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name, surname</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">`Hello <span class="hljs-subst">${name}</span> <span class="hljs-subst">${surname}</span>!`</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">shortDate</span>(<span class="hljs-params">date</span>) </span>{
  <span class="hljs-keyword">return</span> date.toISOString().substring(<span class="hljs-number">0</span>, <span class="hljs-number">10</span>);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ellipsis</span>(<span class="hljs-params">text, length = <span class="hljs-number">50</span></span>) </span>{
  <span class="hljs-keyword">if</span> (text.length &gt; length) {
    <span class="hljs-keyword">return</span> text.substring(<span class="hljs-number">0</span>, length) + <span class="hljs-string">"…"</span>;
  }

  <span class="hljs-keyword">return</span> text;
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">translate</span>(<span class="hljs-params">key, lang = <span class="hljs-string">"en"</span></span>) </span>{
  <span class="hljs-keyword">switch</span> (lang) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"en"</span>:
      <span class="hljs-keyword">switch</span> (key) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"hello"</span>:
          <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello!"</span>;
      }
    <span class="hljs-keyword">case</span> <span class="hljs-string">"pl"</span>:
      <span class="hljs-keyword">switch</span> (key) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"hello"</span>:
          <span class="hljs-keyword">return</span> <span class="hljs-string">"Cześć!"</span>;
      }
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">applyDiscount</span>(<span class="hljs-params">price, discountPercentage</span>) </span>{
  <span class="hljs-keyword">return</span> price - (price * discountPercentage) / <span class="hljs-number">100</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculatePrice</span>(<span class="hljs-params">unitPrice, quantity</span>) </span>{
  <span class="hljs-keyword">return</span> unitPrice * quantity;
}
</code></pre>
<h2 id="heading-adding-jasmine-tests">Adding Jasmine tests</h2>
<p>To add Jasmine, let’s start by converting the folder into an npm package:</p>
<pre><code>$ npm init -y
Wrote to …/package.json:
…
</code></pre><p>Then we can install the Jasmine package:</p>
<pre><code class="lang-SH">$ npm install --save-dev jasmine

added 42 packages, and audited 43 packages <span class="hljs-keyword">in</span> 2s

13 packages are looking <span class="hljs-keyword">for</span> funding
  run `npm fund` <span class="hljs-keyword">for</span> details

found 0 vulnerabilities
</code></pre>
<p>then we can generate folders and files used by Jasmine:</p>
<pre><code class="lang-SH">$ npx jasmine init
(no output)
</code></pre>
<p>This command generates the following:</p>
<ul>
<li><code>spec/</code>—a folder where we can put <code>*.spec.js</code> files with the test, and</li>
<li><code>spec/support/jasmine.json</code>—a file with the Jasmine config.</li>
</ul>
<h2 id="heading-unit-tests">Unit tests</h2>
<p>For the following unit tests, I’m focusing on the happy path only—I check if the result is as expected for reasonable inputs. The test should be self-explanatory, so let’s take a look at them:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">import</span> {
  greet,
  shortDate,
  ellipsis,
  translate,
  applyDiscount,
  calculatePrice,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../src/main.js"</span>;

describe(<span class="hljs-string">"main"</span>, <span class="hljs-function">() =&gt;</span> {
  describe(<span class="hljs-string">"greet"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should greet by name and surname"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(greet(<span class="hljs-string">"Lorem"</span>, <span class="hljs-string">"Ipsum"</span>)).toEqual(<span class="hljs-string">"Hello Lorem Ipsum!"</span>);
    });
  });

  describe(<span class="hljs-string">"shortDate"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should format correclty date"</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-string">"2023-11-02"</span>);
      expect(shortDate(date)).toEqual(<span class="hljs-string">"2023-11-02"</span>);
    });
  });

  describe(<span class="hljs-string">"shortDate"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should shorten long text at 50 chars"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(
        ellipsis(
          <span class="hljs-string">"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa."</span>
        )
      ).toEqual(<span class="hljs-string">"Lorem ipsum dolor sit amet, consectetur adipiscing…"</span>);
    });

    it(<span class="hljs-string">"should leave short text unchanged"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(ellipsis(<span class="hljs-string">"Lorem ipsum sin dolor"</span>)).toEqual(
        <span class="hljs-string">"Lorem ipsum sin dolor"</span>
      );
    });

    it(<span class="hljs-string">"should shorten to custom length"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(ellipsis(<span class="hljs-string">"Lorem ipsum sin dolor"</span>, <span class="hljs-number">10</span>)).toEqual(<span class="hljs-string">"Lorem ipsu…"</span>);
    });
  });

  describe(<span class="hljs-string">"translate"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should translate to supported langauges"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(translate(<span class="hljs-string">"hello"</span>, <span class="hljs-string">"en"</span>)).toEqual(<span class="hljs-string">"Hello!"</span>);
      expect(translate(<span class="hljs-string">"hello"</span>, <span class="hljs-string">"pl"</span>)).toEqual(<span class="hljs-string">"Cześć!"</span>);
    });
  });

  describe(<span class="hljs-string">"applyDiscount"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should lower the price accordingly"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(applyDiscount(<span class="hljs-number">120</span>, <span class="hljs-number">25</span>)).toEqual(<span class="hljs-number">90</span>);
      expect(applyDiscount(<span class="hljs-number">8</span>, <span class="hljs-number">50</span>)).toEqual(<span class="hljs-number">4</span>);
    });
  });

  describe(<span class="hljs-string">"calculatePrice"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"should find a price of many products"</span>, <span class="hljs-function">() =&gt;</span> {
      expect(calculatePrice(<span class="hljs-number">4</span>, <span class="hljs-number">3</span>)).toEqual(<span class="hljs-number">12</span>);
      expect(calculatePrice(<span class="hljs-number">9</span>, <span class="hljs-number">0.5</span>)).toEqual(<span class="hljs-number">4.5</span>);
    });
  });
});
</code></pre>
<p>(file <code>spec/main.spec.js</code>)</p>
<h2 id="heading-running-tests">Running tests</h2>
<p>To run the tests, we can add the following script to <code>package.json</code>:</p>
<pre><code class="lang-JSON">  ..
  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jasmine"</span>
  },
  …
</code></pre>
<p>With this in place, <code>npm run test</code> runs our tests:</p>
<pre><code>$ npm run test

&gt; testing-example@<span class="hljs-number">1.0</span><span class="hljs-number">.0</span> test
&gt; jasmine

Randomized <span class="hljs-keyword">with</span> seed <span class="hljs-number">76873</span>
Started
........


<span class="hljs-number">8</span> specs, <span class="hljs-number">0</span> failures
Finished <span class="hljs-keyword">in</span> <span class="hljs-number">0.004</span> seconds
Randomized <span class="hljs-keyword">with</span> seed <span class="hljs-number">76873</span> (jasmine --random=<span class="hljs-literal">true</span> --seed=<span class="hljs-number">76873</span>)
</code></pre><h2 id="heading-summary">Summary</h2>
<p>In this post, we took a look at a simple example of JS code and how it can be covered by unit tests. You can find the <a target="_blank" href="https://github.com/how-to-js/testing-example/tree/jasmine-basic">complete code example on GitHub</a>. </p>
]]></content:encoded></item><item><title><![CDATA[How to prepare for a job interview]]></title><description><![CDATA[Let’s say you have a job interview in a few days. How should you prepare for it so that you can make an informed decision about joining the company, as well as make sure that your interests are taken care of?
Prepare your questions
An interview is a ...]]></description><link>https://how-to.dev/how-to-prepare-for-a-job-interview</link><guid isPermaLink="true">https://how-to.dev/how-to-prepare-for-a-job-interview</guid><category><![CDATA[interview]]></category><category><![CDATA[salary]]></category><category><![CDATA[negotiation]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Thu, 01 Feb 2024 10:54:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706784818790/5dffe9c0-ee53-418e-b76c-7d9b90795c24.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let’s say you have a job interview in a few days. How should you prepare for it so that you can make an informed decision about joining the company, as well as make sure that your interests are taken care of?</p>
<h2 id="heading-prepare-your-questions">Prepare your questions</h2>
<p>An interview is a two-way street: it’s not only the company investigating you as a potential employee: in addition, you are investigating the company as a potential employer. Hopefully, you have some other options available—such as staying at your current place or trying out other companies interested in you. In the best case, you’ll have flexibility to decide whether you want to follow through with the company or not.</p>
<p>To learn about the potential employer, you need to ask questions. The question will depend on what’s important for you at the current stage of your career. Some things I would like to know before deciding to join a new company are as follows:</p>
<ul>
<li>What is their development process? If they use some standardized methodology as Scrum, I would like to hear how they implement it. Especially whether they have Scrum Master and Product Owner roles covered—and whether those people are easily reachable. I would also ask if they do retrospectives meetings.</li>
<li>How do they do quality automatization: things such as unit tests, e2e, CI &amp; code-style enforcing? For things that they don't have, I would ask if they would like to see it in the project.</li>
<li>I would ask about their product, and how they do product design/discovery.</li>
<li>Life–work balance questions inspired by <a target="_blank" href="https://www.youtube.com/watch?v=cNbWmjGNZD8&amp;t=1213s">Healthy Software Developer’s video</a>:
<strong> how long do employees usually work?
</strong> how do they deal with emergencies?
** how often is there a need to receive a call or respond to messages outside working hours?</li>
</ul>
<h2 id="heading-salary-negotiation">Salary negotiation</h2>
<p>The point of going to the interview is to get to the salary negotiation. The result of the negotiation will have a great impact on your life for the whole time you spend at the company—it’s a smart move to prepare well. The earlier you start, the better—as you will have more time to investigate, ask questions, and plan your strategy. </p>
<p>The best resource for preparing for an interview in IT is <a target="_blank" href="https://fearlesssalarynegotiation.com/">Fearless Salary Negotiation</a>. You can buy the complete e-book, read the chapters online, or get the key advice from the bite-size articles on the website.</p>
<h3 id="heading-research-compensation">Research compensation</h3>
<p>Before you start negotiation, figure out the current situation at the market. A little bit of time spent on systematic investigation can give you a much more precise picture than anecdotes heard here or there. Check out this <a target="_blank" href="https://fearlesssalarynegotiation.com/book/value/market-value-overview/">chapter on market value estimation</a>.</p>
<h3 id="heading-decide-your-minimum">Decide your minimum</h3>
<p>Great advice is to decide on the  minimum pay that you’ll accept <em>before</em> you start speaking with the company. It could happen that during the various rounds of interviews, they will manage to <em>sell</em> the company very well, or that the effort you have already invested into the company will make you more flexible than you should be. In those cases, having the minimum salary decided ahead of time can be very helpful. <a target="_blank" href="https://fearlesssalarynegotiation.com/book/negotiate/what-is-your-minimum-acceptable-salary/">Relevant chapter from the book here</a>.</p>
<h3 id="heading-think-open-about-your-options">Think open about your options</h3>
<p>As you negotiate with the company, it’s good to be flexible about options you consider. If you are asking for more money than they have budget for, you can propose reduced hours with the same hourly rate that you are happy with. Similarly, commuting to the office can easily take 1–2 hours of your day, so a lower salary could be worth it if it comes with guaranteed remote work.</p>
<h2 id="heading-practice-interview">Practice interview</h2>
<p>Try role-playing an interview with someone. If you can handle it, you can ask them to be tough on you—stricter than what you would expect from a real interview. Ideally, you’ll have a tough, low-stakes interview that would make you relaxed during the real thing.</p>
<h2 id="heading-investigate-the-company">Investigate the company</h2>
<p>Learn about the company—all you can before the meeting, that is. Check their website, their LinkedIn page, and their key employees. Play around with their product if you can. In short, spend an hour or two trying to learn as much as you can about the company. It will help you ask important questions and make a good impression.</p>
<h2 id="heading-summary">Summary</h2>
<p>A bit of preparation can go a long way. As developers, we often think about the technical part of the interview, but learning about the company and preparing for salary negotiation can help us even more. We can filter out companies we shouldn’t join, and we can make sure that we get as good a deal as possible.</p>
]]></content:encoded></item><item><title><![CDATA[How to build a demo project]]></title><description><![CDATA[Creating example projects is a common way of showing your skills to potential employers. Let’s take a look at what’s important to keep in mind when building personal projects with an eye toward impressing prospective employers.
Simplicity
Building ap...]]></description><link>https://how-to.dev/how-to-build-a-demo-project</link><guid isPermaLink="true">https://how-to.dev/how-to-build-a-demo-project</guid><category><![CDATA[projects]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Thu, 25 Jan 2024 08:32:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706266031826/a2d590de-2eb1-4f0b-89ac-d2be9e2d55f4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Creating example projects is a common way of showing your skills to potential employers. Let’s take a look at what’s important to keep in mind when building personal projects with an eye toward impressing prospective employers.</p>
<h2 id="heading-simplicity">Simplicity</h2>
<p>Building applications takes a lot of time and effort. Most projects of any kind are greatly underestimated. There are always unpredictable difficulties that you  encounter only after you start working. Besides that, in the case of personal projects, the project will compete with all the other things that you could be spending your spare time on.</p>
<p>The solution to that problem is to keep the feature set as simple as possible. Even the simplest project proves your ability to deliver and shows how you work and what code you can create. If you can make the application solve some problem, that’s great—but focus on finding the minimal feature scope to address the need.</p>
<p>If you are looking for inspiration for an application to build, in my <a target="_blank" href="https://how-to.dev/oh-my-bill-project-introduction">other article</a> I  present a simple energy usage calculator.</p>
<h2 id="heading-covers-many-aspects">Covers many aspects</h2>
<p>Keeping your feature set small will leave you with time and energy for expanding in another direction—to cover many different aspects of application development. Of all the types of things you can create, it’s always the first of its kind that delivers the most value. For example, demonstrating one class with full unit test coverage shows that you can design testable code, write unit tests, and set up the environment to run them. Writing ten classes would prove your persistence and commitment to the project, but there is a diminishing return on your investment. </p>
<h3 id="heading-idea">Idea</h3>
<p>First and foremost, you need an idea for your project. The scope constraints make it tricky to find something that is simultaneously interesting and simple. A common approach is to either make a simple clone of a known application or to follow somebody’s idea for a demo app.</p>
<p>A more creative approach would be to find a small real-world problem and try to solve it with an application. To keep the scope under control, you should aim for making a <a target="_blank" href="https://en.wikipedia.org/wiki/Minimum_viable_product">minimum viable product</a> (MVP)—the simplest product that addresses the users’ needs.</p>
<p>The nice way to describe your application idea is to write <a target="_blank" href="https://en.wikipedia.org/wiki/User_story">user stories</a>. You could start with a very high-level one:</p>
<blockquote>
<p>As a gym user, I want an application to book training sessions.</p>
</blockquote>
<p>Then you can move down to more precise ones:</p>
<blockquote>
<p>As a gym user, I want to have a page that shows the gym schedule with available spots for each class. I want to be able to book classes that have spaces left.</p>
</blockquote>
<h3 id="heading-mockup">Mockup</h3>
<p>Before you begin in your code editor, it makes sense to draw the interface that you plan to build. You can catch many potential issues by thinking about how exactly things will be presented and how users will transition from one place to another. Working with pen and paper is much faster than working with code, and you can easily make many iterations of your interface in an hour or two.</p>
<p>You can use the mockups to communicate your ideas—as I wrote <a target="_blank" href="https://how-to.dev/how-to-collect-inputs-for-your-project">before</a>. </p>
<h3 id="heading-code-repository">Code repository</h3>
<p>As you start working with code, it makes sense to start a new repository. Git is an important skill for all developers, and it’s worth showing that you are familiar with it and that you follow <a target="_blank" href="https://how-to.dev/how-to-get-the-most-value-out-of-your-git-repository">good practices</a>. At the same time, putting your project on GitHub makes it accessible for others as well—so you show your skills and publish your work at the same time.</p>
<h3 id="heading-communication">Communication</h3>
<p>Communication skills are as important for programmers as technical skills. Your work has no way of impacting others if they cannot understand what your project is supposed to do. Usually, you demonstrate your communication skills in action to the people who interact directly with you. A demo project presents an excellent opportunity to demonstrate your skill to the broader public: the README file.</p>
<p>In the README file, your audience is clear: people interested in your project, most likely other programmers who have no idea about what it does and how it works. Providing this information efficiently will show that you can understand what users want to know and provide them just that. You can see more info about writing README files in a <a target="_blank" href="https://how-to.dev/the-readme-file-how-to-help-others-understand-your-project">guest post on my blog</a>. </p>
<h3 id="heading-prototype">Prototype</h3>
<p>The next step would be to build a clickable interface. Build the screens that you designed with mockups using the technologies you plan to use in your final application. Don’t worry about implementing any functionalities: use hard-coded data and buttons that set values without any logic behind the updates. The goal is to give an impression of a usable application before spending time on building the actual thing.</p>
<p>The benefits of starting with a prototype are two-fold. You will be able to try out the interface or ask others to give it a shot. The feedback from this experience will inform your further work on the application—maybe you will tweak some screens, or you will realize you are missing something. Besides that, at this stage your project will be ready to share as a demo with others: there is not much code in there yet, but one will already be able to see enough of your work to evaluate your skills.</p>
<h3 id="heading-code-quality">Code quality</h3>
<p>With some code ready to go, I recommend you put some code quality checks in place. The most basic verification will be static analysis of your code—checking your code without executing it. A few things that you can set up for your code:</p>
<ul>
<li>linters—Programs that check code for possible issues and recommend best practices. For frontend projects you can use things such as <a target="_blank" href="https://eslint.org/">ESLint</a>, <a target="_blank" href="https://stylelint.io/">Stylelint</a>, <a target="_blank" href="https://htmlhint.com/">HTMLHint</a></li>
<li>code style tools—Programs that enforce a specific formatting for your code. On the frontend, Prettier covers almost all file types you could expect. I already wrote about it <a target="_blank" href="https://how-to.dev/how-to-make-your-code-prettier">on the blog</a></li>
</ul>
<h3 id="heading-vanilla-js">Vanilla JS</h3>
<p>The next step is to implement the features with Vanilla JS alone. You can skip this step if you already know a JS framework well enough to build an application with it. If you don't, Vanilla JS is the safest bet—it’s the foundation that other solutions are using. I have a <a target="_blank" href="https://how-to.dev/how-to-implement-a-basic-javascript-application">simple guide</a> on how to set up a simple JS project with Webpack.</p>
<h3 id="heading-continuous-integration">Continuous Integration</h3>
<p>At this stage, your project will already have scripts:</p>
<ul>
<li>static analysis to ensure the quality and styling of the code, and</li>
<li>a build script that prepares the code for deployment.</li>
</ul>
<p>For each change set, you can expect the codebase to be able to pass both scripts without any errors. You can enforce this expectation by setting up continuous integration (CI). Git hosting providers such as GitHub and GitLab offer CI on even the free plans. You can read more about the benefits <a target="_blank" href="https://how-to.dev/continuous-integration-ci-and-how-it-can-help-you">here</a>.</p>
<h3 id="heading-deployment">Deployment</h3>
<p>With CI in place, the very next step is to deploy your application somewhere. Deploying the application will make it easy for anybody to check out your application in action—after all, people are more likely to click on the link than to download and build code locally. The easiest places to deploy are GitHub Pages, or GitLab Pages—each of them is easy to set up from the repository hosting. For GitLab, I have a <a target="_blank" href="​​https://how-to.dev/how-to-deploy-an-application-to-gitlab-pages">guide on the blog</a>.</p>
<h3 id="heading-framework">Framework</h3>
<p>Finally, with all that in place, you can move your application to your framework of choice. There are many options available, and you should choose one that matches what you would like to learn and what’s needed in your job market.</p>
<p>If your application is indeed small, rewriting it to a framework shouldn’t be a big project—changing a few files from JS+HTML to whatever your frameworks uses. If it’s much more than that, you can rethink the scope of the project and find a smaller set of features to build your MVP. And build the rest <em>after</em> you move your project to the framework.</p>
<h3 id="heading-testing">Testing</h3>
<p>Lastly, to show that you care about the quality of the code you produce, you can add tests to the application. On the front end, we usually consider two levels of testing: unit tests that check the individual parts of the application, and end-to-end tests that interact with the whole app through its user interface. For a professional project, I <a target="_blank" href="https://how-to.dev/does-my-web-application-need-end-to-end-and-unit-tests">recommend using both</a>. For demo projects, unit tests alone should be enough—they are easier to set up and faster to run. </p>
<p>It makes sense to add unit tests <em>after</em> moving to a framework because Vanilla JS code is often difficult to test. Frameworks such as React, Vue, or Angular come with their own unit testing tools and best practices, so you should follow framework-related advice.</p>
<h2 id="heading-good-examples">Good examples</h2>
<p>In my work with <a target="_blank" href="https://how-to.dev/free-mentoring">mentees</a>, I’ve had a chance to see this idea applied in practice.</p>
<h3 id="heading-laundry">Laundry</h3>
<p><a target="_blank" href="https://github.com/gulfaniputra">Gulfani Putra</a> is working on an application that is for laundry services to inform customers about the progress of their order. It’s a practical and simple example: the idea came from inefficiencies that he had seen in local business and that could be addressed with a simple application. If you go to the <a target="_blank" href="https://github.com/gulfaniputra/laundry-app">project page at GitHub</a>, you can see the power of a good README file. By reading it, you will get a pretty good overview of what, why, and how he is building.</p>
<h3 id="heading-hexter">Hexter</h3>
<p><a target="_blank" href="https://github.com/wojcraft">Wojciech Peczyk</a> is building an application that randomly generates a color code: <a target="_blank" href="https://github.com/wojcraft/hexter/tree/main">Hexter</a>. The use case is straightforward to implement, and it allows showcasing all aspects of the project. In the case of features, it’s always possible to add more later on: things such as a button to copy the color to the clipboard, storing previously found colors, etc.</p>
<h2 id="heading-summary">Summary</h2>
<p>Writing a demo project is a great idea to showcase your ability to deliver useful applications. At the same time, it’s a lot of work: more than one expects before starting. That’s why it’s important to keep the feature set small, cover many aspects of the project in it, and make sure you can show it to others before you are completely done with it. If you manage to build a project that touches all aspects covered in this article, you will have a strong demo project to show anybody interested in your skills.</p>
<div class="hn-embed-widget" id="convertkit"></div>]]></content:encoded></item><item><title><![CDATA[How to prepare for a daily stand-up meeting]]></title><description><![CDATA[Like it or not, daily stand-ups are usually a regular, integral part of IT work. In this article, I will share some practical tips and insights on how (as a team member) to prepare for a daily scrum/agile meeting. With this guidance, you will be able...]]></description><link>https://how-to.dev/stand-up-preparation</link><guid isPermaLink="true">https://how-to.dev/stand-up-preparation</guid><category><![CDATA[daily scrum]]></category><category><![CDATA[daily meeting]]></category><category><![CDATA[Standup]]></category><category><![CDATA[Stand Up]]></category><dc:creator><![CDATA[Jan Lipecki]]></dc:creator><pubDate>Thu, 18 Jan 2024 14:06:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705573407969/9c5fe0f7-1921-4a30-bd51-200270976a5e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Like it or not, daily stand-ups are usually a regular, integral part of IT work. In this article, I will share some practical tips and insights on how (as a team member) to prepare for a daily scrum/agile meeting. With this guidance, you will be able to unlock the true potential of your team's morning stand-up (or, if you're a stand-up hater, make them less annoying).</p>
<h1 id="heading-what-is-a-stand-up-meeting">What is a stand-up meeting?</h1>
<p>A daily stand-up meeting (also known as a daily scrum) is a method used in agile software development to facilitate a quick and efficient exchange of information among team members. It typically lasts for about 15 minutes and involves each team member's brief summary of:</p>
<ul>
<li><p>what they accomplished the previous day</p>
</li>
<li><p>what they plan to do today</p>
</li>
<li><p>what kind of blockers they are encountering</p>
</li>
</ul>
<p>So, that’s the general definition. But how does it look in everyday life in IT?</p>
<h1 id="heading-daily-stand-up-expectations-vs-reality">Daily stand-up: Expectations VS reality</h1>
<p>Many people treat daily stand-ups as an opportunity for small talk before the start of actual work. However, this is not the worst-case scenario.</p>
<p>The nature of daily stand-up can be unstable. Instead of being a short, goal-oriented meeting, it can get out of hand and become a lengthy debate about marginal issues. Or quite the opposite: a meeting where everyone unreflectively reads their “to-do” list to others (yes, the infamous “meeting that could've been an email” or Slack message). Besides being a waste of time, this can also lead to a harmful impact on team morale: by frustration, (broadly defined) poor communication, or creating an atmosphere of pressure and control.</p>
<h1 id="heading-why-is-it-worth-it-to-prepare-well-for-daily-stand-ups">Why is it worth it to prepare well for daily stand-ups?</h1>
<p>Fortunately, a morning stand-up doesn't have to look as described above. But before we get into the specific ways to prepare for daily stand-up, let's stop for a second and ask ourselves: why (besides relieving irritation) is it worth doing?</p>
<p><strong>Increased efficiency: your own, as well as the group's.</strong> Knowing what to discuss can help you manage your time effectively during the stand-up. You show that you respect time: your own and other people's.</p>
<p><strong>Better communication among the team members on several levels.</strong> By preparing in advance, you will be able to describe your tasks, problems, and blockers more clearly — which not only helps you to avoid misunderstandings but can also open the floodgates for potential feedback/advice/help. This practice also influences greater transparency and trust within the team. Additionally, <a target="_blank" href="https://how-to.dev/what-should-you-learn-next-as-a-developer">it provides training in soft skills that are priceless in IT</a>.</p>
<p><strong>Improved focus (also outside the meeting).</strong> When you prepare for a stand-up, in a way, you present a more detailed, insightful version of your to-do list. Knowing what difficulties you will face during the day, you can have an effect similar to the "rubber duck method" —  where looking at the problem in your head from different angles can lead to a solution.</p>
<h1 id="heading-strategies-for-effective-stand-up-preparation">Strategies for effective stand-up preparation</h1>
<p>While listening to other team members, I feel I can easily guess whether someone has taken the time to prepare their speech or they are constructing their speech live. A good stand-up status update should be prepared in advance. You don't need much time to do this; 10 minutes before the meeting is enough in most cases.</p>
<p>At the beginning of my speech, I talk about how many tasks I had to deal with (in any way), and how many questions I will have/how many things I would like to discuss more extensively after the status update. </p>
<p>I prepare notes for myself in advance. During my speech, I give information according to the following model:</p>
<ol>
<li><p>The ticket number in the task manager for the task I was somehow supposed to address (so it's easy to find if someone shares the screen during the meeting) and the name of the task (because the number alone will not tell other listeners anything about the subject of a task).</p>
</li>
<li><p>The current status of the task: it is still "in testing", I pushed it forward to "in review", it's already done, I sent it back to "in progress", etc.</p>
</li>
<li><p>Explanation of the reason why this is happening ^.</p>
</li>
</ol>
<p>In this way, I provide an update on all of my tasks one by one. I save the questions for last.</p>
<p>Sometimes, I also like to add information about my level of busyness — for example, that I have nothing more to do, so I am happy to help someone/take over the tasks of others.</p>
<p>EXAMPLES:</p>
<p>Update (“What did you do yesterday?”):</p>
<ul>
<li><p>OP-1526: “[FE] Profile description length validation is not dynamic; error message only appears after form submission”. It was in “Ready for testing”, so I took it and tested it. The bug was still occurring, so I sent it back to “In progress” with an appropriate comment. </p>
</li>
<li><p>OP-1543: “[FE] Inviting a new user by link”. It was in “Ready for testing” so I assigned it to myself and put it “In testing”, but I haven’t started yet. I will start today.</p>
</li>
</ul>
<p>Goals for today:</p>
<ul>
<li>Like I’ve said: today I want to focus on OP-1543: “[FE] Inviting a new user by link”.</li>
</ul>
<p>Blockers:</p>
<ul>
<li>OP-1531 “[FE] [Registration] Registration with unacceptable age (too young)”. I’m still waiting for an answer about the requirements from the Product Owner. I can’t start work without it. </li>
</ul>
<p>Think of preparing for the daily stand-up as an exercise in communication/soft skills. After all, as a tester writing tasks/comments/tickets in Jira (or some other task manager of your choice), you too need to briefly and succinctly describe a given problem/bug — to convey as much relevant information as possible in the least amount of text. In preparing for stand-ups, you practice describing the essence of the problem.</p>
<h1 id="heading-timing-of-your-speech">Timing of your speech</h1>
<p>Remember to adjust the timing of your speech according to the conditions of the meeting. If you don't have a predetermined time to speak, pay attention to the duration of the meeting and the amount of people attending. Based on these facts, try to determine the time of your speech.</p>
<p>It pays to be thorough, but not at the expense of other meeting participants. There is always a risk of going into too much detail. For example, if you have a daily meeting with five people, 2–3 minutes for each is enough — and the whole team will make it in 15 minutes. But if there are ten of you, it is better to aim for 1 minute.</p>
<p>It’s also a good idea to set the time of your speech yourself and try to stick to it. However, it is important not to overdo it — the most important criterion should be the clarity of the message; it's not a race to see who can  report the status of their work the fastest. Practice explaining any complex ideas or issues clearly and concisely. You don't have much time, so make sure the things you're about to say can be understood easily.</p>
<h1 id="heading-final-thoughts">Final thoughts</h1>
<p>Of course, the quality of the stand-ups also largely depends on the person leading the meeting (scrum master, project manager, product owner — you name it). However, it is worth starting the change with yourself. Even if you are the only person on the team applying good practices, it will be much easier for you to start demanding the same from others by demonstrating their effectiveness yourself.</p>
<p>Some of the advice listed here seems trivial, even obvious. I assure you, it's not. Ask yourself: how many people do you know who prepare for the morning stand-up to this extent? </p>
<p>By building the habit of regularly using (even some of) the strategies listed here, you contribute to better conditions in the team — and thus to better results.</p>
<p>Good luck — and have short, concise, and to-the-point stand-ups!</p>
]]></content:encoded></item><item><title><![CDATA[What is version control?]]></title><description><![CDATA[Version control is a basic but integral tool in software development. Many people don’t prioritize it while learning to program and, often, developers only start using it when they start their job. Let’s see what version control is and how it can hel...]]></description><link>https://how-to.dev/what-is-version-control</link><guid isPermaLink="true">https://how-to.dev/what-is-version-control</guid><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Thu, 11 Jan 2024 15:33:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704987223611/b1f5e529-78c2-46b8-88cd-ac2daee1e34a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Version control is a basic but integral tool in software development. Many people don’t prioritize it while learning to program and, often, developers only start using it when they start their job. Let’s see what version control is and how it can help you even before you start working on professional projects.</p>
<h2 id="heading-basics">Basics</h2>
<p>When you program, you’ll have many interconnected files that have to be in a precise state for things to work. In the case of the simplest applications, you can manage files yourself. As the complexity of the application grows, however, the difficulty of tracking the changes grows even faster.</p>
<p>Version control is a tool to manage the state of the codebase. It’s an additional level of control on top of the files stored on the disc. So, along with your files, you have a code repository that stores additional information:</p>
<ul>
<li>previous versions of code,</li>
<li>sets of changes that can be applied, or reverted, together, and</li>
<li>descriptions and metadata for sets of changes.</li>
</ul>
<p>With version control, you can store code snapshots. You can think of it as a sort of ‘save’ for development—a place that you can always return to if you mess up something. Same as in games, saving your progress regularly helps to avoid being forced to do the same task twice.</p>
<h2 id="heading-git">Git</h2>
<p>Currently, Git is the de facto standard for version control in the industry. You can safely assume that it’s all you need as a beginner—with a solid grasp of Git, you will be able to pick any tool that your employee could require you to learn.</p>
<p>Git is a distributed system—in a typical use case, everybody has a complete copy of the repository on their machines. The copies of the repository can be easily synchronized. Usually, you have a central, remote repository that is often called “origin,” and each developer synchronizes with this repository.</p>
<p>The centralized repositories are often hosted by external providers, such as:</p>
<ul>
<li>GitHub,</li>
<li>GitLab,</li>
<li>CodeSummit from AWS,</li>
<li>or others.</li>
</ul>
<h2 id="heading-impact-on-productivity">Impact on productivity</h2>
<p>Let’s see how using version control can improve your productivity. </p>
<h3 id="heading-revert-local-changes">Revert local changes</h3>
<p>The first impact is in having a quick way to revert any changes you’ve made locally. Sometimes you need to change the code in many places to make one change. Without version control, getting back to what was already working could be difficult: imagine having to revert changes to five different files in your code editor. You can be as careful as you want, but occasionally, you will struggle to get back in time—unless you create snapshots of your working application with version control.</p>
<h3 id="heading-integrate-changes-from-many-sources">Integrate changes from many sources</h3>
<p>When you have changes coming from many sources, it can be challenging to get them integrated. Even without changes to the same file, it can be difficult to find what was changed in what files when different developers build different features. Changes to the same file are almost impossible to integrate manually—you would have to check the files line-by-line.</p>
<p>Git tracks all changes separately, and it has a powerful feature of three-way merges: comparing two versions of the file that are being merged and the original state before they diverged. Thanks to this capability, Git can often integrate changes without developer intervention—and I have never seen those automated merges produce invalid code.</p>
<h3 id="heading-restore-past-versions">Restore past versions</h3>
<p>Sometimes, you want to get your code to where it was in the past—Git has you covered. You have many options to achieve this reversion:</p>
<ul>
<li><code>git checkout &lt;version&gt;</code> at some version in the past—so you can see how the code worked at a given point</li>
<li><code>git reset --hard &lt;version&gt;</code>—move your branch to the specific version, dropping changes that have been made since that point</li>
<li><code>git checkout &lt;version&gt; -- &lt;file&gt;</code>—restore a given file to its state in some other version</li>
</ul>
<p>When you’re working on a codebase, those features really come in handy.</p>
<h3 id="heading-history">History</h3>
<p>The longer a project lives and the more changes that occur throughout its life, the more value can be found in its history. Well-maintained history, with well-described, atomic commits can provide insight into why things are the way that they are right now in the codebase. This information can help future developers make informed decisions about code changes. In another article, I wrote about <a target="_blank" href="https://how-to.dev/how-to-get-the-most-value-out-of-your-git-repository">creating a useful Git history</a>. </p>
<h3 id="heading-reverting-some-specific-update">Reverting some specific update</h3>
<p>Git allows you to revert very specific sets of changes with <code>git revert &lt;version&gt;</code>. This command attempts to bring all affected files to the state before the change. It often requires manual conflict resolution, and it adds a new commit to revert the changes. This is another reason why you want your commits to be small, and contain closely related changes.</p>
<h2 id="heading-what-goes-into-the-repository">What goes into the repository?</h2>
<p>Once we have a code repository, we can start using it. Let’s see what things are typically managed with version control.</p>
<h3 id="heading-source-code">Source code</h3>
<p>The source code of our application is the most obvious example. In the case of a website, we will put all the related HTML, JS, CSS, etc. files into the repo. </p>
<p>Code that you maintain is the perfect case for version control. Take the following cases:</p>
<ul>
<li>you need to store the precise state of the files—even an extra comma or a whitespace in one of the files could break the application</li>
<li>the files are text-based, so it’s easy to compare different versions</li>
<li>you manage all the changes—it’s possible to ensure that there is a logical connection between all changes bundled together</li>
</ul>
<h3 id="heading-description-of-dependencies">Description of dependencies</h3>
<p>For the code that you use but don’t maintain, you’ll usually store only information about dependencies. In the case of JavaScript applications, those are <code>package.json</code> and <code>package-lock.json</code> files. The dependencies can be downloaded with a package manager in places where we want to run the code. Then it’s the package manager’s job to make sure the correct versions are installed.</p>
<h3 id="heading-binary-files">Binary files</h3>
<p>There are some binary files that you can expect to appear in your codebase. You can expect media files that are used across the application interface: logos or other images, files with sound effects, etc.</p>
<p>Git can manage binary files, but it's primarily focused on text files. When we store binary files, we cannot enjoy many Git features—such as help with conflict resolution or easy comparison between versions with <code>git diff</code>. Git repositories will store each version of a binary file in an uncompressed way. If you add big files, and will continue changing them often, your repository will grow quickly.</p>
<h2 id="heading-what-stays-out-of-the-repository">What stays out of the repository</h2>
<p>Git is a powerful tool for managing files for your projects, but it’s not the right tool for all your needs. There are specific use cases that are better managed outside of a Git repository. </p>
<h3 id="heading-database">Database</h3>
<p>Many systems require a database to function. In those cases, it could be tempting to keep a database alongside the code inside the repository, but it’s rarely a good idea for various reasons.</p>
<p>The life cycles of data and code changes are very different. With code, you create locally, test on a staging server, and finally deploy to production. With data, you want a different database for each environment, with some changes occasionally traveling across all of them in one direction or another. </p>
<p>Databases are likely to compress the data and store it as binary files—and as we discussed before, those are problematic in Git. The only thing you need for running the application locally is a demo database. You could get this with a special container filled up with the example data, or with a database initialization script that you store in the codebase. Both approaches are more suitable than keeping a database in the repository.</p>
<h3 id="heading-built-code">Built code</h3>
<p>There is no reason to keep your build code in the repository. It’s a binary file, it will take a lot of space, and its value is limited. You can always rebuild it directly from code. For storing build results, you need some other solution as an artifact repository: package registry is one you can get from NPM for node modules and a container repository for things that are deployed with container images.</p>
<h3 id="heading-dependencies">Dependencies</h3>
<p>Adding your dependencies to repo (committing <code>node_modules</code>) has a few big downsides:</p>
<ul>
<li>your repo grows considerably, with code that you mostly leave unchanged,</li>
<li>your commits will become less intelligible—for 100 lines of your own changes, you can get tens of thousands of lines in some 3rd-party libraries, and</li>
<li>some 3rd-party dependencies are installed differently depending on the operating system. It will become harder to share code between OSes with significant differences between them—for example, between Windows and macOS.</li>
</ul>
<h3 id="heading-user-uploads">User uploads</h3>
<p>In the case of websites, the user upload can end up inside the directory tree of your application. This is what I often saw when I was working on PHP websites. Nonetheless, those files don’t belong to your code repository—you need to find another way to manage them, and besides that, make sure you don’t remove them while deploying a new version of the application.</p>
<h2 id="heading-repository-in-action">Repository in action</h2>
<p>Let’s see some examples of a Git repository. You can explore the repositories with your local Git client or on hosting platforms such as GitHub. Let’s take a look at a <a target="_blank" href="https://lodash.com/">lodash</a> repository at GitHub.</p>
<h3 id="heading-codebase">Codebase</h3>
<p>Git provides you a view of any version. The current state the <a target="_blank" href="https://github.com/lodash/lodash/tree/main">repo</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704987169928/d7557ef3-06b9-46d7-8927-cd4b96280077.png" alt="Image description" /></p>
<p>or <a target="_blank" href="https://github.com/lodash/lodash/tree/1.0.0">version 1.0.0</a> 12 years ago:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704987171483/710cca7d-82b6-46eb-bae9-acded6217082.png" alt="Image description" /></p>
<h3 id="heading-tree">Tree</h3>
<p>One of my favorite views—all changes displayed on the commit tree. From <a target="_blank" href="https://github.com/lodash/lodash/commits/main/">main branch</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704987173368/96f16bf6-a21a-4fba-b509-08c75e4ae3ef.png" alt="Image description" /></p>
<h3 id="heading-commit-diff">Commit diff</h3>
<p>You can see the changes that were made in a <a target="_blank" href="https://github.com/lodash/lodash/commit/aa18212085c52fc106d075319637b8729e0f179f">specific commit</a> as a diff to all the files in the project:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704987175021/bf0fdadf-459e-4ec0-8993-0095574fd0e6.png" alt="Image description" /></p>
<h3 id="heading-attribution">Attribution</h3>
<p>If you want to know the author of the last change to a line, you can use the neatly named <code>git blame</code> command, or you can see the <a target="_blank" href="https://github.com/lodash/lodash/blame/1.0.0/package.json">file in blame mode at GitHub</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704987176535/29a8210e-289e-486b-9796-7b885b30f45f.png" alt="Image description" /></p>
<h2 id="heading-summary">Summary</h2>
<p>Version control is a crucial tool in any developer’s toolbox. Not using it guarantees that, eventually, you will waste some time. Learning how to use Git takes effort, but it’s an investment that will pay off hugely when you program—even during your studies or work on personal projects.</p>
]]></content:encoded></item><item><title><![CDATA[Why IT projects are never done]]></title><description><![CDATA[Many projects I have worked on seemed simple at first glance. Nonetheless, there is always something to be done, and there is no end in sight. Usually, it’s not a problem—as long as there is money to finance the development. Let’s take a look at why ...]]></description><link>https://how-to.dev/why-it-projects-are-never-done</link><guid isPermaLink="true">https://how-to.dev/why-it-projects-are-never-done</guid><category><![CDATA[project management]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Fri, 29 Sep 2023 05:47:07 GMT</pubDate><content:encoded><![CDATA[<p>Many projects I have worked on seemed simple at first glance. Nonetheless, there is always something to be done, and there is no end in sight. Usually, it’s not a problem—as long as there is money to finance the development. Let’s take a look at why IT projects are never done.</p>
<h2 id="heading-complexity">Complexity</h2>
<p>Things are always more complicated than they seem at first. Often we have unexpected complexity in two places—the problem we want to solve and the solution itself. As we try to solve the problem, we learn about new aspects that make it more complicated than it looked at first. And the solution that we create often becomes more complicated than necessary. This leads to way slower progress, to the point when the requirements change at the similar rate as the code itself. </p>
<h2 id="heading-technical-surroundings">Technical surroundings</h2>
<p>No project is an island. Any functional piece of code depends on countless things over which we have no control. If you look with perspective long enough—5, 10, or 20 years—anything can change: operating systems, programming languages, or ways the IT economy is running. From a business perspective, plenty of efforts take many years to become profitable.</p>
<p>I started my career in 2008, and over the 15 years since I’ve seen:</p>
<ul>
<li>iOS (2007) and Android (2008) becoming important operating systems,</li>
<li>the appearance of Node.js (2009) and its rise to popularity,</li>
<li>Web platforms overtaking desktop applications,</li>
<li>the growing popularity of JavaScript, and</li>
<li>the disappearance of Flash and Java applets.</li>
</ul>
<p>With changes of this scope, there is no way to create <em>a future-proof</em> project—at some point, you (or your successors) could be forced to rewrite everything on a new stack.</p>
<h3 id="heading-third-party-apis">Third-party APIs</h3>
<p>On a less dramatic scale, your application is likely to use some external providers: for managing payments, sending emails, or any other services. Given enough time, some of those providers will go out of business or rebuild their API and deprecate the version that you are using. Usually, there is some transition period, but it will likely be a few months rather than a few years. In a project with many competing priorities, this can feel like short notice.</p>
<h3 id="heading-legal-requirements">Legal requirements</h3>
<p>Similarly, the legal requirements can change from one year to another. In the EU, we had a big change with VAT and online sales in 2021. For many online companies, that meant plenty of changes in the code. They were forced to start dealing with VAT in every EU country that they were selling to.</p>
<p>The company where I work deals with brick and mortar businesses—we were not affected by online trade regulations. Nonetheless, we had an assumption in the code that there are only 3 levels of VAT—for example 0%, 7%, and 21%. This worked fine for us for a long time. It turned out to be a problem, however, when one of our customers expanded to a new country. Over there, not only were the percentages different, but there were also simply more levels. When you have to change a fundamental assumption like this, you are likely to get an avalanche of changes in your codebase.</p>
<h3 id="heading-code-dependencies">Code dependencies</h3>
<p>A mature JavaScript project has many essential dependencies:</p>
<ul>
<li>the framework it uses</li>
<li>unit test library</li>
<li>end-to-end solution</li>
</ul>
<p>Creators of those tools try to smoothen the upgrade path as much as possible, but they have a trade-off between the ease of upgrade for you and how much they can change. And when the tool is discontinued, moving to a replacement is guaranteed to be a lot of work.</p>
<p>When I started working with AngularJS, Protractor was an impressive end-to-end tool—the best tool available for doing integration testing of angular applications, and probably for any frontend application. Now, 8–9 years later, it’s been a few years since it got an update, and in August 2023, it reached its end-of-life. There are better tools available now, but moving four hundred tests I have on Protractor would be a huge project.</p>
<h2 id="heading-product-discovery">Product discovery</h2>
<p>Product discovery is a nice term that covers the fact that it takes time to find the right combination, where:</p>
<ul>
<li>your customers have a problem,</li>
<li>you can address this problem at scale with an application,</li>
<li>they are willing to pay for using your solution, and</li>
<li>what they pay covers your costs.</li>
</ul>
<p>You can expect this process to take time and many iterations. Some of the iterations will require implementing a feature and then seeing if it's useful to customers, and whether it makes money for the company. As long as the product is used, there will be some ideas worth checking.</p>
<h2 id="heading-how-to-manage-it">How to manage it</h2>
<p>So we know that the IT projects are unlikely to be done—that there will always be some changes that require updates to the code. What can we do about it?</p>
<h3 id="heading-plan-long-term">Plan long term</h3>
<p>There are always dead-lines to be met, but make sure that quarterly goals will not ruin the long-term future. Think about it as a marathon, not a sprint. One thing worth investing time in is code quality. Some compromise and flexibility will be needed, but think about overall architecture, consistency, and best practices of the stack you use. Rushing too much can lead to making a code so difficult to maintain that it will become impossible to make the simplest changes.</p>
<p>Document what you are writing. For a start, maintain a README file with instructions on how to start the project. Write documentation for classes and methods, preferably in a way that makes it easy to extract the documentation—for example, JSDoc.</p>
<p>Write automated tests. Unit tests slow down development when you are learning to test at the same time as you write code. Once you are proficient with testing, developing tests along with your code can be faster than the code alone. When you write code and tests together, you have a quick way to recheck all the edge cases you want to cover.</p>
<h3 id="heading-keep-the-team-around">Keep the team around</h3>
<p>Even with the best effort at documentation, there is a lot of knowledge that is stored only in the minds of your team members. What decisions were made 4 years ago and why; how similar bugs were fixed the last time; what code is responsible for what. Every time a team loses someone, part of this knowledge is irreversibly lost. It’s a shame the industry got to the point where changing jobs often is the best advice for developers. If you can influence that, it would make sense to make sure the devs are happy with the job and the conditions and stay as long as possible.</p>
]]></content:encoded></item><item><title><![CDATA[Why is it difficult to get onboarded on an existing project?]]></title><description><![CDATA[Often, when you start working on a project, you will find yourself struggling with the most basic task: getting it up and running on your machine. This can be a frustrating process, so let’s see what causes those problems and how you can handle it. 
...]]></description><link>https://how-to.dev/why-is-it-difficult-to-get-onboarded-on-an-existing-project</link><guid isPermaLink="true">https://how-to.dev/why-is-it-difficult-to-get-onboarded-on-an-existing-project</guid><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 20 Sep 2023 04:34:09 GMT</pubDate><content:encoded><![CDATA[<p>Often, when you start working on a project, you will find yourself struggling with the most basic task: getting it up and running on your machine. This can be a frustrating process, so let’s see what causes those problems and how you can handle it. </p>
<h2 id="heading-developer-experience">Developer experience</h2>
<p>User experience (UX) focuses on how the user interacts with the system and makes their journey as smooth as possible. Similarly, we could consider developer experience with the system. Usually, in small projects, the priority of improvements that benefit developers is low enough to never be done.</p>
<p>The examples of good developer experience come from large projects and products targeting developers specifically—for example:</p>
<ul>
<li>Cypress for end-to-end testing,</li>
<li>popular frameworks, such as Angular or React, or</li>
<li>GitHub, CircleCI, etc.</li>
</ul>
<p>Small companies, or one-person open-source projects, often lack the resources needed to make your journey pleasant. Simply, if you have to onboard a new developer once a year, it can be cheaper to have them struggle for a bit then to make the installation smooth.</p>
<h2 id="heading-ever-growing-complexity">Ever-growing complexity</h2>
<p>Projects tend to grow in complexity with time. All the time, things are being added:</p>
<ul>
<li>new features</li>
<li>refactorings that take forever to be applied on the whole codebase</li>
<li>dependencies that become outdated</li>
</ul>
<p>If you have a project that lasts for a few years, it will definitely be more complicated than something that would be written now. </p>
<p>The accumulated complexity often spills into troubles with starting up the project: you might find a mismatch of technologies, and they can interact in an unexpected way when you start the project on a new machine. </p>
<h2 id="heading-documentation-challenge">Documentation challenge</h2>
<p>Explaining things in writing can be difficult, but this doesn’t often  receive enough attention. Even if the team you join tries to keep docs of a decent quality, there is always one challenge left: they have to assume some level of knowledge in the reader. There is always a trade-off involved with that—when you explain too much, it will be more work to write and maintain the docs. Moreover, you could flood the reader with too much text. If you explain too little, the documentation will lack crucial information for some people.</p>
<p>Some common examples of things you could struggle with:</p>
<ul>
<li>Plenty of programming (C++, Node.js, Python, Git) and internet tools (Apache, Nginx) come from Unix-based systems—if your background is in Windows, then you will be struggling with some underlying concepts.</li>
<li>Many programming tools are built with the command line interface (CLI) in mind: the most important is Git, but other tools are often important as well—ESLint, Prettier, etc. If you have never used CLI tools, you might have gaps in knowledge that no project documentation will try to address.</li>
</ul>
<p>When I was starting to learn programming, I often got stuck on one or two sentences of the book that described a step I couldn’t overcome. Luckily, as time goes on and you gain experience, cases like this become less common.</p>
<h3 id="heading-unexpected-differences">Unexpected differences</h3>
<p>There can be many differences between your machine and whoever builds the system you’re trying to start now. </p>
<p>Differences in operating systems tend to cause the biggest issues. Linux's distros and macOS are usually compatible enough to be considered one camp. On the other side, we have different versions of Windows. If you join a project that was built on an operating system very different from yours, then you are likely to discover some incompatibles that nobody expected. In JS projects, it’s often expected to be able to run it on whatever OS you like, but it can require some effort to make it truly compatible between systems.</p>
<p>Another surprise can come with the ways of installing tools you need to run the project. For example, last time I checked, Windows had three ways of installing Git—each method doing things slightly differently. Similarly, Node.js or Python can be installed in many ways on Unix systems, and sometimes developers forget about the ways that are different from their preferred one. I always use <a target="_blank" href="https://github.com/nvm-sh/nvm">nvm</a> to manage my Node.js, but it’s not what you find when you go to Node.js website to check for installation guides.</p>
<h3 id="heading-containers-to-the-rescue">Containers to the rescue?</h3>
<p>Containerization, which was made popular with Docker, makes it simpler to move across machines and OSes. Unfortunately, you would still be lucky to have your whole developer journey paved with well-prepared, ready to use images. At my job, I had a good experience using Docker as a shortcut to getting a backend up and running quickly locally. Nonetheless, I still struggle to move the whole developer experience to containers so that everybody has the same dependencies available. Containers are a great tool, but any work at optimizing developer experience faces the same lower priority that we mentioned earlier.</p>
<h2 id="heading-how-to-deal-with-it">How to deal with it</h2>
<p><em>Accept that it will take time</em>. If your team tells you that the setup can be tricky, or that you can expect some issues—trust them, and don’t get frustrated.</p>
<p><em>Ask questions</em>. I’ve seen more devs erring on the side of asking too few questions or too late rather than asking too many or too early. If you don’t want to be annoying, or just want to be somehow independent, set an alarm clock to add an hour or two and ask a question when it rings if you are still stuck. Then you can take your time to describe your issue well, following the <a target="_blank" href="https://how-to.dev/how-to-describe-your-technical-issue">tips</a> I shared previously.</p>
<p><em>Improve the doc</em>. Ultimately, try improving the experience for the next person that will take the same path. The places where you struggled are valuable indicators of where the docs are lacking. Maybe “install Node.js” needs more elaboration with respect to “from where” and “how.” Perhaps you are the first one to run the project on Windows, so you could help others take the same path quicker. In a way, during your installation, you become a beta tester of the documentation, and with everything running, you have enough experience to improve the docs.</p>
<h1 id="heading-what-was-your-experience-with-getting-onboarded-on-a-project">What was your experience with getting onboarded on a project?</h1>
<p>Please share in the comments—I’m truly interested in hearing how it goes for newcomers to projects.</p>
]]></content:encoded></item><item><title><![CDATA[How to write maintainable code: Straightforward logic]]></title><description><![CDATA[Maintaining code is more complicated than writing it. Before you make any changes, you need to understand what is there already, how it was supposed to work, and how it works now. The difficulty of this task will depend on how the code was structured...]]></description><link>https://how-to.dev/how-to-write-maintainable-code-straightforward-logic</link><guid isPermaLink="true">https://how-to.dev/how-to-write-maintainable-code-straightforward-logic</guid><category><![CDATA[Programming Tips]]></category><category><![CDATA[quality]]></category><category><![CDATA[maintainability]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Thu, 07 Sep 2023 11:49:53 GMT</pubDate><content:encoded><![CDATA[<p>Maintaining code is more complicated than writing it. Before you make any changes, you need to understand what is there already, how it was supposed to work, and how it works now. The difficulty of this task will depend on how the code was structured and if it’s an easy read. In this article, I’ll show you how you can make your code more readable and therefore easier to maintain.</p>
<h2 id="heading-obvious-entry-points">Obvious entry points</h2>
<p>When you start a ticket on an application, usually you have some information about where the change or fix should happen. You can make linking that place to the code easier if you consistently use some convention for naming and placing the files. Let’s take a look at a few examples.</p>
<h3 id="heading-component-based-app">Component-based app</h3>
<p>In my day job, I build and maintain a few Angular applications that are built with components. Each application has many routes defined, and for each route there is a top-level component that is responsible for this view. The naming convention we use is as follows:</p>
<ul>
<li>simple route: <code>/home-page</code>—<code>&lt;home-page&gt;</code></li>
<li>nested route: <code>/long/nested-route</code>—<code>&lt;long-nested-route&gt;</code></li>
<li>route with parameter: <code>/user/:id/edit</code>—<code>&lt;user-edit&gt;</code></li>
</ul>
<p>In this way, if I get the route where the changes should happen, I can immediately find related component files.</p>
<h3 id="heading-backend">Backend</h3>
<p>On the backend, we have a few constraints put on the routes we use. The API is loosely inspired by the REST approach, and each endpoint is related to one of the collections that we have in the database. The routes are in a format <code>/collection/operation</code>—for example:</p>
<ul>
<li><code>/users/get</code></li>
<li><code>/transactions/get-report</code></li>
</ul>
<p>The code that is called by those endpoints is organized in files by the collection: so in one file we have methods related to users' collection and in another we have methods related to transactions. In this way, based on the first part of the API route, I know where to look for the code.  </p>
<h2 id="heading-avoid-unnecessary-jumps">Avoid unnecessary jumps</h2>
<p>One of the ways that I often see makes the code complicated is by sending the reader through many unnecessary jumps. When you read code, it’s inevitable that you will need to do some jumps between different parts. This becomes a problem when the jumps are many and unnecessary. Some examples based on what I’ve seen in real-world code:</p>
<ul>
<li>a function that does nothing besides creating an alias for another function</li>
</ul>
<pre><code class="lang-JS"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">A</span>(<span class="hljs-params">param1, param2</span>) </span>{
  <span class="hljs-keyword">return</span> B(param1, param2)
}
</code></pre>
<p>this can make sense for some refactoring, but it would be good to have it in a temporary situation,</p>
<ul>
<li>named callback functions defined away from where they are used:</li>
</ul>
<pre><code class="lang-JS"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">success</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-comment">/*..success..*/</span>}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">error</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-comment">/*..error..*/</span>}

getPromise().then(success, error)
</code></pre>
<p>The same thing would be simpler to read if it were:</p>
<pre><code class="lang-JS">getPromise().then(<span class="hljs-function">() =&gt;</span> { <span class="hljs-comment">/*..success..*/</span>}, <span class="hljs-function">() =&gt;</span> { <span class="hljs-comment">/*..error..*/</span>})
</code></pre>
<ul>
<li>expectations in a test set in variables, away from where they are used:</li>
</ul>
<pre><code class="lang-JS"><span class="hljs-keyword">const</span> expectedObject = { <span class="hljs-comment">/*..some big object..*/</span> };

<span class="hljs-comment">/*..many lines of code..*/</span>

expect(result).toEqual(expectedObject);
</code></pre>
<p>Whenever we have a jump in code, we make it slightly more complicated to read. Let’s make sure that this inconvenience is balanced by some benefit—that there is a good reason to do it this way.</p>
<h2 id="heading-keep-it-simple">Keep it simple</h2>
<p>The flow of your code should be straight. It should be easy to draw a chart of how the logic flows through the application and how things depend on each other. There should be no circular paths in your code, unless you are doing some recursion on purpose.</p>
<p>It should be your goal to be always able to explain how user actions or some external events lead to data changes. If you cannot easily tell what is responsible for what, then it’s very likely your code is chaotic and difficult to follow.</p>
<h2 id="heading-displaying-data">Displaying data</h2>
<p>Of the simple cases is transforming the data for display. It could be one of many things:</p>
<ul>
<li>formatting dates in a user's locale,</li>
<li>translating into user’s language,</li>
<li>combining many properties of an object into one, ready to display string, or</li>
<li>filtering an array based on a search.</li>
</ul>
<p>Each of these operations should have an easily identifiable input and output format and should be written in a form such that a reader knows what goes in and goes out. </p>
<p>Formatting data for display should leave the original untouched—there is no reason to change the data just because it is displayed in some place.</p>
<h2 id="heading-changing-state">Changing state</h2>
<p>When you change the state of your data, it should be possible to easily identify the following parts of the code:</p>
<ul>
<li>source of the change—button that was clicked, the event that occurred in the system, etc.</li>
<li>the change itself—the code that checks the constraints and updates the state of the data</li>
<li>saving the changes to the storage—this could be an update to the database in the case of backend code or calling a save API in the case of the frontend</li>
</ul>
<p>If, for some reason, it’s not easy for you to identify what parts of your code are responsible for some of those points, then reading this code will probably be pretty confusing.</p>
<h2 id="heading-testability">Testability</h2>
<p>All the things we discussed here are consistent with writing testable code. Small, well-defined units with clear responsibilities are easy for developers to understand—and easy to test. For me, writing tests is a good exercise that can teach you to write more readable code: just pay attention when testing starts becoming painful and when the code becomes too convoluted to easily work with. </p>
<h2 id="heading-learn-more">Learn more</h2>
<p>If you are interested in hearing from me when I publish some new material about programming or related topics, you can <a target="_blank" href="https://how-to-dev.ck.page/a5c69742db">sign up for my mailing list</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Writing maintainable code: Data model]]></title><description><![CDATA[In programming, a lot of the challenge is related to organizing data in a structure that makes sense and which helps to solve the problems and facilitates understanding of the code. In this article, I’ll show you what tools you have at your disposal ...]]></description><link>https://how-to.dev/writing-maintainable-code-data-model</link><guid isPermaLink="true">https://how-to.dev/writing-maintainable-code-data-model</guid><category><![CDATA[Programming Tips]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[maintainability]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Fri, 01 Sep 2023 07:45:01 GMT</pubDate><content:encoded><![CDATA[<p>In programming, a lot of the challenge is related to organizing data in a structure that makes sense and which helps to solve the problems and facilitates understanding of the code. In this article, I’ll show you what tools you have at your disposal and how to use them.</p>
<h2 id="heading-building-blocks">Building blocks</h2>
<p>To simplify our discussion, let’s focus on what we have available in JSON—the data format that was created based on how data can be hard-coded in JavaScript. In this way, we don’t need to think about the performance implications of different data structures—we only focus on the usefulness of the data model.</p>
<h3 id="heading-primitive-values">Primitive values</h3>
<p>These are the most basic value types we can have in our program. In JSON, those values are:</p>
<ul>
<li>boolean—a true or false value,</li>
<li>a number—a floating-point value,</li>
<li>string—a sequence of letters, and</li>
<li><code>null</code>—a missing value, which is still useful for expressing certain states.</li>
</ul>
<p>Already with those basic types, we have the possibility of addressing the same thing in different ways. For example, for customer type, you could use some of the following:</p>
<ol>
<li><code>const customerType = “retail”;</code>—which could accept any other string value, both valid or invalid ones</li>
<li><code>const isRetail = true;</code>—a more rigid approach: its two options are obvious and clear, but it has no way of allowing more possibilities</li>
<li><code>const customerType = 2</code>—can be expanded, but requires documentation for understanding what each number means</li>
</ol>
<p>Anything you decide will impact how easy it will be to change code later on. As you are picking the value type for your variable, it’s good practice to try to think about possible changes and pick a type that fits well for both current and future needs. </p>
<h3 id="heading-arrays">Arrays</h3>
<p>Arrays are ordered lists of values. The JavaScript arrays can mix any types of values, for example:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">const</span> someArray = [ <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, “test”, [“another”, “array]];
</code></pre>
<p>Although it is a valid array, mixed types arrays are confusing to work with. It’s way easier to stick to keeping the same types of values in an array.</p>
<p>An important feature of arrays is that they are ordered. This makes them a great match for places where you care about similar data points and where the order is meaningful. For example:</p>
<ul>
<li>products in cart—you definitely want to display items from a cart in the same order; and</li>
<li>students in a class—each one of them has their list number.</li>
</ul>
<p>Arrays work well when you access many values in sequence. It’s less useful when you want to find whether a given value is in an array. When I find myself often using <code>includes()</code> to see if an array has some object I’m looking for, I take it as a potential sign that I should reorganize the data structure.</p>
<h3 id="heading-objects">Objects</h3>
<p>The object is a structure that consists of a set of key–value pairs. The structure is unordered, so it makes it a suitable choice for many places that don’t fit the array. Each value on an object can be understood independently of all the rest, so you can mix different types of values without worry. Example of an object:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">const</span> user = {
  <span class="hljs-attr">login</span>: “lorem.ipsum”,
  <span class="hljs-attr">email</span>: “sin@dolor.com”,
  <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>,
}
</code></pre>
<p>Objects are a good match for collections of named, unordered properties. For example, a set of permissions:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">const</span> hasAccessTo = {
  <span class="hljs-attr">blog</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">blogAdmin</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">userAdmin</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<h3 id="heading-built-in-objects">Built-in objects</h3>
<p>JavaScript provides many object types that you can use on the code side to keep your values in a more suitable form—and with methods that make them more usable. For example:</p>
<ul>
<li><code>Date</code>—for date time values,</li>
<li><code>Set</code>—for unordered collections of unnamed values that don’t repeat, and</li>
<li><code>Symbol</code>—a non-string identifier that will not collide with other values.</li>
</ul>
<p>Those types are very useful, but in communication that goes through a web API that uses JSON to represent data, they all will be serialized to value types described above. In my daily job, where I program business applications, the only types that I use regularly are dates.</p>
<h2 id="heading-pick-the-appropriate-structure">Pick the appropriate structure</h2>
<p>The way we organize data impacts what can be easily done in our code. Let’s take a look at the permission example from above:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">const</span> hasAccessTo = {
  <span class="hljs-attr">blog</span>: <span class="hljs-literal">true</span>,
  …
}
</code></pre>
<p>This value can be used easily in conditional cases such as: <code>if (hasAccessTo.blog)</code>.</p>
<p>The same requirement for a permission list could be met with another data structure:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">const</span> permissions: [{
    <span class="hljs-attr">resource</span>: “blog”,
    <span class="hljs-attr">access</span>: <span class="hljs-literal">true</span>,
  },{
    <span class="hljs-attr">resource</span>: “blogAdmin”,
    <span class="hljs-attr">access</span>: <span class="hljs-literal">true</span>,
  },{
    <span class="hljs-attr">resource</span>: “userAdmin”,
    <span class="hljs-attr">access</span>: <span class="hljs-literal">false</span>,
  },
]
</code></pre>
<p>The same condition from above would need to be replaced by:</p>
<pre><code class="lang-JS"><span class="hljs-keyword">const</span> blogPermission = permissions.find(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> x.resource === ”blog”);

<span class="hljs-keyword">if</span> (blogPermissions?.value) {
…
</code></pre>
<p>This is much harder to read, and it’s easier to write code that will throw errors in some specific cases. By using arrays, the only thing we “gain” is the order of permissions, which shouldn’t matter.</p>
<h2 id="heading-create-a-draft">Create a draft</h2>
<p>There are plenty of things to consider as we organize data in our codebase, and calls can get complicated pretty quickly. To avoid rewriting code, it makes sense to create some form of draft for the structures. In my case, I often describe them with the names I plan to use in the tickets I’m going to work on. Often, when you see your structure design written down, you’ll notice some issues with it.</p>
<h2 id="heading-keep-on-improving">Keep on improving</h2>
<p>The data structure for your code will never be finished—it should keep evolving with your application. Changing names <em>after</em> they appear in many places in code, and in databases, <em>will</em> be painful. However, it is necessary because otherwise the mismatch between names and their current understanding will only grow as things change over time. This is a common source of code debt that often slowly piles up until it makes working with the code an unpleasant and unproductive experience.</p>
<h2 id="heading-learn-more">Learn more</h2>
<p>If you want to receive an occasional email from me about programming or related topics, you can sign up <a target="_blank" href="https://how-to-dev.ck.page/a5c69742db">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to write maintainable code: Naming things]]></title><description><![CDATA[Using the right names is an essential part of writing maintainable code. For a computer, any name will work just fine—they either match or not. For the humans who read the code, the names are the first thing they have in mind as they work on the code...]]></description><link>https://how-to.dev/how-to-write-maintainable-code-naming-things</link><guid isPermaLink="true">https://how-to.dev/how-to-write-maintainable-code-naming-things</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[naming]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 23 Aug 2023 11:36:29 GMT</pubDate><content:encoded><![CDATA[<p>Using the right names is an essential part of writing maintainable code. For a computer, any name will work just fine—they either match or not. For the humans who read the code, the names are the first thing they have in mind as they work on the code. We all have some capacity to deal with a wrong name. If necessary, we can do a mental translation when the name doesn’t match the concept, or we can ignore some typo. But doing so uses both our memory and mental capacities. It’s easier and more efficient to work with the code that has the naming done right.</p>
<h2 id="heading-one-name-for-one-thing">One name for one thing</h2>
<p>For organizing our stuff, the general advice is to have <em>a place for everything and everything in its place</em>. Similarly, our lives will be much easier if all the people involved in the same project use the same terminology. Usually, we developers don’t have a perfect understanding of the domain in which the project is used. As a result, it makes the most sense to learn the terminology that is used by our business colleagues and use it in the code as well.</p>
<h2 id="heading-parts-of-speech">Parts of speech</h2>
<p>To create terminology that is easy to use, it makes sense to apply some of the grammatical knowledge we all got from school. Different types of words fit better in different use cases:</p>
<ul>
<li>nouns are a perfect fit for objects or primitive values: <code>user</code>, <code>accountNumber</code>, <code>customerEmail</code></li>
<li>adjectives work great for some Boolean flags: <code>allowed</code>, <code>disabled</code></li>
<li>verbs match functions or object methods <code>user.login()</code>, <code>shutDown()</code></li>
</ul>
<p>You’ll likely find cases where it would make sense to bend this rule, but for me, it makes sense to try tweaking the names to match this pattern. For example, for a method that checks the current state, I would use <code>user.isActive()</code> instead of  <code>user.active()</code>.</p>
<h2 id="heading-avoid-abbreviation">Avoid abbreviation</h2>
<p>I’m always skeptical of abbreviations as names in code. Many abbreviations are obvious only when you are deep in the context of the code. A reader who is new to the code and the domain can be confused. Making names short doesn’t improve meaningful metrics. When we write code, we usually use code suggestions, and most lines fit on the screen anyway.</p>
<p>When there is potential conflict between brevity and clarity, I always prefer to stay on the side of clarity. The only abbreviation I can think of now that I’m OK with seeing in code is VAT. It’s so commonly used that it is easier to understand than its expanded form: <em>value added tax</em>.</p>
<h2 id="heading-pronunciation">Pronunciation</h2>
<p>All names we put to code are used in two ways. In writing—in code or documentation, and in speech—and when we talk about them. It’s important to think about both use cases when choosing the name. Pronunciation is often another reason to avoid abbreviations: they often miss vowels, and you may need to say it letter by letter.</p>
<h2 id="heading-avoid-name-collisions">Avoid name collisions</h2>
<p>Try not to reuse the names with different meanings in other contexts. If you use some synonyms instead, then it will be easier for developers to intuitively understand the terms correctly when they hear it—without overthinking about the context in which they were used.</p>
<h2 id="heading-brainstorm-ideas">Brainstorm ideas</h2>
<p>I have a high bar for naming things. Some names are easy to create; others are more difficult to come up with. For the most complicated cases, I try to write down as many ideas as I have in the ticket that will introduce a given concept to the code. I try to generate about 3 to 5 ideas—if it’s very difficult, I write down even the ones I don't like. With this in place, I ask my colleagues for their opinion. In this way, I get an external input and spend more time on thinking about the name. It helps in making the decision.</p>
<h2 id="heading-newsletter">Newsletter</h2>
<p>If you want to get occasional emails about programming or related topics, you can <a target="_blank" href="https://how-to-dev.ck.page/a5c69742db">sign up for my newsletter here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to manually test a web API]]></title><description><![CDATA[A few weeks ago, I showed the basic ideas and terminology of web APIs. In this article, I will demonstrate how to apply this knowledge, and try an API with some manual testing.
Tweak query
The easy way to start testing any API is to find an example t...]]></description><link>https://how-to.dev/how-to-manually-test-a-web-api</link><guid isPermaLink="true">https://how-to.dev/how-to-manually-test-a-web-api</guid><category><![CDATA[Web Development]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 16 Aug 2023 06:20:40 GMT</pubDate><content:encoded><![CDATA[<p>A few weeks ago, I showed the <a target="_blank" href="https://how-to.dev/what-you-should-know-about-web-apis">basic ideas and terminology of web APIs</a>. In this article, I will demonstrate how to apply this knowledge, and try an API with some manual testing.</p>
<h2 id="heading-tweak-query">Tweak query</h2>
<p>The easy way to start testing any API is to find an example that works—and then tweak it. You can pick any website and see what requests it does. For example, when you open developer tools in Chrome and reload my blog at <a target="_blank" href="https://how-to.dev/what-is-an-api">how-to.dev</a>, you can see plenty of requests sent by the website:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166774002/18dcd0e4-2935-4a5b-b1f7-167c2ff68d42.png" alt="Image description" /></p>
<p>In the list, we have a few types or requests:</p>
<ul>
<li><em>script</em> or <em>stylesheet</em> with names 4421.a65a… or 6238.6ee7…,</li>
<li><em>fetch</em> with names such as user, tags, events, </li>
<li><em>xhr</em> with name event,</li>
<li>and some other types with resources: <em>svg</em>, <em>avif</em>, <em>font</em>.</li>
</ul>
<p>We are the most interested in <em>fetch</em> and <em>xhr</em> request types. Both could be triggered from the JavaScript side and used for talking to the web API. The other requests we can see here are requests to load some static files—the code or some media content. For each of the queries we see on the list, we can copy one of the formats:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166776490/24335d2f-1d97-448f-9920-b363dbcc654b.png" alt="Image description" /></p>
<p>Copying the code allows you to easily do one of two things:</p>
<ul>
<li>rerun the query exactly as it was done by the application, or</li>
<li>tweak the query to see how the API works with different input.</li>
</ul>
<h3 id="heading-fetch">Fetch</h3>
<p>Fetch is a JavaScript interface to communicate with servers—for example, to talk to a web API. You can read more at <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">MDN</a>. Here we will see our example query:</p>
<pre><code class="lang-JS">fetch(<span class="hljs-string">"https://how-to.dev/api/user"</span>, {
  <span class="hljs-string">"headers"</span>: {
    <span class="hljs-string">"accept"</span>: <span class="hljs-string">"application/json"</span>,
    <span class="hljs-string">"accept-language"</span>: <span class="hljs-string">"en-GB,en-US;q=0.9,en;q=0.8"</span>,
    <span class="hljs-string">"baggage"</span>: <span class="hljs-string">"sentry-environment=vercel-production,sentry-release=736267205a61e0548a85c08aab089d3f1421126b,sentry-transaction=%2F%5B...slug%5D,sentry-public_key=0fbf92e944b8468cb9706e15c488c84e,sentry-trace_id=a2a1dbab6f5b4c619173000812050469,sentry-sample_rate=0"</span>,
    <span class="hljs-string">"content-type"</span>: <span class="hljs-string">"application/json"</span>,
    <span class="hljs-string">"if-none-match"</span>: <span class="hljs-string">"\"as45c9ut8od\""</span>,
    <span class="hljs-string">"sec-ch-ua"</span>: <span class="hljs-string">"\"Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"115\", \"Chromium\";v=\"115\""</span>,
    <span class="hljs-string">"sec-ch-ua-mobile"</span>: <span class="hljs-string">"?0"</span>,
    <span class="hljs-string">"sec-ch-ua-platform"</span>: <span class="hljs-string">"\"macOS\""</span>,
    <span class="hljs-string">"sec-fetch-dest"</span>: <span class="hljs-string">"empty"</span>,
    <span class="hljs-string">"sec-fetch-mode"</span>: <span class="hljs-string">"cors"</span>,
    <span class="hljs-string">"sec-fetch-site"</span>: <span class="hljs-string">"same-origin"</span>,
    <span class="hljs-string">"sentry-trace"</span>: <span class="hljs-string">"a2a1dbab6f5b4c619173000812050469-8d225d0201152147-0"</span>
  },
  <span class="hljs-string">"referrer"</span>: <span class="hljs-string">"https://how-to.dev/what-is-an-api"</span>,
  <span class="hljs-string">"referrerPolicy"</span>: <span class="hljs-string">"origin-when-cross-origin"</span>,
  <span class="hljs-string">"body"</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-string">"method"</span>: <span class="hljs-string">"GET"</span>,
  <span class="hljs-string">"mode"</span>: <span class="hljs-string">"cors"</span>,
  <span class="hljs-string">"credentials"</span>: <span class="hljs-string">"include"</span>
});
</code></pre>
<p>As you can see, there are a lot of details. To run the query, paste this code in the console in dev tools and add <code>.then(console.log)</code> at the end of it. The fetch function returns a promise, and adding <code>console.log</code> as a callback will show us the output right there on the screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166778904/31c7bc47-f77b-4316-8e82-45871a008918.png" alt="Image description" /></p>
<p>You can modify any of the parameters provided to the call, and in this way you can see how the API will behave.</p>
<p>The big advantage of this approach is that you will reuse the credential information already available in your browser. If you have an open session, there will be a cookie in your browser, and it will be sent with your request: in this way, the server will know you are you, and where you should be given access.</p>
<h2 id="heading-get-request">GET request</h2>
<p>Another option to test the API is to put the URL where you want to send your GET request into the address bar. By default, the browser does the GET request to the endpoint and displays  the response on the screen. It will not always work as expected: in some rare cases, the API can be flexible enough to support different formats depending on the query headers. In such a case, it may be that address bar requests show HTML, whereas the API call gets JSON.</p>
<h3 id="heading-demo-api">Demo API</h3>
<p><a target="_blank" href="http://httpbin.org/">Httpbin</a> is an example API we can use for our testing. Its main page is some documentation that shows all the endpoints available for us:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166780902/28341166-ccac-405f-8fc0-da89155c551b.png" alt="Image description" /></p>
<p>Let’s try visiting some of the endpoints directly from the browser.</p>
<h3 id="heading-address-bar">Address bar</h3>
<p>When you open one of the endpoints <a target="_blank" href="http://httpbin.org/uuid">http://httpbin.org/uuid</a> you will get a response similar to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166782842/a3f9aeb5-8993-4913-82e3-c560e27e6ae9.png" alt="Image description" /></p>
<p>You can see more details by opening the dev tools and the network tab. When you refresh the page, you can see all the headers that were sent and received by the browser:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166784846/0d00fd37-369d-4808-9bf4-1249ce464bdc.png" alt="Image description" /></p>
<p>You can use this approach to test GET requests to web APIs.</p>
<h2 id="heading-post-request">POST request</h2>
<p>Creating a POST from scratch is more complicated. You could try writing <code>fetch</code> calls, but as you saw earlier in this article, they can be quite complicated. Let’s use an API testing tool instead.</p>
<h3 id="heading-hoppscotch">Hoppscotch</h3>
<p><a target="_blank" href="https://hoppscotch.io/">Hoppscotch</a> is an API development tool that we can use to send any type of request—POST included. If you’ve heard about Postman, this is an open-source alternative. For the testing, I’ll send a POST request with some JSON data to Httpbin’s POST endpoint. At the initial screen, I set the URL to <code>http://httpbin.org/post</code>, the method to <em>POST</em>. In the <em>Body</em> tab, I set the <em>Content Type</em> to <code>application/json</code> and the <em>Raw Request Body</em> to:</p>
<pre><code class="lang-JSON">{<span class="hljs-attr">"test"</span>: <span class="hljs-number">123</span>}
</code></pre>
<p>Here’s the request just before sending:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166786839/c9e6742f-074d-459c-8ed6-00a1460a688d.png" alt="Image description" /></p>
<p>The initial attempt fails because we are accessing an external server. There are few options to address it, with <em>Proxy</em> being the easiest to get you off the ground:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166788654/a0029f50-98f1-4335-a953-0ead223ba347.png" alt="Image description" /></p>
<p>The result after retrying the request:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692166790547/93ffd231-4a3b-43d8-9384-d49e0a157ae6.png" alt="Image description" /></p>
<p>As you can see, the Httpbin API just returns a bunch  of technical information about the request and the body. </p>
<p>This simple test skips the issue of authorization—many POST requests are only available to the user that is logged in on the server and fail for anonymous users. Covering this concept fully is a topic for another article.</p>
<h2 id="heading-want-to-learn-more">Want to learn more?</h2>
<p>If you are interested in learning more about API or related topics, you can sign up for occasional emails from <a target="_blank" href="https://how-to-dev.ck.page/a5c69742db">my newsletter</a>. </p>
]]></content:encoded></item><item><title><![CDATA[How to build an impressive demo project]]></title><description><![CDATA[When applying for a job, it’s good to have a demo project to present as an example of your work. In this article, I’ll show you what to focus on while building such a project. I share conclusions from being on both sides: applying for a job and revie...]]></description><link>https://how-to.dev/how-to-build-an-impressive-demo-project</link><guid isPermaLink="true">https://how-to.dev/how-to-build-an-impressive-demo-project</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[projects]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 09 Aug 2023 05:31:55 GMT</pubDate><content:encoded><![CDATA[<p>When applying for a job, it’s good to have a demo project to present as an example of your work. In this article, I’ll show you what to focus on while building such a project. I share conclusions from being on both sides: applying for a job and reviewing projects of applicants.</p>
<h2 id="heading-demo-project-goals">Demo project goals</h2>
<p>A demo project is a good opportunity to show off the wide range of your skills. You can do this the best by expanding your project in depth—having a simple set of features for the application but implemented with high-quality code. With a simple feature set, you can focus on showing all the aspects of programming that you would like to work with. With a demo project, you have an empty canvas you can fill in as you please. The only constraints are your creativity, skills, and how much time you want to put into it. You can use it to show the breadth of your knowledge.</p>
<p>While working on a demo project, you don’t have to follow guidelines imposed on you by other developers. You can use this opportunity to show exactly what <em>you</em> mean by good, quality code. Quality is something that good workplaces pay a lot of attention to. Even in places where they say <em>we have no time for quality code</em>, it’s very likely that the technical interviewer will prefer people who can deliver maintainable code.</p>
<p>By delivering a demo project, you prove that you can ship something. Any project that is completed is perfect proof that you both have the skills necessary to create it, and that you are not a perfectionist who can’t finish stuff. Both things will be valued in a workplace.</p>
<h2 id="heading-side-goals">Side goals</h2>
<p>It can be tempting to add some side goals to the project to make the time investment more worthwhile. Depending on your situation, this could indeed be a good idea, but keep in mind that by adding additional priorities, you either water down the original purpose of the project, or you increase the scope of your undertaking. If you are thinking of applying for a job soon, try starting simple with technologies you know and add the new ones later on—if you have time.</p>
<h2 id="heading-project-scope">Project scope</h2>
<p>Building a project from scratch is always a lot of work. Typically, projects go over the initial budget estimation: just look at any construction project in your area. If you follow my advice of demonstrating many of your skills, you will already have a lot of work to do. To avoid starting a project that is bigger than you can finish, the best idea is to keep the feature scope as little as necessary. You can always expand the feature scope in the following iterations—exactly the way you do in agile. If you want some inspiration for simple demo projects, here you have a few examples of what I discussed on this blog:</p>
<ul>
<li>a <a target="_blank" href="https://how-to.dev/oh-my-bill-project-introduction">simple application</a> to store a sequence of data points on energy consumption</li>
<li>a <a target="_blank" href="https://how-to.dev/how-to-collect-inputs-for-your-project">hello world app</a></li>
</ul>
<h3 id="heading-frontend">Frontend</h3>
<p>As a frontend developer, I’m always focusing the most on that part. Even if your priorities are elsewhere, the frontend will be the part of the application the reviewer interacts with, so it makes sense to invest some effort in it.</p>
<p>Depending on your priorities, you can include different qualities to it:</p>
<ul>
<li>If your dream job involves UI/UX design, you can put in the effort to make it pretty. Otherwise, a standard UI framework or even no styled elements will be OK. </li>
<li>If you aim for a frontend job with some framework, you can use this framework in your project. Otherwise, vanilla JS could be an interesting showcase for how you solve some common problems on your own.</li>
</ul>
<h3 id="heading-backend">Backend</h3>
<p>For many applications, you will need some form of backend. Depending on your career goals, you can try some “serverless” backend from the cloud, or build a server for your application yourself. If you aim for full-stack or backend positions, this will be a great exercise. It will complicate a lot of your local and deployment environments, but it will bring your demo application to be much closer to real-world cases. </p>
<p>With backend and frontend work, you will be confronted with many aspects of development that are not present in a project that involves only the frontend. For example:</p>
<ul>
<li>mono-repo vs. poly-repo, a topic I discussed in <a target="_blank" href="https://how-to.dev/pros-and-cons-of-keeping-your-code-in-monorepo">another article</a></li>
<li>true end-to-end tests where you check both parts of the app</li>
</ul>
<p>Covering those aspects in the demo app will be a great way of showing your capacities to the interviewees.</p>
<h3 id="heading-database">Database</h3>
<p>Adding a database to your project would be yet another level of complexity. If you aim for a backend or full-stack job, it would be a great opportunity for you to show your work across all the parts of the stack. When your focus is the frontend, it will probably make more sense to skip the database and just keep data in the server’s memory.</p>
<h2 id="heading-technology-stack">Technology stack</h2>
<p>You will need many technologies to get your project up and running. Make sure to choose things that make sense together: use a combination of technologies that are often used together and avoid adding libraries that overlap with the features they provide.</p>
<p>If possible, try using tools you are familiar with. Learning new things will make you slower in creating the application, and it’s more probable that you will make some mistakes while using it.</p>
<h2 id="heading-what-to-include">What to include</h2>
<p>When I review projects for other people, I focus on whether and how they approach certain aspects, which I discuss below. This list is my personal list, and others will put different weights on those things, but I’ve noticed many senior developers are paying attention to the considerations I mention here. At the same time, some of those things are things ignored by junior developers. </p>
<h3 id="heading-readme">README</h3>
<p>When I visit a project for the first time, I expect a README file that will quickly bring me up to speed with the project. A great example is at <a target="_blank" href="https://github.com/date-fns/date-fns">date-fns</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1691559063237/4fa1dd69-a8dd-4a42-8b84-7932d3024235.png" alt="Image description" /></p>
<p>You can find more about how to write a good README in <a target="_blank" href="https://how-to.dev/the-readme-file-how-to-help-others-understand-your-project">an article</a> on my blog.</p>
<h3 id="heading-deployed-application">Deployed application</h3>
<p>When you try to show what you can build, it makes sense to make it easy for people to see the application in action and play with it. This gives them a context that is helpful to understand the code and will demonstrate the scope of the project. Besides, deploying is a critical part of the project life-cycle, and it makes sense to show you can take care of that too.</p>
<p>If you build only the frontend, the deployment will be effortless: you can use GitHub or GitLab pages, or Netlify. Adding a custom backend or database will require more effort—the easiest would be to find an affordable cloud provider and deploy to the cheapest instances there. I liked the simplicity of the offer from Digital Ocean, but the details of the offering of those companies change every few months.</p>
<h3 id="heading-cicd">CI/CD</h3>
<p>Continuous integration (CI) is a piece of your project’s infrastructure that checks whether everything is working as expected after each commit. Continuous delivery (CD) deploys the last version somewhere that it can be tested: in the case of a demo project, it could be to the main environment because you don’t need to create a production and staging split.</p>
<p>For implementing continuous integration and delivery, you can use an offering of your Git hosting provider: for example, GitHub Actions or GitLab CI/CI. Another option is a dedicated CI service, for example, CircleCI. All those solutions have similar capabilities, and for simple pipelines, it shouldn’t matter much which one you are using.</p>
<p>Setting up CI can be more time-consuming than expected. As you tweak the configuration, you often need to wait for many minutes to see the impact of your changes. Running the code on external machines makes troubleshooting more complicated.</p>
<h3 id="heading-linter">Linter</h3>
<p>Linter is a program that analyzes your code, looking for errors or potentially problematic patterns. Each programming language has some tools like this available. In my frontend work, I use:</p>
<ul>
<li><a target="_blank" href="https://eslint.org/">ESLint</a> for JavaScript and TypeScript code,</li>
<li><a target="_blank" href="https://stylelint.io/">Stylelint</a> for CSS and SCSS, and</li>
<li><a target="_blank" href="https://htmlhint.com/">HTMLHint</a> for HTML.</li>
</ul>
<p>Those tools help to catch little, annoying bugs and teach you what structures in code you should avoid. They often have extensive configuration options, and can be expanded by plugins. I see no reason not to use them in any project, let alone a project where you have to show off your skills and dedication to the craft.</p>
<h3 id="heading-code-style">Code style</h3>
<p>As a developer, you spend more time <em>reading</em> code than writing it. Making the reading experience pleasant is important, and many senior developers insist on keeping the code as consistent as possible. Luckily, we have tools that take care of applying the code style across the project. For the frontend, Prettier is a tool that covers all JS/TS, HTML, and CSS. You can read more about it <a target="_blank" href="https://how-to.dev/how-to-make-your-code-prettier">here</a>.</p>
<h3 id="heading-unit-tests">Unit tests</h3>
<p>The goal of unit tests is to check whether the part of the application—methods, classes, etc. are doing the thing they are supposed to do. There are many tools in JavaScript that you could use for writing unit tests, for example:</p>
<ul>
<li>Jasmine</li>
<li>Jest</li>
<li>Mocha</li>
</ul>
<p>You have probably heard about the importance of unit tests many times before. On my blog, I have 2 related articles: <a target="_blank" href="https://how-to.dev/how-to-write-unit-tests">how to write unit tests</a> for a practical guide, and <a target="_blank" href="https://how-to.dev/what-are-the-benefits-of-unit-testing">what are the benefits of unit tests</a>. </p>
<h3 id="heading-end-to-end-test">End-to-end test</h3>
<p>End-to-end (e2e) tests check that the application works as expected all the way from the frontend through the backend and to the database. Those tests can be complicated to set up because there are plenty of moving parts—frontend, backend, database—and they all should work fine both locally and in the CI setup. Even though it could be difficult to get it right, those tests allow automating a lot of repetitive quality assurance (QA) work. Including them in your demo project can be a great way of showing you care about the quality and efficiency of the development team.</p>
<p>There are many e2e frameworks available: for example, Cypress, Playwright, and Nightwatch. Unless you have a specific reason to prefer some of them, for the demo project, I would use Cypress—it’s the most popular option. Even if the team uses other tools than Cypress, they will definitely recognize it.</p>
<p>If you are new to automated QA, you might wonder what’s the point of having unit and e2e tests in one project. Many teams create both types of tests, and I went through reasons why it makes sense in <a target="_blank" href="https://how-to.dev/does-my-web-application-need-end-to-end-and-unit-tests">another  article</a>.</p>
<h3 id="heading-codebase-documentation">Codebase documentation</h3>
<p>I already mentioned the README file that covers the main purpose of the project, and how to start playing with it. Besides this top-level documentation, it’s very helpful to explain briefly the purpose of the classes and methods you write. The best place to do it is in the code—so you can read and update the description as you work on the files. At the same time, it’s good to have the documentation available in other places too: as suggestions in your code editor or on a website other developers could access without downloading the code.</p>
<p>JSDoc is a popular syntax for adding in-code documentation to JS projects. It integrates with many different tools—good code editors will manage to parse it and use it for code suggesting, or it could be built static.</p>
<h3 id="heading-meaningful-commits">Meaningful commits</h3>
<p>One of the things I pay attention to in projects is the quality of the commit history. A good project history has the changes organized in commits that make sense as a whole and are described in a meaningful way. Well-maintained code history makes it much easier to understand the changes when one reviews code and simpler to look for a reason why something was changed. Small commits, with related changes, are easier to revert if necessary. I wrote more about how to use Git repositories efficiently <a target="_blank" href="https://how-to.dev/how-to-get-the-most-value-out-of-your-git-repository">in a previous blog</a>. </p>
<h2 id="heading-want-to-learn-more">Want to learn more?</h2>
<p>If you are interested in learning more about building projects or other development related things, you can sign up for an occasional email from me <a target="_blank" href="https://how-to-dev.ck.page/a5c69742db">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[What you should know about web APIs]]></title><description><![CDATA[Understanding web application programming interfaces (APIs) is important for many jobs in the tech industry. Backend developers build APIs, frontend developers use them to create applications, and testers check whether they work as expected. There ar...]]></description><link>https://how-to.dev/what-you-should-know-about-web-apis</link><guid isPermaLink="true">https://how-to.dev/what-you-should-know-about-web-apis</guid><category><![CDATA[Testing]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 02 Aug 2023 08:24:08 GMT</pubDate><content:encoded><![CDATA[<p>Understanding web application programming interfaces (APIs) is important for many jobs in the tech industry. Backend developers build APIs, frontend developers use them to create applications, and testers check whether they work as expected. There are many aspects and considerations related to APIs, and it can be all confusing at first. In this article, I’ll show you what things you should know to be able to work with web APIs efficiently.</p>
<h2 id="heading-what-is-a-web-api">What is a web API</h2>
<p>The API is what applications use to communicate with each other. Sometimes, it’s part of the server-client architecture of one system. In that case, a frontend application gets data from a server that is developed and maintained by the same team. In other cases, we have a different company providing access to their systems for external developers. Web APIs are how applications talk to each other over the internet.</p>
<h2 id="heading-http">HTTP</h2>
<p>HTTP is a protocol that is the foundation of the internet—when you open a website, your browser sends a GET request to the address you provided. Most APIs calls done by web applications as they run in the browser are done with HTTP as well. Let’s see the basic concept we have in the protocol.</p>
<h3 id="heading-url">URL</h3>
<p>Every request that we send with HTTP is asking for a specific resource, identified with a uniform resource locator (URL). An example of a URL is <code>https://how-to.dev/what-is-an-api</code>, where we have:</p>
<ul>
<li><code>https</code>—protocol, in this case secure HTTP,</li>
<li><code>how-to.dev</code>—domain, which points to the server that takes care of the resource,</li>
<li><code>what-is-an-api</code>—a resource on that server.</li>
</ul>
<h3 id="heading-request-method">Request method</h3>
<p>Each HTTP request contains a method that explains what the client wants to do with the resource in question. There are 9 methods defined in the protocol—some widely used, others pretty obscure.</p>
<p>When you type a URL into the address bar, your browser will make a GET request to the server and display its output on the screen. GET requests should get an answer from the server, have no side effects, and be safe for caching.</p>
<p>Another common method is POST—it’s sending data <em>to</em> the server and expecting an answer to what was sent. It’s not supposed to be cached because it often alters data on the server. As it allows for two-way communication, it’s very frequently used for web APIs. So when you save a comment on a blog, add a product to a shopping cart, or edit your profile, it’s all most likely going through POST requests.</p>
<p>Some web APIs use the DELETE method for requesting the removal of a given resource and the PUT method for doing updates. Others use POST for all requests that result in changes on the server.</p>
<h3 id="heading-query-parameters">Query parameters</h3>
<p>Query parameters are additional information added at the end of the URL. The query string starts with <code>?</code>, and after that, there are <code>parameter=value</code> pairs separated by <code>&amp;</code>. They are often used in GET requests to pass information to the server.</p>
<p>For example, by doing a GET request to http://geodb-free-service.wirefreethought.com/v1/geo/countries?limit=5&amp;offset=0, you have:</p>
<ul>
<li><code>v1/geo/countries</code> resource at <code>geodb-free-service.wirefreethought.com</code> server,</li>
<li>query string <code>?limit=5&amp;offset=0</code>, which sets <em>limit</em> parameter to <code>5</code>, and <em>offset</em> to <code>0</code>—names commonly used for paginated requests.</li>
</ul>
<h3 id="heading-headers">Headers</h3>
<p>Each HTTP request and response contains additional, technical information in headers. In the case of request headers, a lot of it is added automatically by the browser. The browser adds headers based on its capacities and configuration, previous communication with a given server, and system preference. </p>
<p>Some examples of headers that a browser adds to the requests it sends:</p>
<ul>
<li><code>Accept:</code>—to tell what data type the browser should expect as an answer, such as <code>text/html</code> for HTML files, </li>
<li><code>Accept-Encoding:</code>—to tell in what compression type the browser can deal with, for example <code>gzip, deflate, br</code></li>
<li><code>Accept-Language:</code>—for the language preference, with weights, for example: <code>en-GB,en-US;q=0.9,en;q=0.8</code></li>
</ul>
<p>Other important information passed in headers is cookies. Cookies are set by the client or server, and while they are present, they are added by the browser to each request to a server with a matching domain. Cookies are often used to manage user sessions on the server.</p>
<p>In Chrome’s dev tools, you can see the headers in a long list in the details tab after you click some request you are interested in:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690964580193/ad5bf039-4011-4ddb-9cb8-7ddb92f7cc54.png" alt="Image description" /></p>
<h3 id="heading-response-codes">Response codes</h3>
<p>A response code is a quick way of summarizing the result of the request. There are many codes precisely defined, but the most important are broad categories indicated by the first number of the 3-digit codes:</p>
<ul>
<li><code>1xx</code>—request received, still processing</li>
<li><code>2xx</code>—successful request</li>
<li><code>3xx</code>—resource redirection</li>
<li><code>4xx</code>—client error–the request is invalid</li>
<li><code>5xx</code>—server errors</li>
</ul>
<p>The response codes are used by different layers of the application to decide what to do with the request. A response with status <code>200 OK</code> will be cached by the browser or intermediary server. Status <code>301 Moved Permanetly</code> will cause the browser to repeat the request to the new location.</p>
<p>Any tool that you use for inspecting the request will show it in a prominent place. For example, in Chrome’s dev tools, it is right in the second column in the network tab:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690964582417/c0b32c49-f6d2-4c8f-9cff-99c8486394db.png" alt="Image description" /></p>
<h3 id="heading-response-body">Response body</h3>
<p>In case of successful GET requests, the body contains the resource that the client was asking for. In other cases, it can be the error page—for example, a 404 page for missing content. The simplest way of testing a GET request is to paste the URL in the address bar of a browser. For example, Chrome displays an API response from http://geodb-free-service.wirefreethought.com/v1/geo/countries?limit=5&amp;offset=0 like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690964584857/eaf28f52-4031-4afe-950c-00749cdbc37d.png" alt="Image description" /></p>
<p>For POST requests, there are many different answers that could make sense in the body:</p>
<ul>
<li>some summary of the result of the action that was performed</li>
<li>complete resource after changes that we requested</li>
</ul>
<p>It’s best to check the API documentation to see what is expected. For example, a login call to the European Tertiary Education Register is <a target="_blank" href="https://www.eter-project.com/api/doc/#/User/User_Login">documented</a> to respond like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690964587023/804f4d87-dbf2-4160-bc5c-f4580e6f85e2.png" alt="Image description" /></p>
<h2 id="heading-authorization">Authorization</h2>
<p>Most APIs need to control who gets access to what. Even an API that exposes public data, such as the previously mentioned <a target="_blank" href="http://geodb-cities-api.wirefreethought.com/">GeoDB</a>, can require authorization to limit its usage according to the user’s privilege. Some common approaches to this problem are as follows.</p>
<h3 id="heading-session">Session</h3>
<p>Often in client-server applications, we have a login when the server checks the user + password combination, and a session is created when they match. The session is stored on the server and linked to the user. The session identification is sent back as a cookie and added to every consecutive request. In this way, we exchange the credentials only once, but with every request, the server knows which user is talking to it. Based on this knowledge, it grants or prohibits access to the data.</p>
<h3 id="heading-api-key">API key</h3>
<p>For accessing the 3rd-party API, we often use access keys. It is similar to a password, but we are supposed to add it to every request. Managing API keys in web applications can be tricky because if we send it to the code run by the browsers, it could be retrieved from there and someone could get access to the API in our name. To avoid this risk, we could use a proxy that allows the users with a valid session to access the 3rd-party API, without exposing the key to the outside world.</p>
<h2 id="heading-data-formats">Data formats</h2>
<p>To do successful data exchange, both client and server have to agree on a data format. In some APIs, it could be negotiated with request headers. In others, the server supports only one format, and the client has to adapt to it. There are many options available, but they all serve the same purpose, and most often the communication happens in one of the following formats.</p>
<h3 id="heading-json">JSON</h3>
<p>JavaScript Object Notation—a simple data format, inspired by how to write a hard-coded object in JavaScript. It’s very common in web APIs—it’s easy to parse on the frontend side, and there are plenty of tools available to generate it in server frameworks. The format is verbose and easy for developers to read as well.</p>
<p>An example object looks like this:</p>
<pre><code class="lang-JSON">{
  <span class="hljs-attr">"lorem"</span>: <span class="hljs-string">"ipsum"</span>,
  <span class="hljs-attr">"number"</span>: <span class="hljs-number">12</span>,
  <span class="hljs-attr">"array"</span>: [
    <span class="hljs-string">"sin"</span>,
    <span class="hljs-string">"dolor"</span>
  ]
}
</code></pre>
<h3 id="heading-xml">XML</h3>
<p>Extensible Markup Language is another data format that could be used by an API to transfer data. It can be used on the web, but it’s a bit more of an awkward format than JSON—instead of getting plain objects, we get nested nodes that can have attributes. It became popular much earlier than JSON, so now it’s often used by older applications. </p>
<p>Example XML:</p>
<pre><code class="lang-XML"><span class="hljs-tag">&lt;<span class="hljs-name">lorem</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ipsum</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">sin</span> <span class="hljs-attr">dolor</span>=<span class="hljs-string">"1"</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">sin</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">lorem</span>&gt;</span>
</code></pre>
<h2 id="heading-api-architecture">API architecture</h2>
<p>There are countless ways the API could be structured, and with good documentation, each approach could be equally useful. At the same time, there is a value in reusing good patterns between projects—you can reuse some code, and developers have it easier to switch between projects. Some noteworthy API architectures are below.</p>
<h3 id="heading-rest">REST</h3>
<p>Representational state transfer—its formal definition is well summarized on <a target="_blank" href="https://en.wikipedia.org/wiki/Representational_state_transfer">Wikipedia</a>, but the term is used somehow loosely. A REST API should expose different URLs for different resources and use different request methods for different purposes—GET for loading, POST or PUT for data manipulation, and DELETE for removing. </p>
<p>In REST, the server provides the data in a format it decided relevant, and often we perform many requests for related data, for example:</p>
<ul>
<li>we query <code>/user/123</code> endpoint to get users details,</li>
<li>and we query <code>/orders/?user=123</code> to get all orders placed by the user.</li>
</ul>
<p>Years ago, REST was a buzzword, and REST APIs were seen everywhere—to the point that the term was overused. You even got  <a target="_blank" href="https://en.wikipedia.org/wiki/Richardson_Maturity_Model">models</a> to evaluate how close an API is to the actual REST idea. When I hear some API is RESTful, I assume that there will be different URLs for different resources, and that most likely the data will be available in JSON format. For the rest of the details, I’m checking in the API’s documentation.</p>
<h3 id="heading-graphql">GraphQL</h3>
<p>GraphQL is a language for querying and manipulating the data. It’s well defined, so any API that claims to use it should use it the same way. Some of the differences between it and REST are that all the communication happens at the same URL, and it’s the client that is in charge of deciding what data it needs—combining many related objects in one request. </p>
<p>This approach helps with:</p>
<ul>
<li>limiting the number of requests that go over the network,</li>
<li>limiting the fields that are requested to only what is needed by the application at that moment, and</li>
<li>smoothing the transition when some new fields are added to the object.</li>
</ul>
<p>A short and to-the-point example from the GraphQL’s <a target="_blank" href="https://graphql.org/">website</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690964589106/7a45e22c-6c0f-4ddb-8dc3-8119dce7adf6.png" alt="Image description" /></p>
<h2 id="heading-interested-in-learning-more">Interested in learning more?</h2>
<p>Sign up <a target="_blank" href="https://how-to-dev.ck.page/a5c69742db">here</a> to receive an occasional email with learning resources for programming and related topics.</p>
]]></content:encoded></item><item><title><![CDATA[What is an API?]]></title><description><![CDATA[If you are new to tech, you might be confused by a term that you’ll see all over the place: API. Let’s take a look at what it means, some examples, and how you can use it.
Definition
API is the abbreviation for application programming interface. Thos...]]></description><link>https://how-to.dev/what-is-an-api</link><guid isPermaLink="true">https://how-to.dev/what-is-an-api</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Testing]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 26 Jul 2023 09:19:28 GMT</pubDate><content:encoded><![CDATA[<p>If you are new to tech, you might be confused by a term that you’ll see all over the place: API. Let’s take a look at what it means, some examples, and how you can use it.</p>
<h2 id="heading-definition">Definition</h2>
<p>API is the abbreviation for application programming interface. Those words alone probably don't help much, so let’s see what each of them means here.</p>
<h3 id="heading-application">Application</h3>
<p>Applications are programs that provide some feature(s) to users. They store and retrieve data, perform calculations, etc. Applications give us a reason to use computers at all. The direct usefulness of applications contrasts with programs that we run to access other programs, for example:</p>
<ul>
<li>we use the operating system to open applications, and</li>
<li>we use browsers to access web applications.</li>
</ul>
<h3 id="heading-interface">Interface</h3>
<p>The interface is an exposed part of an application, prepared to receive input from the outside. As a user, you maybe already be familiar with some types of interfaces:</p>
<ul>
<li>graphical user interface (GUI)—the most common interface that we all know from personal computers and mobile devices.</li>
<li>command line interface (CLI)—where the user types a program name and parameters to run a program.</li>
</ul>
<h3 id="heading-programming">Programming</h3>
<p>An API is an interface that is meant to be used by other programs. So, instead of exposing buttons or menus, the application provides a way of interacting with it in a machine-friendly way. Nowadays, it is typically understood as a Web API—an online server that exposes different routes and returns data in a format that is both easy to parse for a computer and understandable for humans. </p>
<p>The name itself doesn’t imply any specific channel of communication—there are other types of APIs as well. On the web platform, we have an ever-growing list of APIs exposed to JavaScript by the browsers. The way of accessing differs, but the method is almost always rather rigid and requires precise interaction with it.</p>
<h2 id="heading-intuition">Intuition</h2>
<p>APIs are simply a way for applications to communicate with each other. Good APIs are stable—because a breaking change in one application will require an update in all applications that use it. And good APIs are documented—because otherwise it’s very difficult to write a program that uses them.</p>
<h2 id="heading-examples">Examples</h2>
<p>Let’s take a look at some examples of APIs that you could play around with.</p>
<h3 id="heading-url">URL</h3>
<p>The URL (uniform resource locator) is a form of an API. As users, we usually use them without thinking much about them. We use a web browser to fetch and display a website from an address that we clicked as a link. With well-designed addresses, we can tweak them and get still get a response from the server:</p>
<ul>
<li>when we replace the <code>Netherlands</code> part of https://en.wikipedia.org/wiki/Netherlands with <code>Belgium</code>, we get a valid URL: https://en.wikipedia.org/wiki/Belgium </li>
<li>Some URLs are organized in a nice hierarchy. If we remove parts of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Numbers_and_dates, we go up to:<ul>
<li>A <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide">list of JavaScript guides</a>,</li>
<li>general <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">JavaScript page</a>,</li>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web">Main page</a> for web platform documentation.</li>
</ul>
</li>
</ul>
<p>A well-designed URL system invites us to tweak the address but will not help much if we ask for a page it doesn’t have. For example, when we replace <code>JavaScript</code> with <code>TypeScript</code>, we get https://developer.mozilla.org/en-US/docs/Web/TypeScript: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690363119470/11028efa-8c33-4db6-8ab7-25b33a7d4680.png" alt="Image description" /></p>
<p>Playing around with URLs can be a simple way of trying out communicating directly with a machine—and getting used to their requirements of providing the parameters in exactly the way they expect.</p>
<h3 id="heading-command-line-programs">Command line programs</h3>
<p>Another simple way of starting with APIs are command line programs. Similarly to web APIs, the first step is to read the documentation. Then, make a few trial and error attempts at getting the program to do what you want it to do. In another article, I provide a simple introduction to <a target="_blank" href="https://how-to.dev/the-hitchhikers-guide-to-the-command-line">CLI programs</a>.</p>
<h3 id="heading-web-api">Web API</h3>
<p>As a tester or a programmer, you are most likely to use a web API. They are relatively easy to use, but there are some difficulties involved:</p>
<ul>
<li>the access can be limited to authorized users—each system will have a different way of authorization and can require creating a user, logging in, providing the session information in cookies or some ID and key pair</li>
<li>without getting too deep, you can do only GET requests—by pasting the API address into the address bar of your browser. The other types of requests (POST or DELETE) will require either getting some specialized program or writing simple JavaScript in the developer tools of your browser.</li>
</ul>
<p>Let’s see some examples of APIs that you could experiment with:</p>
<ul>
<li><a target="_blank" href="https://wiki.openstreetmap.org/wiki/API_v0.6#URL_+_authentication">Open street map</a>,</li>
<li><a target="_blank" href="https://docs.joinmastodon.org/api/guidelines/">Mastodon</a>,</li>
<li><a target="_blank" href="https://en.wikipedia.org/api/rest_v1/#/">Wikipedia</a>.</li>
</ul>
<h2 id="heading-what-you-can-do-with-apis">What you can do with APIs</h2>
<p>The main use of an API is to call other applications from the program you write. You can use them to leverage other systems for any variety of functionalities:</p>
<ul>
<li>OAuth for authorization with 3rd-party providers such as Google for Facebook</li>
<li>getting automated translations from the cloud</li>
<li>getting geolocation from map systems</li>
<li>automatically cross-publishing the same content on many social media platforms</li>
<li>accessing large language models to provide some AI functionality</li>
<li>and many more</li>
</ul>
<p>In a way, a lot of modern programming is writing glue code between different APIs.</p>
<h2 id="heading-how-understanding-apis-helps-you-debug">How understanding APIs helps you debug</h2>
<p>Because so much programming is about calling APIs, there is a lot of troubleshooting that can be done there. Many bugs I created encountered in my frontend programming career were caused by either</p>
<ul>
<li>sending an incorrect request to the API, or</li>
<li>interpreting the response incorrectly.</li>
</ul>
<p>If the frontend sends a valid request and displays the response as it should, then the bug is probably on the backend. If you can troubleshoot that much as a tester, this can significantly speed up finding and fixing the bug.</p>
<h2 id="heading-learn-more">Learn more</h2>
<p>If you are interested in learning more about APIs, programming, and testing, <a target="_blank" href="https://how-to-dev.ck.page/a5c69742db">sign up here</a> for an occasional email from me. </p>
]]></content:encoded></item><item><title><![CDATA[How to figure out the next step in your career]]></title><description><![CDATA[We are all responsible for navigating our careers. In a fast-changing job environment, traditional guidance became either nonexistent or of dubious quality. In my experience, we cannot hope that we will get a viable career plan from:

traditional uni...]]></description><link>https://how-to.dev/how-to-figure-out-the-next-step-in-your-career</link><guid isPermaLink="true">https://how-to.dev/how-to-figure-out-the-next-step-in-your-career</guid><category><![CDATA[Career]]></category><category><![CDATA[mentorship]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 19 Jul 2023 05:27:58 GMT</pubDate><content:encoded><![CDATA[<p>We are all responsible for navigating our careers. In a fast-changing job environment, traditional guidance became either nonexistent or of dubious quality. In my experience, we cannot hope that we will get a viable career plan from:</p>
<ul>
<li>traditional universities,</li>
<li>a company’s development plan, or</li>
<li>family (especially parents) advice.</li>
</ul>
<p>In this article, I’ll show you how you can analyze your career options and create a well-informed plan. </p>
<p>Note! I mean this as an exercise that will take a few hours of thinking about your career, and making real notes that you can review later. </p>
<h2 id="heading-list-your-long-term-options">List your long-term options</h2>
<p>The first step will be to write a list of options you are considering. Someone entering the tech industry could consider technical jobs such as:</p>
<ul>
<li>programming—a common end goal of the transition to IT,</li>
<li>quality assurance (testing), or</li>
<li>data science.</li>
</ul>
<p>Or you might be considering non-technical roles—as a stepping stone toward tech roles or a goal in itself:</p>
<ul>
<li>project or product management</li>
<li>data visualization</li>
<li>user experience (UX) design</li>
<li>customer success specialist</li>
</ul>
<p>As you can see, there are many options available, and many more I forgot about. Writing them down will help you keep them all in mind while analyzing your career steps.</p>
<p>The goal of writing this list is to make it explicit what possibilities you <em>are</em> considering and what possibilities you reject (and why). At the same time, the list will show what options you are not aware of. This will be very helpful later on when looking for external feedback on your plan.</p>
<h2 id="heading-make-a-pros-and-cons-list-for-your-options">Make a pros and cons list for your options</h2>
<p>Once you know what options you are considering, let’s write down what you believe are their pros and cons. There are no good and bad answers here—the goal is to make it explicit what you believe waits for you on each path. You are planning to change your career for some reason, and having your reasoning stated explicitly will make it easy to catch any obvious mistakes or unrealistic expectations.</p>
<h2 id="heading-get-someone-to-validate-your-way-of-thinking">Get someone to validate your way of thinking</h2>
<p>So, after making a list of options you're considering, and making a list of pros and cons for each of them, you are ready to get external help. What you wrote is a perfect launching pad for a very productive conversation with the right person—you can show them a page or two that shows what you’re considering, and what you expect. With that, they will be able to point out any obvious mistakes in your understanding of the career you’re thinking about, or options you could consider as well. </p>
<p>The perfect person would be someone working in the industry you are interested in, someone who is on one of the paths you consider—but a few years ahead of you. You want an insider’s knowledge, but you need to keep in mind that people will know primarily how it was back in their days. </p>
<p>What I described is career mentoring, and many experienced people do it as a pay-it-forward thing, or just for fun. Maybe you already have someone who could help you in your network—try asking around. Alternatively, you can try online platforms to find free mentoring, such as <a target="_blank" href="https://codingcoach.io/">coadingcoach</a>, or look for some paid help.</p>
<h2 id="heading-write-a-plan">Write a plan</h2>
<p>After getting feedback on your expectations, you should have much more clarity about which direction makes the most sense in your situation. This brings us to another writing exercise: creating a plan of action to achieve your goal. It could be something a simple as:</p>
<blockquote>
<p>To become junior JavaScript developer, I’ll:</p>
<ul>
<li>learn git,</li>
<li>follow X course on my framework of choice,</li>
<li>make an example application with … features, unit tests, continues integration, etc.</li>
</ul>
</blockquote>
<p>Or,</p>
<blockquote>
<p>To become testing specialist, I’ll</p>
<ul>
<li>follow a Y course on manual testing,</li>
<li>learn Cypress from Z resource,</li>
<li>list 5 companies I would like to apply to</li>
</ul>
</blockquote>
<p>The plan description doesn't have to be long, but it would be good to make it precise—including links to resources you want to learn from. This will make it easier to evaluate.</p>
<h2 id="heading-evaluate-your-plan">Evaluate your plan</h2>
<p>When you are done with your plan, you are ready to have another productive talk with your mentor. Again, having a document makes it effortless to get up to speed on a lot of information on a complicated topic in a very short time. Half a page plus a few links to courses or books will be enough to cover a half a year of your career development. With this information, it will be easy for your mentor to catch some obvious mistakes. For example, forgetting about Git if you want to become a programmer, or including some tools that you are very unlikely to use together—like Cypress and Playwright for end-to-end testing. </p>
<h2 id="heading-execute">Execute</h2>
<p>Having a good plan is just preparation—now you have to follow through with it. Good mentoring should address your second-guessing of decisions. Your mentor should provide you with enough context for their recommendation that you have clarity on why you do what you do.</p>
<p>Not doubting your plans fixes some source of delays, but not all. In any project, you can expect two things:</p>
<ul>
<li>to underestimate the difficulty of the challenge</li>
<li>to overestimate time you can dedicate to it</li>
</ul>
<p>It’s normal to have a 1-month plan take a few months—especially if you plan to do it on top of a full-time job, keeping up with other responsibilities and a healthy sleep schedule.</p>
<h2 id="heading-free-mentoring">Free mentoring</h2>
<p>If you are interested in analyzing your work plans with me, you can check the <a target="_blank" href="https://how-to.dev/free-mentoring">free mentoring page</a> at my blog.</p>
]]></content:encoded></item><item><title><![CDATA[Job hopping throws a lot of value away. How can we do better as an industry?]]></title><description><![CDATA[I’ve been working for the same client since 2015. 8 years at the same company is way longer than the 2–3 years that you stay in one place while job hopping. Let’s analyze the possibilities we have as developers in our careers.
What is job hopping?
Jo...]]></description><link>https://how-to.dev/job-hopping-throws-a-lot-of-value-away-how-can-we-do-better-as-an-industry</link><guid isPermaLink="true">https://how-to.dev/job-hopping-throws-a-lot-of-value-away-how-can-we-do-better-as-an-industry</guid><category><![CDATA[Career]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 12 Jul 2023 07:06:24 GMT</pubDate><content:encoded><![CDATA[<p>I’ve been working for the same client since 2015. 8 years at the same company is way longer than the 2–3 years that you stay in one place while job hopping. Let’s analyze the possibilities we have as developers in our careers.</p>
<h2 id="heading-what-is-job-hopping">What is job hopping?</h2>
<p>Job hopping is the practice of changing your workplace as often as possible, without looking suspicious on your CV. So, you get a job, learn technologies that the company uses and the internal process and the product they build, and then you start searching for a new job. </p>
<h2 id="heading-advantages-for-employees">Advantages for employees</h2>
<p>Job hopping is often recommended to devs as a way of making sure your compensation is up to the market rate. When you look for a job, you’ll naturally pay a lot of attention to the job market. If you are lucky, you’ll get offers from different companies and make them pitch against each other.</p>
<p>Another advantage is expanding your professional network: when you change companies, or even teams, you can meet new people who work in the industry. If they have a good experience working with you, they can be a valuable connection later on in your career. </p>
<h2 id="heading-value-of-a-long-tenure">Value of a long tenure</h2>
<p>Staying a long time working on the same project is more productive. It can take a few months to get onboarded on a new project, and during this time you need a lot of oversight—or you make a lot of mistakes. Staying long term is an especially good match for companies that maintain and develop their own products. The projects are never ending, and they always need someone around to make sure the necessary changes can be made to the code.</p>
<p>Similarly, even companies that deal with shorter projects benefit from developers staying a long time. With time, you get experience with the technology stack that the company uses, and you can be very productive when some of the projects you built are reopened for updates or maintenance.</p>
<h3 id="heading-institutional-knowledge">Institutional knowledge</h3>
<p>By staying at the same company, you contribute to its institutional knowledge. You remember the past discussions and reasoning behind all the decisions that shaped the current state of the code and the infrastructure. The same goes for the emergencies and the fixes. Something that would take hours for a new person can be just fifteen minutes for you if you remember similar problems from the past. </p>
<h3 id="heading-deep-understanding">Deep understanding</h3>
<p>In time, you develop a better understanding of everything related to your job. You understand the product and how it’s helping the customers. Maybe you met some customer and over the course of that relationship you developed a better picture of the users of the application. You get to know the terminology of the industry in which the product is working, and there is less that has to be explained to you as you start building new features. </p>
<h3 id="heading-knowing-the-code">Knowing the code</h3>
<p>After 8 years in one place, I have an advantage over any other developer: I know a lot about our codebase because I wrote a big part of it. In our repository, I’m an author of more than half of the commits, and at least half of the rest went through a thorough review with me. This knowledge is something specific to the project I work on—were I to change jobs, neither me nor my employer will get any use from it.</p>
<h2 id="heading-sharing-value-of-long-tenure-fairly">Sharing value of long tenure fairly</h2>
<p>So, we have seen the advantages of job hopping for the employees and the value the long tenure has for the companies. Creating a lot of value for the company could be a common goal for both parties—after all, if the pie becomes bigger, there should be more for everybody. To make it work in the long term, both parties need to find a way to share this value fairly so that the employee will not leave.</p>
<h3 id="heading-salary-negotiation">Salary negotiation</h3>
<p>Job hopping feels a bit like a workaround for lack of well-prepared salary negotiation. From the employee perspective, negotiating your salary is stressful:</p>
<ul>
<li>plenty of things depend on it</li>
<li>it can feel closely related to your self-esteem (am I worth the salary I’m asking for?)</li>
<li>at best, we do it every few years</li>
</ul>
<p>At the same time, for the company representatives:</p>
<ul>
<li>they do it often: every time when somebody asks for a raise or applies to the company</li>
<li>the stakes are low—it’s not personal and in most cases they don’t spend their money</li>
<li>they know the market well—they know how much people at the company make, and what salaries new people ask for or accepts</li>
</ul>
<p>This means that you need to prepare well. My go-to recommendation for that are resources from <a target="_blank" href="https://fearlesssalarynegotiation.com/book/raise/">fearless salary negotiation</a>. It’s a good, actionable guide that helped me a lot.</p>
<h4 id="heading-baseline-salary">Baseline salary</h4>
<p>The company you work for knows exactly how much you earn—or for how little you accepted working for them. But there is no reason for your new salary to stay within some relation to your current salary—especially if you were severely underpaid for a long time. Getting a 50% pay raise is not generous, if after it you are still below the market.  </p>
<p>The only reasonable baseline salary is how much people with your experience are paid on the market. You will need to do some basic research to make sure your information is up-to-date: what is paid <em>now</em> for your <em>current</em> skill set. You most likely learned something new since you started your job, and the market changed as well.</p>
<h4 id="heading-best-alternatives">Best alternatives</h4>
<p>While preparing for the negotiations, it’s good to analyze the <em>best alternative to a negotiated agreement</em> for both you and your employer. For company, not reaching a deal with you can mean:</p>
<ul>
<li>having to find someone new <em>for the market value</em> and without your company-specific experience</li>
<li>spending months on searching and onboarding a new employee</li>
<li>if they use a recruitment firm, they will have to pay the fee for people they hire—it can be a few months worth of the new person’s salary</li>
</ul>
<p>For you, the alternative can be as easy as getting back to the original idea of looking for a new job. In that case, you already have some market research done, and you have your negotiation skills refreshed. </p>
<h3 id="heading-reduced-hours">Reduced hours</h3>
<p>Another possibility to find a common ground with your employer is to negotiate working fewer hours, for the same pay. When you ask for a significantly better salary, you will very likely get either a straight no, or some version of “we would love to pay you better, but we have no budget for it”. Working fewer hours is a perfect solution for getting a better rate for you, and not affecting the company budget too much. Because you already know the project well, in the short to mid term, you will always be more productive than a possible replacement that would join for full time. And based on my experience, freeing a few hours or a whole day every week makes more of a difference to the quality of life than money.</p>
<h2 id="heading-when-to-leave-company">When to leave company</h2>
<p>We’ve spent a lot of time thinking about how to stay with the same company. Not all companies are worth the effort. Let’s see a few good reasons to leave:</p>
<ul>
<li>bad atmosphere—company that not only takes your time and energy but hurts your mental health as well</li>
<li>inflexible negotiation—company willing to keep all the surplus of your experience for itself, while using guilt or loyalty to trick you into work for less than fair compensation</li>
<li>getting a much better offer in another place, especially from companies with stronger foundations</li>
</ul>
<h2 id="heading-lets-get-in-touch">Let’s get in touch</h2>
<p>Salary negotiation is one of the topics I often discuss at my free mentoring sessions. If you are interested in analyzing your case, you can check out the <a target="_blank" href="https://how-to.dev/free-mentoring">mentoring page</a> on my website.</p>
]]></content:encoded></item><item><title><![CDATA[What to expect from your first job in programming]]></title><description><![CDATA[Up until recently, work in  tech had a glamorous image online. It was, and is, partially true: there are great companies out there, where employees are well compensated, are not stressed out, and have all the resources they need. It’s likely that you...]]></description><link>https://how-to.dev/what-to-expect-from-your-first-job-in-programming</link><guid isPermaLink="true">https://how-to.dev/what-to-expect-from-your-first-job-in-programming</guid><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 05 Jul 2023 16:50:32 GMT</pubDate><content:encoded><![CDATA[<p>Up until recently, work in  tech had a glamorous image online. It was, and is, partially true: there are great companies out there, where employees are well compensated, are not stressed out, and have all the resources they need. It’s likely that your first job will not be at one of those places. At good companies, people stay there for longer, so the companies don’t need to hire so often. And when they do, often employees will try to bring in someone from their network. As a person starting your career, you are most likely to be hired by an organization that:</p>
<ul>
<li>has conditions that cause a high turnover of employees, and </li>
<li>developers don’t recommend as a workplace to their friends.</li>
</ul>
<p>In short—companies that people leave as soon as they can. Let’s take a look at what you can expect at some of the jobs that are always hiring.</p>
<h2 id="heading-waterfall">Waterfall</h2>
<p>Often, you can find yourself working on projects that are of a fixed scope and fixed price. There is a list of features that the company promises to deliver and the price the customer is paying. Basically, a waterfall project. As soon as there is some unexpected issue, both partners find themselves in a conflict: either price goes up, or scope goes down, or the IT company gives up part of its profit. Such a low-trust environment makes it difficult to build anything besides a small, simple project—no more than a few months of work for a team of just a few people.</p>
<p>On the bright side, you can quickly try and test many different approaches to projects. Languages, technologies, processes, you name it. If you pay attention to what works and what doesn’t, you can get a lot of experience in a short time.</p>
<p>Besides that, there are plenty of downsides. It can be very chaotic, with many projects underway at the same time, distracting you and your colleagues. It can be stressful because spending a bit more time (or being paid for overtime) can mean that the company delivers the project at a loss.</p>
<h2 id="heading-everything-is-cheap">Everything is cheap</h2>
<p>A cheap customer, with their cheap project, will look for some cheap IT service provider. Then the provider will look for some cheap developer to fit into the budget, deliver something that the client accepts and still makes a profit. As a newcomer to the industry, you are likely to accept below-average rates, so that you and a company like this are a “good” match. </p>
<p>To add to this sad image, often because of razor-thin margins, even your workstation can be cheap as well. You will still be expected to stay productive and deliver stuff, so you better learn how to optimize your workflow on a slow, old computer.</p>
<h2 id="heading-low-quality">Low quality</h2>
<p>So, we have rushed projects, done by inexperienced developers on slow computers. You can expect the output’s quality to match that of the input. With projects that are defined for a limited time, it’s very tempting to trade long-term health to speed things up. The things that are likely to suffer first:</p>
<ul>
<li>documentation</li>
<li>testing</li>
<li>code architecture</li>
<li>maintainability</li>
</ul>
<p>It can be especially frustrating if you care about your craft and want to learn how to build good, quality projects that will be able to have a long and healthy life. </p>
<h2 id="heading-a-lot-of-pressure-and-little-support">A lot of pressure and little support</h2>
<p>Another common issue: limited resources, and built-in conflict with the customer, makes it very likely to put pressure on a dev team. Unfortunately, more stress at work is likely to only make things worse: you will make more mistakes as well as waste time and effort. At the same time, an environment like this does not invite code reviews, pair programming, or even helping out your colleagues when they need it. So, you are probably going to get little to no support.</p>
<h2 id="heading-light-at-the-end-of-the-tunnel">Light at the end of the tunnel</h2>
<p>It sounds pretty grim, doesn’t it? Luckily, every month you spend at a company like this, you gain experience, and you get closer to being able to get another, better job. When I was starting my career, I thought there was a trade-off where you get better money, but with worse conditions—longer hours, more stress, etc. Fortunately, for me, the opposite was true: every time I changed work, it was better for both money and general work conditions. It makes sense: if a company has money, it’s better to keep employees productive by not stressing them out, and hiring enough people to keep the workload doable. So, even if your first job in programming isn’t great, you are likely on the way to finding something better. Good luck!</p>
<h2 id="heading-still-interested-in-it">Still interested in IT?</h2>
<p>If you are still interested in starting your programming career, you may find these articles interesting:</p>
<ul>
<li><a target="_blank" href="https://how-to.dev/how-to-do-web-programming-on-an-old-computer">How to do web programming on an old computer</a>,</li>
<li><a target="_blank" href="https://how-to.dev/how-to-get-a-pay-raise-in-it">How to get a pay raise in IT</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to do web programming on an old computer]]></title><description><![CDATA[Programming is a field that doesn't require much financial investment. To start learning or even working as a freelancer, you just need a computer — not even necessarily a powerful one. For many years, I was working on outdated machines, and I found ...]]></description><link>https://how-to.dev/how-to-do-web-programming-on-an-old-computer</link><guid isPermaLink="true">https://how-to.dev/how-to-do-web-programming-on-an-old-computer</guid><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Marcin Wosinek]]></dc:creator><pubDate>Wed, 28 Jun 2023 05:37:46 GMT</pubDate><content:encoded><![CDATA[<p>Programming is a field that doesn't require much financial investment. To start learning or even working as a freelancer, you just need a computer — not even necessarily a powerful one. For many years, I was working on outdated machines, and I found a few tricks that allowed me to stay productive while doing web development.</p>
<h2 id="heading-operating-system-linux">Operating system: Linux</h2>
<p>When I was starting in IT in the 2000s in Poland, the default operating system (OS) was Windows. It was working OK on the new machines, but after a few years and few system updates, most PCs were becoming painfully slow. I hated all the visual bells and whistles that were appearing in the interface with each new OS version: what’s the point of things looking nice if the system is painfully slow?</p>
<p>My solution was switching to Linux. Luckily, all the tools I needed (Apache, PHP, MySQL, Git) were created for Linux, so they were faster and easier to configure there too.</p>
<p>The distribution that worked for me the best was <a target="_blank" href="https://en.wikipedia.org/wiki/Lubuntu">Lubuntu</a>—a lightweight Ubuntu with a desktop interface optimized for older machines. It’s still regularly released, so I would check it out if you are struggling with the speed of your development machine.</p>
<h2 id="heading-command-line-as-an-ide">Command line as an IDE</h2>
<p>To do web development, you need a browser and a code editor. Code editors are often installed as a part of an integrated development environment (IDE). At my first job, I had a bad time trying to use a big, Java-based IDE called Eclipse on an old PC. It was so slow that I was easily distracted while the computer was processing. It was seriously affecting my productivity, so I started searching for faster alternatives.</p>
<p>Part of my job was done over SSH on remote servers, so I developed a workflow based on command line tools. The best part of the command line interface (CLI) is that the tools integrate well by default—you don’t need an IDE to integrate them for you.</p>
<h3 id="heading-tmux">Tmux</h3>
<p>Tmux is a program that allows you to run multiple sessions of a terminal inside one window. With a bit of effort, you can easily create nested sessions, and a script to start it up for you. I found it so easy to work with that</p>
<ul>
<li>I kept using a CLI-based workflow even when I switched to a much faster machine,</li>
<li>I don’t use a second screen: switching between application windows or CLI sessions is efficient enough with keyboard shortcuts to make another screen almost useless. </li>
</ul>
<h3 id="heading-vim">Vim</h3>
<p>Vim is a great command line text editor. Because it’s developed with a keyboard only in mind, every feature is available as a keyboard shortcut. At first, it might give you a headache or two—you will probably have to search how to exit the files. When you invest time in learning it, you will find its interface very efficient. I’ve learned Vim by following about ¼ of the video course <a target="_blank" href="http://derekwyatt.org/vim/tutorials/novice/">here</a> and by occasionally searching for a solution to some problems.</p>
<p>NeoVim is a modern Vim reimplementation. It has a plugin that allows you to use syntax highlighting and suggestions integration from VS Code. The configuration can be tricky at times, but you have access to all the same tools as other code editors.</p>
<h3 id="heading-git">Git</h3>
<p>Git is a key tool for development. The core program has a CLI only. There are some tools promising better user experience with a graphical user interface (GUI), but</p>
<ul>
<li>I was never convinced by those promises, and</li>
<li>performance-wise, you will be the safest using CLI. </li>
</ul>
<h3 id="heading-cli-tools">CLI tools</h3>
<p>Most tools used in programming are developed first for the command line and later integrated into IDEs or get a dedicated GUI. This means that directly from the CLI you can access the same commands that you can from IDE — or sometimes even more commands. The only issue can be typing them in without making mistakes, but you can address this by defining aliases.</p>
<h2 id="heading-low-cost-screen-sharing">Low-cost screen sharing</h2>
<p>I have never done this outside of experiments, but with SSH and Tmux, you can share a CLI session over the internet. It can be especially helpful if your internet connection isn’t stable enough to carry voice and screen sharing. You can find a how-to guide <a target="_blank" href="https://www.hamvocke.com/blog/remote-pair-programming-with-tmux/">here</a>.</p>
<h2 id="heading-learn-more">Learn more</h2>
<p>If you are working on a machine with a lower performance, the articles might also be interesting for you:</p>
<ul>
<li><a target="_blank" href="https://how-to.dev/the-hitchhikers-guide-to-the-command-line">The Hitchhiker’s Guide to the Command Line</a>,</li>
<li><a target="_blank" href="https://how-to.dev/how-to-run-nested-tmux-session">How to run nested tmux session</a>,</li>
<li><a target="_blank" href="https://how-to.dev/how-to-create-tmux-session-with-a-script">How to create Tmux session with a script</a>,</li>
<li><a target="_blank" href="https://how-to.dev/intro-to-the-terminal-basic-commands-that-will-help-you-get-started">Intro to the terminal: basic commands that will help you get started</a>,</li>
<li><a target="_blank" href="https://how-to.dev/why-do-people-use-the-command-line-interface-cli">Why do people use the command-line interface</a></li>
</ul>
]]></content:encoded></item></channel></rss>